feat: Tolerate collector failures (#1769)

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2024-11-25 21:27:31 +01:00
committed by GitHub
parent fd76be38e0
commit 1a4c6c5ce7
121 changed files with 1726 additions and 1221 deletions

View File

@@ -11,7 +11,6 @@ linters:
- exportloopref - exportloopref
- fatcontext - fatcontext
- funlen - funlen
- gochecknoglobals
- gocognit - gocognit
- goconst - goconst
- gocyclo - gocyclo
@@ -88,7 +87,3 @@ issues:
- text: "don't use ALL_CAPS in Go names; use CamelCase" - text: "don't use ALL_CAPS in Go names; use CamelCase"
linters: linters:
- revive - revive
- path: internal/perfdata/v1/
linters:
- godox
- stylecheck

13
.run/all.run.xml Normal file
View File

@@ -0,0 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="all" type="GoApplicationRunConfiguration" factoryName="Go Application" folderName="run">
<module name="windows_exporter" />
<working_directory value="$PROJECT_DIR$" />
<parameters value="--web.listen-address=127.0.0.1:9182 --log.level=debug --collectors.enabled=ad,adcs,adfs,cache,container,cpu,cpu_info,cs,dfsr,dhcp,diskdrive,dns,exchange,filetime,fsrmquota,hyperv,iis,license,logical_disk,logon,memory,mscluster,msmq,mssql,net,netframework,nps,os,pagefile,perfdata,physical_disk,printer,process,remote_fx,scheduled_task,service,smb,smbclient,smtp,system,tcp,terminal_services,textfile,thermalzone,time,udp,update,vmware" />
<sudo value="true" />
<kind value="PACKAGE" />
<package value="github.com/prometheus-community/windows_exporter/cmd/windows_exporter" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/exporter.go" />
<method v="2" />
</configuration>
</component>

View File

@@ -42,6 +42,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/httphandler" "github.com/prometheus-community/windows_exporter/internal/httphandler"
"github.com/prometheus-community/windows_exporter/internal/log" "github.com/prometheus-community/windows_exporter/internal/log"
"github.com/prometheus-community/windows_exporter/internal/log/flag" "github.com/prometheus-community/windows_exporter/internal/log/flag"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus-community/windows_exporter/pkg/collector" "github.com/prometheus-community/windows_exporter/pkg/collector"
"github.com/prometheus/common/version" "github.com/prometheus/common/version"
"github.com/prometheus/exporter-toolkit/web" "github.com/prometheus/exporter-toolkit/web"
@@ -64,6 +65,8 @@ func main() {
} }
func run() int { func run() int {
startTime := time.Now()
app := kingpin.New("windows_exporter", "A metrics collector for Windows.") app := kingpin.New("windows_exporter", "A metrics collector for Windows.")
var ( var (
@@ -191,7 +194,7 @@ func run() int {
enabledCollectorList := expandEnabledCollectors(*enabledCollectors) enabledCollectorList := expandEnabledCollectors(*enabledCollectors)
if err := collectors.Enable(enabledCollectorList); err != nil { if err := collectors.Enable(enabledCollectorList); err != nil {
logger.Error("Couldn't enable collectors", logger.Error("couldn't enable collectors",
slog.Any("err", err), slog.Any("err", err),
) )
@@ -200,11 +203,11 @@ func run() int {
// Initialize collectors before loading // Initialize collectors before loading
if err = collectors.Build(logger); err != nil { if err = collectors.Build(logger); err != nil {
logger.Error("Couldn't load collectors", for _, err := range utils.SplitError(err) {
slog.Any("err", err), logger.Warn("couldn't initialize collector",
) slog.Any("err", err),
)
return 1 }
} }
logCurrentUser(logger) logCurrentUser(logger)
@@ -228,7 +231,7 @@ func run() int {
mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace) mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace)
} }
logger.Info("Starting windows_exporter", logger.Info(fmt.Sprintf("starting windows_exporter in %s", time.Since(startTime)),
slog.String("version", version.Version), slog.String("version", version.Version),
slog.String("branch", version.Branch), slog.String("branch", version.Branch),
slog.String("revision", version.GetRevision()), slog.String("revision", version.GetRevision()),

View File

@@ -16,7 +16,6 @@
package ad package ad
import ( import (
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
@@ -31,6 +30,7 @@ const Name = "ad"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
@@ -671,7 +671,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
data, ok := perfData["NTDS"] data, ok := perfData["NTDS"]
if !ok { if !ok {
return errors.New("perflib query for DirectoryServices (AD) returned empty result set") return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -16,7 +16,6 @@
package adcs package adcs
import ( import (
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
@@ -32,6 +31,7 @@ const Name = "adcs"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
@@ -191,7 +191,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for Certification Authority (ADCS) returned empty result set") return fmt.Errorf("failed to collect Certification Authority (ADCS) metrics: %w", types.ErrNoData)
} }
for name, data := range perfData { for name, data := range perfData {

View File

@@ -16,7 +16,6 @@
package adfs package adfs
import ( import (
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"maps" "maps"
@@ -34,6 +33,7 @@ const Name = "adfs"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
@@ -160,7 +160,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
avgConfigDBQueryTime, avgConfigDBQueryTime,
federationMetadataRequests, federationMetadataRequests,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create AD FS collector: %w", err) return fmt.Errorf("failed to create AD FS collector: %w", err)
} }
@@ -435,13 +435,13 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
instanceKey := slices.Collect(maps.Keys(data)) instanceKey := slices.Collect(maps.Keys(data))
if len(instanceKey) == 0 { if len(instanceKey) == 0 {
return errors.New("perflib query for ADFS returned empty result set") return fmt.Errorf("failed to collect ADFS metrics: %w", types.ErrNoData)
} }
adfsData, ok := data[instanceKey[0]] adfsData, ok := data[instanceKey[0]]
if !ok { if !ok {
return errors.New("perflib query for ADFS returned empty result set") return fmt.Errorf("failed to collect ADFS metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -16,7 +16,6 @@
package cache package cache
import ( import (
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
@@ -31,6 +30,7 @@ const Name = "cache"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for Perflib Cache metrics. // A Collector is a Prometheus Collector for Perflib Cache metrics.
@@ -322,7 +322,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
cacheData, ok := data[perfdata.InstanceEmpty] cacheData, ok := data[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("perflib query for Cache returned empty result set") return fmt.Errorf("failed to collect Cache metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -33,6 +33,7 @@ const Name = "container"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for containers metrics. // A Collector is a Prometheus Collector for containers metrics.

View File

@@ -32,6 +32,7 @@ const Name = "cpu"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {

View File

@@ -32,6 +32,7 @@ const Name = "cpu_info"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor. // A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor.
@@ -147,6 +148,11 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
nil, nil,
) )
var dst []miProcessor
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }

View File

@@ -29,6 +29,7 @@ const Name = "cs"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.

View File

@@ -53,5 +53,5 @@ const (
databaseLookupsTotal = "Database Lookups" databaseLookupsTotal = "Database Lookups"
usnJournalRecordsReadTotal = "USN Journal Records Read" usnJournalRecordsReadTotal = "USN Journal Records Read"
usnJournalRecordsAcceptedTotal = "USN Journal Records Accepted" usnJournalRecordsAcceptedTotal = "USN Journal Records Accepted"
usnJournalUnreadPercentage = "USN Journal Records Unread Percentage" usnJournalUnreadPercentage = "USN Journal Unread Percentage"
) )

View File

@@ -35,6 +35,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{"connection", "folder", "volume"}, CollectorsEnabled: []string{"connection", "folder", "volume"},
} }
@@ -542,7 +543,7 @@ func (c *Collector) collectPDHConnection(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for DFS Replication Connections returned empty result set") return fmt.Errorf("failed to collect DFS Replication Connections metrics: %w", types.ErrNoData)
} }
for name, connection := range perfData { for name, connection := range perfData {
@@ -620,7 +621,7 @@ func (c *Collector) collectPDHFolder(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for DFS Replicated Folders returned empty result set") return fmt.Errorf("failed to collect DFS Replicated Folders metrics: %w", types.ErrNoData)
} }
for name, folder := range perfData { for name, folder := range perfData {
@@ -824,7 +825,7 @@ func (c *Collector) collectPDHVolume(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for DFS Replication Volumes returned empty result set") return fmt.Errorf("failed to collect DFS Replication Volumes metrics: %w", types.ErrNoData)
} }
for name, volume := range perfData { for name, volume := range perfData {

View File

@@ -16,7 +16,6 @@
package dhcp package dhcp
import ( import (
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
@@ -31,6 +30,7 @@ const Name = "dhcp"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector perflib DHCP metrics. // A Collector is a Prometheus Collector perflib DHCP metrics.
@@ -288,7 +288,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
data, ok := perfData[perfdata.InstanceEmpty] data, ok := perfData[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("perflib query for DHCP Server returned empty result set") return fmt.Errorf("failed to collect DHCP Server metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -31,6 +31,7 @@ const Name = "diskdrive"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive. // A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive.
@@ -119,6 +120,11 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
nil, nil,
) )
var dst []diskDrive
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }
@@ -133,6 +139,7 @@ type diskDrive struct {
Availability uint16 `mi:"Availability"` Availability uint16 `mi:"Availability"`
} }
//nolint:gochecknoglobals
var ( var (
allDiskStatus = []string{ allDiskStatus = []string{
"OK", "OK",

View File

@@ -16,7 +16,6 @@
package dns package dns
import ( import (
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
@@ -31,6 +30,7 @@ const Name = "dns"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics.
@@ -284,7 +284,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
data, ok := perfData[perfdata.InstanceEmpty] data, ok := perfData[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("perflib query for DNS returned empty result set") return fmt.Errorf("failed to collect DNS metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -47,6 +47,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{ CollectorsEnabled: []string{
adAccessProcesses, adAccessProcesses,

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -73,7 +72,7 @@ func (c *Collector) collectActiveSync(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange ActiveSync returned empty result set") return fmt.Errorf("failed to collect MSExchange ActiveSync metrics: %w", types.ErrNoData)
} }
for _, data := range perfData { for _, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -89,7 +88,7 @@ func (c *Collector) collectADAccessProcesses(ch chan<- prometheus.Metric) error
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange ADAccess Processes returned empty result set") return fmt.Errorf("failed to collect MSExchange ADAccess Processes metrics: %w", types.ErrNoData)
} }
labelUseCount := make(map[string]int) labelUseCount := make(map[string]int)

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -53,7 +52,7 @@ func (c *Collector) collectAutoDiscover(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange Autodiscover returned empty result set") return fmt.Errorf("failed to collect MSExchange Autodiscover metrics: %w", types.ErrNoData)
} }
for _, data := range perfData { for _, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -53,7 +52,7 @@ func (c *Collector) collectAvailabilityService(ch chan<- prometheus.Metric) erro
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange Availability Service returned empty result set") return fmt.Errorf("failed to collect MSExchange Availability Service metrics: %w", types.ErrNoData)
} }
for _, data := range perfData { for _, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -97,7 +96,7 @@ func (c *Collector) collectHTTPProxy(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange HttpProxy Service returned empty result set") return fmt.Errorf("failed to collect MSExchange HttpProxy Service metrics: %w", types.ErrNoData)
} }
for name, data := range perfData { for name, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -57,7 +56,7 @@ func (c *Collector) collectMapiHttpEmsmdb(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange MapiHttp Emsmdb returned empty result set") return fmt.Errorf("failed to collect MSExchange MapiHttp Emsmdb metrics: %w", types.ErrNoData)
} }
for _, data := range perfData { for _, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -65,7 +64,7 @@ func (c *Collector) collectOWA(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange OWA returned empty result set") return fmt.Errorf("failed to collect MSExchange OWA metrics: %w", types.ErrNoData)
} }
for _, data := range perfData { for _, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -97,7 +96,7 @@ func (c *Collector) collectRPC(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange RpcClientAccess returned empty result set") return fmt.Errorf("failed to collect MSExchange RpcClientAccess metrics: %w", types.ErrNoData)
} }
for _, data := range perfData { for _, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -201,7 +200,7 @@ func (c *Collector) collectTransportQueues(ch chan<- prometheus.Metric) error {
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchangeTransport Queues returned empty result set") return fmt.Errorf("failed to collect MSExchangeTransport Queues metrics: %w", types.ErrNoData)
} }
for name, data := range perfData { for name, data := range perfData {

View File

@@ -16,7 +16,6 @@
package exchange package exchange
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -89,7 +88,7 @@ func (c *Collector) collectWorkloadManagementWorkloads(ch chan<- prometheus.Metr
} }
if len(perfData) == 0 { if len(perfData) == 0 {
return errors.New("perflib query for MSExchange WorkloadManagement Workloads returned empty result set") return fmt.Errorf("failed to collect MSExchange WorkloadManagement Workloads metrics: %w", types.ErrNoData)
} }
for name, data := range perfData { for name, data := range perfData {

View File

@@ -36,6 +36,7 @@ type Config struct {
FilePatterns []string FilePatterns []string
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
FilePatterns: []string{}, FilePatterns: []string{},
} }

View File

@@ -31,6 +31,7 @@ const Name = "fsrmquota"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
@@ -142,30 +143,32 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
nil, nil,
) )
var dst []msftFSRMQuota
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }
// MSFT_FSRMQuota docs: // MSFT_FSRMQuota docs:
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
type MSFT_FSRMQuota struct { type msftFSRMQuota struct {
Name string `mi:"Name"` Path string `mi:"Path"`
PeakUsage uint64 `mi:"PeakUsage"`
Path string `mi:"Path"` Size uint64 `mi:"Size"`
PeakUsage uint64 `mi:"PeakUsage"` Usage uint64 `mi:"Usage"`
Size uint64 `mi:"Size"` Description string `mi:"Description"`
Usage uint64 `mi:"Usage"` Template string `mi:"Template"`
Description string `mi:"Description"` Disabled bool `mi:"Disabled"`
Template string `mi:"Template"` MatchesTemplate bool `mi:"MatchesTemplate"`
// Threshold string `mi:"Threshold"` SoftLimit bool `mi:"SoftLimit"`
Disabled bool `mi:"Disabled"`
MatchesTemplate bool `mi:"MatchesTemplate"`
SoftLimit bool `mi:"SoftLimit"`
} }
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var dst []MSFT_FSRMQuota var dst []msftFSRMQuota
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery); err != nil { if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -25,7 +25,9 @@ import (
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows"
) )
const ( const (
@@ -52,6 +54,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{ CollectorsEnabled: []string{
subCollectorDataStore, subCollectorDataStore,
@@ -154,15 +157,19 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
return nil return nil
} }
version := windows.RtlGetVersion()
subCollectors := map[string]struct { subCollectors := map[string]struct {
build func() error build func() error
collect func(ch chan<- prometheus.Metric) error collect func(ch chan<- prometheus.Metric) error
close func() close func()
minBuildNumber uint32
}{ }{
subCollectorDataStore: { subCollectorDataStore: {
build: c.buildDataStore, build: c.buildDataStore,
collect: c.collectDataStore, collect: c.collectDataStore,
close: c.perfDataCollectorDataStore.Close, close: c.perfDataCollectorDataStore.Close,
minBuildNumber: types.BuildNumberWindowsServer2022,
}, },
subCollectorDynamicMemoryBalancer: { subCollectorDynamicMemoryBalancer: {
build: c.buildDynamicMemoryBalancer, build: c.buildDynamicMemoryBalancer,
@@ -239,20 +246,30 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Result must order, to prevent test failures. // Result must order, to prevent test failures.
sort.Strings(c.config.CollectorsEnabled) sort.Strings(c.config.CollectorsEnabled)
errs := make([]error, 0, len(c.config.CollectorsEnabled))
for _, name := range c.config.CollectorsEnabled { for _, name := range c.config.CollectorsEnabled {
if _, ok := subCollectors[name]; !ok { if _, ok := subCollectors[name]; !ok {
return fmt.Errorf("unknown collector: %s", name) return fmt.Errorf("unknown collector: %s", name)
} }
if version.BuildNumber < subCollectors[name].minBuildNumber {
errs = append(errs, fmt.Errorf("collector %s requires Windows Server 2022 or newer", name))
continue
}
if err := subCollectors[name].build(); err != nil { if err := subCollectors[name].build(); err != nil {
return fmt.Errorf("failed to build %s collector: %w", name, err) errs = append(errs, fmt.Errorf("failed to build %s collector: %w", name, err))
continue
} }
c.collectorFns = append(c.collectorFns, subCollectors[name].collect) c.collectorFns = append(c.collectorFns, subCollectors[name].collect)
c.closeFns = append(c.closeFns, subCollectors[name].close) c.closeFns = append(c.closeFns, subCollectors[name].close)
} }
return nil return errors.Join(errs...)
} }
// Collect sends the metric values for each metric // Collect sends the metric values for each metric

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -177,7 +176,7 @@ func (c *Collector) buildDataStore() error {
dataStoreSetOperationLatencyMicro, dataStoreSetOperationLatencyMicro,
dataStoreSetOperationCount, dataStoreSetOperationCount,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V DataStore collector: %w", err) return fmt.Errorf("failed to create Hyper-V DataStore collector: %w", err)
} }
@@ -463,7 +462,7 @@ func (c *Collector) buildDataStore() error {
func (c *Collector) collectDataStore(ch chan<- prometheus.Metric) error { func (c *Collector) collectDataStore(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorDataStore.Collect() data, err := c.perfDataCollectorDataStore.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V DataStore metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V DataStore metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -69,7 +68,7 @@ func (c *Collector) buildDynamicMemoryVM() error {
vmMemoryRemovedMemory, vmMemoryRemovedMemory,
vmMemoryGuestAvailableMemory, vmMemoryGuestAvailableMemory,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Dynamic Memory VM collector: %w", err) return fmt.Errorf("failed to create Hyper-V Dynamic Memory VM collector: %w", err)
} }
@@ -139,7 +138,7 @@ func (c *Collector) buildDynamicMemoryVM() error {
func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error { func (c *Collector) collectDynamicMemoryVM(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorDynamicMemoryVM.Collect() data, err := c.perfDataCollectorDynamicMemoryVM.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Dynamic Memory VM metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Dynamic Memory VM metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"strings" "strings"
@@ -58,7 +57,7 @@ func (c *Collector) buildHypervisorVirtualProcessor() error {
hypervisorVirtualProcessorRemoteRunTimePercent, hypervisorVirtualProcessorRemoteRunTimePercent,
hypervisorVirtualProcessorCPUWaitTimePerDispatch, hypervisorVirtualProcessorCPUWaitTimePerDispatch,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err) return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err)
} }
@@ -86,7 +85,7 @@ func (c *Collector) buildHypervisorVirtualProcessor() error {
func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metric) error { func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorHypervisorVirtualProcessor.Collect() data, err := c.perfDataCollectorHypervisorVirtualProcessor.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Hypervisor Virtual Processor metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Hypervisor Virtual Processor metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -56,7 +55,7 @@ func (c *Collector) buildLegacyNetworkAdapter() error {
legacyNetworkAdapterFramesReceived, legacyNetworkAdapterFramesReceived,
legacyNetworkAdapterFramesSent, legacyNetworkAdapterFramesSent,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Legacy Network Adapter collector: %w", err) return fmt.Errorf("failed to create Hyper-V Legacy Network Adapter collector: %w", err)
} }
@@ -102,7 +101,7 @@ func (c *Collector) buildLegacyNetworkAdapter() error {
func (c *Collector) collectLegacyNetworkAdapter(ch chan<- prometheus.Metric) error { func (c *Collector) collectLegacyNetworkAdapter(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorLegacyNetworkAdapter.Collect() data, err := c.perfDataCollectorLegacyNetworkAdapter.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Legacy Network Adapter metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Legacy Network Adapter metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -46,7 +45,7 @@ func (c *Collector) buildVirtualMachineVidPartition() error {
preferredNUMANodeIndex, preferredNUMANodeIndex,
remotePhysicalPages, remotePhysicalPages,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err) return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err)
} }
@@ -74,7 +73,7 @@ func (c *Collector) buildVirtualMachineVidPartition() error {
func (c *Collector) collectVirtualMachineVidPartition(ch chan<- prometheus.Metric) error { func (c *Collector) collectVirtualMachineVidPartition(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualMachineVidPartition.Collect() data, err := c.perfDataCollectorVirtualMachineVidPartition.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V VM Vid Partition metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V VM Vid Partition metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -56,7 +55,7 @@ func (c *Collector) buildVirtualNetworkAdapter() error {
virtualNetworkAdapterPacketsReceived, virtualNetworkAdapterPacketsReceived,
virtualNetworkAdapterPacketsSent, virtualNetworkAdapterPacketsSent,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter collector: %w", err) return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter collector: %w", err)
} }
@@ -102,7 +101,7 @@ func (c *Collector) buildVirtualNetworkAdapter() error {
func (c *Collector) collectVirtualNetworkAdapter(ch chan<- prometheus.Metric) error { func (c *Collector) collectVirtualNetworkAdapter(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualNetworkAdapter.Collect() data, err := c.perfDataCollectorVirtualNetworkAdapter.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -215,7 +214,7 @@ func (c *Collector) buildVirtualNetworkAdapterDropReasons() error {
virtualNetworkAdapterDropReasonsOutgoingUnknown, virtualNetworkAdapterDropReasonsOutgoingUnknown,
virtualNetworkAdapterDropReasonsIncomingUnknown, virtualNetworkAdapterDropReasonsIncomingUnknown,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter Drop Reasons collector: %w", err) return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter Drop Reasons collector: %w", err)
} }
@@ -231,7 +230,7 @@ func (c *Collector) buildVirtualNetworkAdapterDropReasons() error {
func (c *Collector) collectVirtualNetworkAdapterDropReasons(ch chan<- prometheus.Metric) error { func (c *Collector) collectVirtualNetworkAdapterDropReasons(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualNetworkAdapterDropReasons.Collect() data, err := c.perfDataCollectorVirtualNetworkAdapterDropReasons.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter Drop Reasons metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Virtual Network Adapter Drop Reasons metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -89,7 +88,7 @@ func (c *Collector) buildVirtualSMB() error {
virtualSMBSentBytes, virtualSMBSentBytes,
virtualSMBReceivedBytes, virtualSMBReceivedBytes,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual SMB collector: %w", err) return fmt.Errorf("failed to create Hyper-V Virtual SMB collector: %w", err)
} }
@@ -201,7 +200,7 @@ func (c *Collector) buildVirtualSMB() error {
func (c *Collector) collectVirtualSMB(ch chan<- prometheus.Metric) error { func (c *Collector) collectVirtualSMB(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualSMB.Collect() data, err := c.perfDataCollectorVirtualSMB.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual SMB metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Virtual SMB metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -74,7 +73,7 @@ func (c *Collector) buildVirtualStorageDevice() error {
virtualStorageDeviceLowerLatency, virtualStorageDeviceLowerLatency,
virtualStorageDeviceIOQuotaReplenishmentRate, virtualStorageDeviceIOQuotaReplenishmentRate,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err) return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err)
} }
@@ -156,7 +155,7 @@ func (c *Collector) buildVirtualStorageDevice() error {
func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) error { func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualStorageDevice.Collect() data, err := c.perfDataCollectorVirtualStorageDevice.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Storage Device metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Virtual Storage Device metrics: %w", err)
} }

View File

@@ -16,7 +16,6 @@
package hyperv package hyperv
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -100,7 +99,7 @@ func (c *Collector) buildVirtualSwitch() error {
virtualSwitchPacketsSent, virtualSwitchPacketsSent,
virtualSwitchPurgedMacAddresses, virtualSwitchPurgedMacAddresses,
}) })
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Switch collector: %w", err) return fmt.Errorf("failed to create Hyper-V Virtual Switch collector: %w", err)
} }
@@ -236,7 +235,7 @@ func (c *Collector) buildVirtualSwitch() error {
func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error { func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollectorVirtualSwitch.Collect() data, err := c.perfDataCollectorVirtualSwitch.Collect()
if err != nil && !errors.Is(err, perfdata.ErrNoData) { if err != nil {
return fmt.Errorf("failed to collect Hyper-V Virtual Switch metrics: %w", err) return fmt.Errorf("failed to collect Hyper-V Virtual Switch metrics: %w", err)
} }

View File

@@ -41,6 +41,7 @@ type Config struct {
AppExclude *regexp.Regexp `yaml:"app_exclude"` AppExclude *regexp.Regexp `yaml:"app_exclude"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
SiteInclude: types.RegExpAny, SiteInclude: types.RegExpAny,
SiteExclude: types.RegExpEmpty, SiteExclude: types.RegExpEmpty,
@@ -150,8 +151,8 @@ func (c *Collector) GetName() string {
func (c *Collector) Close() error { func (c *Collector) Close() error {
c.perfDataCollectorWebService.Close() c.perfDataCollectorWebService.Close()
c.perfDataCollectorAppPoolWAS.Close() c.perfDataCollectorAppPoolWAS.Close()
c.perfDataCollectorW3SVCW3WP.Close() c.w3SVCW3WPPerfDataCollector.Close()
c.perfDataCollectorWebServiceCache.Close() c.serviceCachePerfDataCollector.Close()
return nil return nil
} }
@@ -168,23 +169,25 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
prometheus.Labels{"version": fmt.Sprintf("%d.%d", c.iisVersion.major, c.iisVersion.minor)}, prometheus.Labels{"version": fmt.Sprintf("%d.%d", c.iisVersion.major, c.iisVersion.minor)},
) )
errs := make([]error, 0, 4)
if err := c.buildWebService(); err != nil { if err := c.buildWebService(); err != nil {
return fmt.Errorf("failed to build Web Service collector: %w", err) errs = append(errs, fmt.Errorf("failed to build Web Service collector: %w", err))
} }
if err := c.buildAppPoolWAS(); err != nil { if err := c.buildAppPoolWAS(); err != nil {
return fmt.Errorf("failed to build APP_POOL_WAS collector: %w", err) errs = append(errs, fmt.Errorf("failed to build APP_POOL_WAS collector: %w", err))
} }
if err := c.buildW3SVCW3WP(); err != nil { if err := c.buildW3SVCW3WP(); err != nil {
return fmt.Errorf("failed to build W3SVC_W3WP collector: %w", err) errs = append(errs, fmt.Errorf("failed to build W3SVC_W3WP collector: %w", err))
} }
if err := c.buildWebServiceCache(); err != nil { if err := c.buildWebServiceCache(); err != nil {
return fmt.Errorf("failed to build Web Service Cache collector: %w", err) errs = append(errs, fmt.Errorf("failed to build Web Service Cache collector: %w", err))
} }
return nil return errors.Join(errs...)
} }
type simpleVersion struct { type simpleVersion struct {
@@ -195,7 +198,7 @@ type simpleVersion struct {
func (c *Collector) getIISVersion(logger *slog.Logger) simpleVersion { func (c *Collector) getIISVersion(logger *slog.Logger) simpleVersion {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE) k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE)
if err != nil { if err != nil {
logger.Warn("Couldn't open registry to determine IIS version", logger.Warn("couldn't open registry to determine IIS version",
slog.Any("err", err), slog.Any("err", err),
) )
@@ -273,7 +276,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
// discarded, and "Site_B#2" would be kept and presented as "Site_B" in the // discarded, and "Site_B#2" would be kept and presented as "Site_B" in the
// Collector metrics. // Collector metrics.
// [ "Site_A", "Site_B", "Site_C", "Site_B#2" ]. // [ "Site_A", "Site_B", "Site_C", "Site_B#2" ].
func deduplicateIISNames(counterValues map[string]map[string]perfdata.CounterValues) { func deduplicateIISNames(counterValues map[string]map[string]perfdata.CounterValue) {
services := slices.Collect(maps.Keys(counterValues)) services := slices.Collect(maps.Keys(counterValues))
// Ensure IIS entry with the highest suffix occurs last // Ensure IIS entry with the highest suffix occurs last

View File

@@ -57,6 +57,7 @@ const (
TotalWorkerProcessStartupFailures = "Total Worker Process Startup Failures" TotalWorkerProcessStartupFailures = "Total Worker Process Startup Failures"
) )
//nolint:gochecknoglobals
var applicationStates = map[uint32]string{ var applicationStates = map[uint32]string{
1: "Uninitialized", 1: "Uninitialized",
2: "Initialized", 2: "Initialized",

View File

@@ -26,399 +26,385 @@ import (
) )
type collectorW3SVCW3WP struct { type collectorW3SVCW3WP struct {
perfDataCollectorW3SVCW3WP *perfdata.Collector w3SVCW3WPPerfDataCollector *perfdata.Collector
// W3SVC_W3WP // W3SVC_W3WP
threads *prometheus.Desc w3SVCW3WPThreads *prometheus.Desc
maximumThreads *prometheus.Desc w3SVCW3WPMaximumThreads *prometheus.Desc
requestsTotal *prometheus.Desc w3SVCW3WPRequestsTotal *prometheus.Desc
requestsActive *prometheus.Desc w3SVCW3WPRequestsActive *prometheus.Desc
activeFlushedEntries *prometheus.Desc w3SVCW3WPActiveFlushedEntries *prometheus.Desc
currentFileCacheMemoryUsage *prometheus.Desc w3SVCW3WPCurrentFileCacheMemoryUsage *prometheus.Desc
maximumFileCacheMemoryUsage *prometheus.Desc w3SVCW3WPMaximumFileCacheMemoryUsage *prometheus.Desc
fileCacheFlushesTotal *prometheus.Desc w3SVCW3WPFileCacheFlushesTotal *prometheus.Desc
fileCacheQueriesTotal *prometheus.Desc w3SVCW3WPFileCacheQueriesTotal *prometheus.Desc
fileCacheHitsTotal *prometheus.Desc w3SVCW3WPFileCacheHitsTotal *prometheus.Desc
filesCached *prometheus.Desc w3SVCW3WPFilesCached *prometheus.Desc
filesCachedTotal *prometheus.Desc w3SVCW3WPFilesCachedTotal *prometheus.Desc
filesFlushedTotal *prometheus.Desc w3SVCW3WPFilesFlushedTotal *prometheus.Desc
uriCacheFlushesTotal *prometheus.Desc w3SVCW3WPURICacheFlushesTotal *prometheus.Desc
uriCacheQueriesTotal *prometheus.Desc w3SVCW3WPURICacheQueriesTotal *prometheus.Desc
uriCacheHitsTotal *prometheus.Desc w3SVCW3WPURICacheHitsTotal *prometheus.Desc
urisCached *prometheus.Desc w3SVCW3WPURIsCached *prometheus.Desc
urisCachedTotal *prometheus.Desc w3SVCW3WPURIsCachedTotal *prometheus.Desc
urisFlushedTotal *prometheus.Desc w3SVCW3WPURIsFlushedTotal *prometheus.Desc
metadataCached *prometheus.Desc w3SVCW3WPMetadataCached *prometheus.Desc
metadataCacheFlushes *prometheus.Desc w3SVCW3WPMetadataCacheFlushes *prometheus.Desc
metadataCacheQueriesTotal *prometheus.Desc w3SVCW3WPMetadataCacheQueriesTotal *prometheus.Desc
metadataCacheHitsTotal *prometheus.Desc w3SVCW3WPMetadataCacheHitsTotal *prometheus.Desc
metadataCachedTotal *prometheus.Desc w3SVCW3WPMetadataCachedTotal *prometheus.Desc
metadataFlushedTotal *prometheus.Desc w3SVCW3WPMetadataFlushedTotal *prometheus.Desc
outputCacheActiveFlushedItems *prometheus.Desc w3SVCW3WPOutputCacheActiveFlushedItems *prometheus.Desc
outputCacheItems *prometheus.Desc w3SVCW3WPOutputCacheItems *prometheus.Desc
outputCacheMemoryUsage *prometheus.Desc w3SVCW3WPOutputCacheMemoryUsage *prometheus.Desc
outputCacheQueriesTotal *prometheus.Desc w3SVCW3WPOutputCacheQueriesTotal *prometheus.Desc
outputCacheHitsTotal *prometheus.Desc w3SVCW3WPOutputCacheHitsTotal *prometheus.Desc
outputCacheFlushedItemsTotal *prometheus.Desc w3SVCW3WPOutputCacheFlushedItemsTotal *prometheus.Desc
outputCacheFlushesTotal *prometheus.Desc w3SVCW3WPOutputCacheFlushesTotal *prometheus.Desc
// IIS 8+ Only // IIS 8+ Only
requestErrorsTotal *prometheus.Desc w3SVCW3WPRequestErrorsTotal *prometheus.Desc
webSocketRequestsActive *prometheus.Desc w3SVCW3WPWebSocketRequestsActive *prometheus.Desc
webSocketConnectionAttempts *prometheus.Desc w3SVCW3WPWebSocketConnectionAttempts *prometheus.Desc
webSocketConnectionsAccepted *prometheus.Desc w3SVCW3WPWebSocketConnectionsAccepted *prometheus.Desc
webSocketConnectionsRejected *prometheus.Desc w3SVCW3WPWebSocketConnectionsRejected *prometheus.Desc
} }
var workerProcessNameExtractor = regexp.MustCompile(`^(\d+)_(.+)$`) var workerProcessNameExtractor = regexp.MustCompile(`^(\d+)_(.+)$`)
const ( const (
Threads = "Active Threads Count" w3SVCW3WPThreads = "Active Threads Count"
MaximumThreads = "Maximum Threads Count" w3SVCW3WPMaximumThreads = "Maximum Threads Count"
RequestsTotal = "Total HTTP Requests Served" w3SVCW3WPRequestsTotal = "Total HTTP Requests Served"
RequestsActive = "Active Requests" w3SVCW3WPRequestsActive = "Active Requests"
ActiveFlushedEntries = "Active Flushed Entries" w3SVCW3WPActiveFlushedEntries = "Active Flushed Entries"
CurrentFileCacheMemoryUsage = "Current File Cache Memory Usage" w3SVCW3WPCurrentFileCacheMemoryUsage = "Current File Cache Memory Usage"
MaximumFileCacheMemoryUsage = "Maximum File Cache Memory Usage" w3SVCW3WPMaximumFileCacheMemoryUsage = "Maximum File Cache Memory Usage"
FileCacheFlushesTotal = "File Cache Flushes" w3SVCW3WPFileCacheFlushesTotal = "File Cache Flushes"
FileCacheHitsTotal = "File Cache Hits" w3SVCW3WPFileCacheHitsTotal = "File Cache Hits"
FileCacheMissesTotal = "File Cache Misses" w3SVCW3WPFileCacheMissesTotal = "File Cache Misses"
FilesCached = "Current Files Cached" w3SVCW3WPFilesCached = "Current Files Cached"
FilesCachedTotal = "Total Files Cached" w3SVCW3WPFilesCachedTotal = "Total Files Cached"
FilesFlushedTotal = "Total Flushed Files" w3SVCW3WPFilesFlushedTotal = "Total Flushed Files"
URICacheFlushesTotal = "Total Flushed URIs" w3SVCW3WPURICacheFlushesTotal = "Total Flushed URIs"
URICacheFlushesTotalKernel = "Total Flushed URIs" w3SVCW3WPURICacheHitsTotal = "URI Cache Hits"
URIsFlushedTotalKernel = "Kernel: Total Flushed URIs" w3SVCW3WPURICacheMissesTotal = "URI Cache Misses"
URICacheHitsTotal = "URI Cache Hits" w3SVCW3WPURIsCached = "Current URIs Cached"
URICacheHitsTotalKernel = "Kernel: URI Cache Hits" w3SVCW3WPURIsCachedTotal = "Total URIs Cached"
URICacheMissesTotal = "URI Cache Misses" w3SVCW3WPURIsFlushedTotal = "Total Flushed URIs"
URICacheMissesTotalKernel = "Kernel: URI Cache Misses"
URIsCached = "Current URIs Cached"
URIsCachedKernel = "Kernel: Current URIs Cached"
URIsCachedTotal = "Total URIs Cached"
URIsCachedTotalKernel = "Total URIs Cached"
URIsFlushedTotal = "Total Flushed URIs"
MetaDataCacheHits = "Metadata Cache Hits" w3SVCW3WPMetaDataCacheHits = "Metadata Cache Hits"
MetaDataCacheMisses = "Metadata Cache Misses" w3SVCW3WPMetaDataCacheMisses = "Metadata Cache Misses"
MetadataCached = "Current Metadata Cached" w3SVCW3WPMetadataCached = "Current Metadata Cached"
MetadataCacheFlushes = "Metadata Cache Flushes" w3SVCW3WPMetadataCacheFlushes = "Metadata Cache Flushes"
MetadataCachedTotal = "Total Metadata Cached" w3SVCW3WPMetadataCachedTotal = "Total Metadata Cached"
MetadataFlushedTotal = "Total Flushed Metadata" w3SVCW3WPMetadataFlushedTotal = "Total Flushed Metadata"
OutputCacheActiveFlushedItems = "Output Cache Current Flushed Items" w3SVCW3WPOutputCacheActiveFlushedItems = "Output Cache Current Flushed Items"
OutputCacheItems = "Output Cache Current Items" w3SVCW3WPOutputCacheItems = "Output Cache Current Items"
OutputCacheMemoryUsage = "Output Cache Current Memory Usage" w3SVCW3WPOutputCacheMemoryUsage = "Output Cache Current Memory Usage"
OutputCacheHitsTotal = "Output Cache Total Hits" w3SVCW3WPOutputCacheHitsTotal = "Output Cache Total Hits"
OutputCacheMissesTotal = "Output Cache Total Misses" w3SVCW3WPOutputCacheMissesTotal = "Output Cache Total Misses"
OutputCacheFlushedItemsTotal = "Output Cache Total Flushed Items" w3SVCW3WPOutputCacheFlushedItemsTotal = "Output Cache Total Flushed Items"
OutputCacheFlushesTotal = "Output Cache Total Flushes" w3SVCW3WPOutputCacheFlushesTotal = "Output Cache Total Flushes"
// IIS8 // IIS8
RequestErrors500 = "% 500 HTTP Response Sent" w3SVCW3WPRequestErrors500 = "% 500 HTTP Response Sent"
RequestErrors503 = "% 503 HTTP Response Sent" w3SVCW3WPRequestErrors404 = "% 404 HTTP Response Sent"
RequestErrors404 = "% 404 HTTP Response Sent" w3SVCW3WPRequestErrors403 = "% 403 HTTP Response Sent"
RequestErrors403 = "% 403 HTTP Response Sent" w3SVCW3WPRequestErrors401 = "% 401 HTTP Response Sent"
RequestErrors401 = "% 401 HTTP Response Sent"
WebSocketRequestsActive = "WebSocket Active Requests" w3SVCW3WPWebSocketRequestsActive = "WebSocket Active Requests"
WebSocketConnectionAttempts = "WebSocket Connection Attempts / Sec" w3SVCW3WPWebSocketConnectionAttempts = "WebSocket Connection Attempts / Sec"
WebSocketConnectionsAccepted = "WebSocket Connections Accepted / Sec" w3SVCW3WPWebSocketConnectionsAccepted = "WebSocket Connections Accepted / Sec"
WebSocketConnectionsRejected = "WebSocket Connections Rejected / Sec" w3SVCW3WPWebSocketConnectionsRejected = "WebSocket Connections Rejected / Sec"
) )
func (c *Collector) buildW3SVCW3WP() error { func (c *Collector) buildW3SVCW3WP() error {
counters := []string{ counters := []string{
Threads, w3SVCW3WPThreads,
MaximumThreads, w3SVCW3WPMaximumThreads,
RequestsTotal, w3SVCW3WPRequestsTotal,
RequestsActive, w3SVCW3WPRequestsActive,
ActiveFlushedEntries, w3SVCW3WPActiveFlushedEntries,
CurrentFileCacheMemoryUsage, w3SVCW3WPCurrentFileCacheMemoryUsage,
MaximumFileCacheMemoryUsage, w3SVCW3WPMaximumFileCacheMemoryUsage,
FileCacheFlushesTotal, w3SVCW3WPFileCacheFlushesTotal,
FileCacheHitsTotal, w3SVCW3WPFileCacheHitsTotal,
FileCacheMissesTotal, w3SVCW3WPFileCacheMissesTotal,
FilesCached, w3SVCW3WPFilesCached,
FilesCachedTotal, w3SVCW3WPFilesCachedTotal,
FilesFlushedTotal, w3SVCW3WPFilesFlushedTotal,
URICacheFlushesTotal, w3SVCW3WPURICacheFlushesTotal,
URICacheFlushesTotalKernel, w3SVCW3WPURICacheHitsTotal,
URIsFlushedTotalKernel, w3SVCW3WPURICacheMissesTotal,
URICacheHitsTotal, w3SVCW3WPURIsCached,
URICacheHitsTotalKernel, w3SVCW3WPURIsCachedTotal,
URICacheMissesTotal, w3SVCW3WPURIsFlushedTotal,
URICacheMissesTotalKernel, w3SVCW3WPMetaDataCacheHits,
URIsCached, w3SVCW3WPMetaDataCacheMisses,
URIsCachedKernel, w3SVCW3WPMetadataCached,
URIsCachedTotal, w3SVCW3WPMetadataCacheFlushes,
URIsCachedTotalKernel, w3SVCW3WPMetadataCachedTotal,
URIsFlushedTotal, w3SVCW3WPMetadataFlushedTotal,
MetaDataCacheHits, w3SVCW3WPOutputCacheActiveFlushedItems,
MetaDataCacheMisses, w3SVCW3WPOutputCacheItems,
MetadataCached, w3SVCW3WPOutputCacheMemoryUsage,
MetadataCacheFlushes, w3SVCW3WPOutputCacheHitsTotal,
MetadataCachedTotal, w3SVCW3WPOutputCacheMissesTotal,
MetadataFlushedTotal, w3SVCW3WPOutputCacheFlushedItemsTotal,
OutputCacheActiveFlushedItems, w3SVCW3WPOutputCacheFlushesTotal,
OutputCacheItems,
OutputCacheMemoryUsage,
OutputCacheHitsTotal,
OutputCacheMissesTotal,
OutputCacheFlushedItemsTotal,
OutputCacheFlushesTotal,
} }
if c.iisVersion.major >= 8 { if c.iisVersion.major >= 8 {
counters = append(counters, []string{ counters = append(counters, []string{
RequestErrors500, w3SVCW3WPRequestErrors500,
RequestErrors503, w3SVCW3WPRequestErrors404,
RequestErrors404, w3SVCW3WPRequestErrors403,
RequestErrors403, w3SVCW3WPRequestErrors401,
RequestErrors401, w3SVCW3WPWebSocketRequestsActive,
WebSocketRequestsActive, w3SVCW3WPWebSocketConnectionAttempts,
WebSocketConnectionAttempts, w3SVCW3WPWebSocketConnectionsAccepted,
WebSocketConnectionsAccepted, w3SVCW3WPWebSocketConnectionsRejected,
WebSocketConnectionsRejected,
}...) }...)
} }
var err error var err error
c.perfDataCollectorW3SVCW3WP, err = perfdata.NewCollector("W3SVC_W3WP", perfdata.InstancesAll, counters) c.w3SVCW3WPPerfDataCollector, err = perfdata.NewCollector("W3SVC_W3WP", perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create W3SVC_W3WP collector: %w", err) return fmt.Errorf("failed to create W3SVC_W3WP collector: %w", err)
} }
// W3SVC_W3WP // W3SVC_W3WP
c.threads = prometheus.NewDesc( c.w3SVCW3WPThreads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_threads"), prometheus.BuildFQName(types.Namespace, Name, "worker_threads"),
"Number of threads actively processing requests in the worker process", "Number of threads actively processing requests in the worker process",
[]string{"app", "pid", "state"}, []string{"app", "pid", "state"},
nil, nil,
) )
c.maximumThreads = prometheus.NewDesc( c.w3SVCW3WPMaximumThreads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_max_threads"), prometheus.BuildFQName(types.Namespace, Name, "worker_max_threads"),
"Maximum number of threads to which the thread pool can grow as needed", "Maximum number of threads to which the thread pool can grow as needed",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.requestsTotal = prometheus.NewDesc( c.w3SVCW3WPRequestsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_requests_total"),
"Total number of HTTP requests served by the worker process", "Total number of HTTP requests served by the worker process",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.requestsActive = prometheus.NewDesc( c.w3SVCW3WPRequestsActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_current_requests"), prometheus.BuildFQName(types.Namespace, Name, "worker_current_requests"),
"Current number of requests being processed by the worker process", "Current number of requests being processed by the worker process",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.activeFlushedEntries = prometheus.NewDesc( c.w3SVCW3WPActiveFlushedEntries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_cache_active_flushed_entries"), 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.", "Number of file handles cached in user-mode that will be closed when all current transfers complete.",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.currentFileCacheMemoryUsage = prometheus.NewDesc( c.w3SVCW3WPCurrentFileCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_memory_bytes"), prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_memory_bytes"),
"Current number of bytes used by user-mode file cache", "Current number of bytes used by user-mode file cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.maximumFileCacheMemoryUsage = prometheus.NewDesc( c.w3SVCW3WPMaximumFileCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_max_memory_bytes"), prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_max_memory_bytes"),
"Maximum number of bytes used by user-mode file cache", "Maximum number of bytes used by user-mode file cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.fileCacheFlushesTotal = prometheus.NewDesc( c.w3SVCW3WPFileCacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_flushes_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_flushes_total"),
"Total number of files removed from the user-mode cache", "Total number of files removed from the user-mode cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.fileCacheQueriesTotal = prometheus.NewDesc( c.w3SVCW3WPFileCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_queries_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_queries_total"),
"Total file cache queries (hits + misses)", "Total file cache queries (hits + misses)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.fileCacheHitsTotal = prometheus.NewDesc( c.w3SVCW3WPFileCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_hits_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_hits_total"),
"Total number of successful lookups in the user-mode file cache", "Total number of successful lookups in the user-mode file cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.filesCached = prometheus.NewDesc( c.w3SVCW3WPFilesCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items"), prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items"),
"Current number of files whose contents are present in user-mode cache", "Current number of files whose contents are present in user-mode cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.filesCachedTotal = prometheus.NewDesc( c.w3SVCW3WPFilesCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items_total"), 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)", "Total number of files whose contents were ever added to the user-mode cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.filesFlushedTotal = prometheus.NewDesc( c.w3SVCW3WPFilesFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items_flushed_total"), 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)", "Total number of file handles that have been removed from the user-mode cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.uriCacheFlushesTotal = prometheus.NewDesc( c.w3SVCW3WPURICacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_flushes_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_flushes_total"),
"Total number of URI cache flushes (since service startup)", "Total number of URI cache flushes (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.uriCacheQueriesTotal = prometheus.NewDesc( c.w3SVCW3WPURICacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_queries_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_queries_total"),
"Total number of uri cache queries (hits + misses)", "Total number of uri cache queries (hits + misses)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.uriCacheHitsTotal = prometheus.NewDesc( c.w3SVCW3WPURICacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_hits_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_hits_total"),
"Total number of successful lookups in the user-mode URI cache (since service startup)", "Total number of successful lookups in the user-mode URI cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.urisCached = prometheus.NewDesc( c.w3SVCW3WPURIsCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items"), prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items"),
"Number of URI information blocks currently in the user-mode cache", "Number of URI information blocks currently in the user-mode cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.urisCachedTotal = prometheus.NewDesc( c.w3SVCW3WPURIsCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items_total"), 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)", "Total number of URI information blocks added to the user-mode cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.urisFlushedTotal = prometheus.NewDesc( c.w3SVCW3WPURIsFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items_flushed_total"), 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)", "The number of URI information blocks that have been removed from the user-mode cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.metadataCached = prometheus.NewDesc( c.w3SVCW3WPMetadataCached = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items"), prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items"),
"Number of metadata information blocks currently present in user-mode cache", "Number of metadata information blocks currently present in user-mode cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.metadataCacheFlushes = prometheus.NewDesc( c.w3SVCW3WPMetadataCacheFlushes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_flushes_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_flushes_total"),
"Total number of user-mode metadata cache flushes (since service startup)", "Total number of user-mode metadata cache flushes (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.metadataCacheQueriesTotal = prometheus.NewDesc( c.w3SVCW3WPMetadataCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_queries_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_queries_total"),
"Total metadata cache queries (hits + misses)", "Total metadata cache queries (hits + misses)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.metadataCacheHitsTotal = prometheus.NewDesc( c.w3SVCW3WPMetadataCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_hits_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_hits_total"),
"Total number of successful lookups in the user-mode metadata cache (since service startup)", "Total number of successful lookups in the user-mode metadata cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.metadataCachedTotal = prometheus.NewDesc( c.w3SVCW3WPMetadataCachedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items_cached_total"), 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)", "Total number of metadata information blocks added to the user-mode cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.metadataFlushedTotal = prometheus.NewDesc( c.w3SVCW3WPMetadataFlushedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items_flushed_total"), 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)", "Total number of metadata information blocks removed from the user-mode cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.outputCacheActiveFlushedItems = prometheus.NewDesc( c.w3SVCW3WPOutputCacheActiveFlushedItems = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_active_flushed_items"), prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_active_flushed_items"),
"", "",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.outputCacheItems = prometheus.NewDesc( c.w3SVCW3WPOutputCacheItems = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items"), prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items"),
"Number of items current present in output cache", "Number of items current present in output cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.outputCacheMemoryUsage = prometheus.NewDesc( c.w3SVCW3WPOutputCacheMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_memory_bytes"), prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_memory_bytes"),
"Current number of bytes used by output cache", "Current number of bytes used by output cache",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.outputCacheQueriesTotal = prometheus.NewDesc( c.w3SVCW3WPOutputCacheQueriesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_queries_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_output_queries_total"),
"Total number of output cache queries (hits + misses)", "Total number of output cache queries (hits + misses)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.outputCacheHitsTotal = prometheus.NewDesc( c.w3SVCW3WPOutputCacheHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_hits_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_hits_total"),
"Total number of successful lookups in output cache (since service startup)", "Total number of successful lookups in output cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.outputCacheFlushedItemsTotal = prometheus.NewDesc( c.w3SVCW3WPOutputCacheFlushedItemsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items_flushed_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items_flushed_total"),
"Total number of items flushed from output cache (since service startup)", "Total number of items flushed from output cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.outputCacheFlushesTotal = prometheus.NewDesc( c.w3SVCW3WPOutputCacheFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_flushes_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_flushes_total"),
"Total number of flushes of output cache (since service startup)", "Total number of flushes of output cache (since service startup)",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
// W3SVC_W3WP_IIS8 // W3SVC_W3WP_IIS8
c.requestErrorsTotal = prometheus.NewDesc( c.w3SVCW3WPRequestErrorsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_request_errors_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_request_errors_total"),
"Total number of requests that returned an error", "Total number of requests that returned an error",
[]string{"app", "pid", "status_code"}, []string{"app", "pid", "status_code"},
nil, nil,
) )
c.webSocketRequestsActive = prometheus.NewDesc( c.w3SVCW3WPWebSocketRequestsActive = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_current_websocket_requests"), prometheus.BuildFQName(types.Namespace, Name, "worker_current_websocket_requests"),
"", "",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.webSocketConnectionAttempts = prometheus.NewDesc( c.w3SVCW3WPWebSocketConnectionAttempts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_attempts_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_attempts_total"),
"", "",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.webSocketConnectionsAccepted = prometheus.NewDesc( c.w3SVCW3WPWebSocketConnectionsAccepted = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_accepted_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_accepted_total"),
"", "",
[]string{"app", "pid"}, []string{"app", "pid"},
nil, nil,
) )
c.webSocketConnectionsRejected = prometheus.NewDesc( c.w3SVCW3WPWebSocketConnectionsRejected = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_rejected_total"), prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_rejected_total"),
"", "",
[]string{"app", "pid"}, []string{"app", "pid"},
@@ -429,7 +415,7 @@ func (c *Collector) buildW3SVCW3WP() error {
} }
func (c *Collector) collectW3SVCW3WP(ch chan<- prometheus.Metric) error { func (c *Collector) collectW3SVCW3WP(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorW3SVCW3WP.Collect() perfData, err := c.w3SVCW3WPPerfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err) return fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err)
} }
@@ -456,297 +442,289 @@ func (c *Collector) collectW3SVCW3WP(ch chan<- prometheus.Metric) error {
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.threads, c.w3SVCW3WPThreads,
prometheus.GaugeValue, prometheus.GaugeValue,
app[Threads].FirstValue, app[w3SVCW3WPThreads].FirstValue,
name, name,
pid, pid,
"busy", "busy",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.maximumThreads, c.w3SVCW3WPMaximumThreads,
prometheus.CounterValue, prometheus.CounterValue,
app[MaximumThreads].FirstValue, app[w3SVCW3WPMaximumThreads].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestsTotal, c.w3SVCW3WPRequestsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[RequestsTotal].FirstValue, app[w3SVCW3WPRequestsTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestsActive, c.w3SVCW3WPRequestsActive,
prometheus.CounterValue, prometheus.CounterValue,
app[RequestsActive].FirstValue, app[w3SVCW3WPRequestsActive].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.activeFlushedEntries, c.w3SVCW3WPActiveFlushedEntries,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ActiveFlushedEntries].FirstValue, app[w3SVCW3WPActiveFlushedEntries].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentFileCacheMemoryUsage, c.w3SVCW3WPCurrentFileCacheMemoryUsage,
prometheus.GaugeValue, prometheus.GaugeValue,
app[CurrentFileCacheMemoryUsage].FirstValue, app[w3SVCW3WPCurrentFileCacheMemoryUsage].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.maximumFileCacheMemoryUsage, c.w3SVCW3WPMaximumFileCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
app[MaximumFileCacheMemoryUsage].FirstValue, app[w3SVCW3WPMaximumFileCacheMemoryUsage].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.fileCacheFlushesTotal, c.w3SVCW3WPFileCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[FileCacheFlushesTotal].FirstValue, app[w3SVCW3WPFileCacheFlushesTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.fileCacheQueriesTotal, c.w3SVCW3WPFileCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[FileCacheHitsTotal].FirstValue+app[FileCacheMissesTotal].FirstValue, app[w3SVCW3WPFileCacheHitsTotal].FirstValue+app[w3SVCW3WPFileCacheMissesTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.fileCacheHitsTotal, c.w3SVCW3WPFileCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[FileCacheHitsTotal].FirstValue, app[w3SVCW3WPFileCacheHitsTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.filesCached, c.w3SVCW3WPFilesCached,
prometheus.GaugeValue, prometheus.GaugeValue,
app[FilesCached].FirstValue, app[w3SVCW3WPFilesCached].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.filesCachedTotal, c.w3SVCW3WPFilesCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[FilesCachedTotal].FirstValue, app[w3SVCW3WPFilesCachedTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.filesFlushedTotal, c.w3SVCW3WPFilesFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[FilesFlushedTotal].FirstValue, app[w3SVCW3WPFilesFlushedTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.uriCacheFlushesTotal, c.w3SVCW3WPURICacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[URICacheFlushesTotal].FirstValue, app[w3SVCW3WPURICacheFlushesTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.uriCacheQueriesTotal, c.w3SVCW3WPURICacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[URICacheHitsTotal].FirstValue+app[URICacheMissesTotal].FirstValue, app[w3SVCW3WPURICacheHitsTotal].FirstValue+app[w3SVCW3WPURICacheMissesTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.uriCacheHitsTotal, c.w3SVCW3WPURICacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[URICacheHitsTotal].FirstValue, app[w3SVCW3WPURICacheHitsTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.urisCached, c.w3SVCW3WPURIsCached,
prometheus.GaugeValue, prometheus.GaugeValue,
app[URIsCached].FirstValue, app[w3SVCW3WPURIsCached].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.urisCachedTotal, c.w3SVCW3WPURIsCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[URIsCachedTotal].FirstValue, app[w3SVCW3WPURIsCachedTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.urisFlushedTotal, c.w3SVCW3WPURIsFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[URIsFlushedTotal].FirstValue, app[w3SVCW3WPURIsFlushedTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.metadataCached, c.w3SVCW3WPMetadataCached,
prometheus.GaugeValue, prometheus.GaugeValue,
app[MetadataCached].FirstValue, app[w3SVCW3WPMetadataCached].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.metadataCacheFlushes, c.w3SVCW3WPMetadataCacheFlushes,
prometheus.CounterValue, prometheus.CounterValue,
app[MetadataCacheFlushes].FirstValue, app[w3SVCW3WPMetadataCacheFlushes].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.metadataCacheQueriesTotal, c.w3SVCW3WPMetadataCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[MetaDataCacheHits].FirstValue+app[MetaDataCacheMisses].FirstValue, app[w3SVCW3WPMetaDataCacheHits].FirstValue+app[w3SVCW3WPMetaDataCacheMisses].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.metadataCacheHitsTotal, c.w3SVCW3WPMetadataCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[MetaDataCacheHits].FirstValue, app[w3SVCW3WPMetaDataCacheHits].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.metadataCachedTotal, c.w3SVCW3WPMetadataCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[MetadataCachedTotal].FirstValue, app[w3SVCW3WPMetadataCachedTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.metadataFlushedTotal, c.w3SVCW3WPMetadataFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[MetadataFlushedTotal].FirstValue, app[w3SVCW3WPMetadataFlushedTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputCacheActiveFlushedItems, c.w3SVCW3WPOutputCacheActiveFlushedItems,
prometheus.CounterValue, prometheus.CounterValue,
app[OutputCacheActiveFlushedItems].FirstValue, app[w3SVCW3WPOutputCacheActiveFlushedItems].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputCacheItems, c.w3SVCW3WPOutputCacheItems,
prometheus.CounterValue, prometheus.CounterValue,
app[OutputCacheItems].FirstValue, app[w3SVCW3WPOutputCacheItems].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputCacheMemoryUsage, c.w3SVCW3WPOutputCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
app[OutputCacheMemoryUsage].FirstValue, app[w3SVCW3WPOutputCacheMemoryUsage].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputCacheQueriesTotal, c.w3SVCW3WPOutputCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[OutputCacheHitsTotal].FirstValue+app[OutputCacheMissesTotal].FirstValue, app[w3SVCW3WPOutputCacheHitsTotal].FirstValue+app[w3SVCW3WPOutputCacheMissesTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputCacheHitsTotal, c.w3SVCW3WPOutputCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[OutputCacheHitsTotal].FirstValue, app[w3SVCW3WPOutputCacheHitsTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputCacheFlushedItemsTotal, c.w3SVCW3WPOutputCacheFlushedItemsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[OutputCacheFlushedItemsTotal].FirstValue, app[w3SVCW3WPOutputCacheFlushedItemsTotal].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputCacheFlushesTotal, c.w3SVCW3WPOutputCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[OutputCacheFlushesTotal].FirstValue, app[w3SVCW3WPOutputCacheFlushesTotal].FirstValue,
name, name,
pid, pid,
) )
if c.iisVersion.major >= 8 { if c.iisVersion.major >= 8 {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal, c.w3SVCW3WPRequestErrorsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[RequestErrors401].FirstValue, app[w3SVCW3WPRequestErrors401].FirstValue,
name, name,
pid, pid,
"401", "401",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal, c.w3SVCW3WPRequestErrorsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[RequestErrors403].FirstValue, app[w3SVCW3WPRequestErrors403].FirstValue,
name, name,
pid, pid,
"403", "403",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal, c.w3SVCW3WPRequestErrorsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[RequestErrors404].FirstValue, app[w3SVCW3WPRequestErrors404].FirstValue,
name, name,
pid, pid,
"404", "404",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal, c.w3SVCW3WPRequestErrorsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[RequestErrors500].FirstValue, app[w3SVCW3WPRequestErrors500].FirstValue,
name, name,
pid, pid,
"500", "500",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestErrorsTotal, c.w3SVCW3WPWebSocketRequestsActive,
prometheus.CounterValue, prometheus.CounterValue,
app[RequestErrors503].FirstValue, app[w3SVCW3WPWebSocketRequestsActive].FirstValue,
name,
pid,
"503",
)
ch <- prometheus.MustNewConstMetric(
c.webSocketRequestsActive,
prometheus.CounterValue,
app[WebSocketRequestsActive].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webSocketConnectionAttempts, c.w3SVCW3WPWebSocketConnectionAttempts,
prometheus.CounterValue, prometheus.CounterValue,
app[WebSocketConnectionAttempts].FirstValue, app[w3SVCW3WPWebSocketConnectionAttempts].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webSocketConnectionsAccepted, c.w3SVCW3WPWebSocketConnectionsAccepted,
prometheus.CounterValue, prometheus.CounterValue,
app[WebSocketConnectionsAccepted].FirstValue, app[w3SVCW3WPWebSocketConnectionsAccepted].FirstValue,
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webSocketConnectionsRejected, c.w3SVCW3WPWebSocketConnectionsRejected,
prometheus.CounterValue, prometheus.CounterValue,
app[WebSocketConnectionsRejected].FirstValue, app[w3SVCW3WPWebSocketConnectionsRejected].FirstValue,
name, name,
pid, pid,
) )

View File

@@ -26,243 +26,243 @@ import (
type collectorWebService struct { type collectorWebService struct {
perfDataCollectorWebService *perfdata.Collector perfDataCollectorWebService *perfdata.Collector
currentAnonymousUsers *prometheus.Desc webServiceCurrentAnonymousUsers *prometheus.Desc
currentBlockedAsyncIORequests *prometheus.Desc webServiceCurrentBlockedAsyncIORequests *prometheus.Desc
currentCGIRequests *prometheus.Desc webServiceCurrentCGIRequests *prometheus.Desc
currentConnections *prometheus.Desc webServiceCurrentConnections *prometheus.Desc
currentISAPIExtensionRequests *prometheus.Desc webServiceCurrentISAPIExtensionRequests *prometheus.Desc
currentNonAnonymousUsers *prometheus.Desc webServiceCurrentNonAnonymousUsers *prometheus.Desc
serviceUptime *prometheus.Desc webServiceServiceUptime *prometheus.Desc
totalBytesReceived *prometheus.Desc webServiceTotalBytesReceived *prometheus.Desc
totalBytesSent *prometheus.Desc webServiceTotalBytesSent *prometheus.Desc
totalAnonymousUsers *prometheus.Desc webServiceTotalAnonymousUsers *prometheus.Desc
totalBlockedAsyncIORequests *prometheus.Desc webServiceTotalBlockedAsyncIORequests *prometheus.Desc
totalCGIRequests *prometheus.Desc webServiceTotalCGIRequests *prometheus.Desc
totalConnectionAttemptsAllInstances *prometheus.Desc webServiceTotalConnectionAttemptsAllInstances *prometheus.Desc
totalRequests *prometheus.Desc webServiceTotalRequests *prometheus.Desc
totalFilesReceived *prometheus.Desc webServiceTotalFilesReceived *prometheus.Desc
totalFilesSent *prometheus.Desc webServiceTotalFilesSent *prometheus.Desc
totalISAPIExtensionRequests *prometheus.Desc webServiceTotalISAPIExtensionRequests *prometheus.Desc
totalLockedErrors *prometheus.Desc webServiceTotalLockedErrors *prometheus.Desc
totalLogonAttempts *prometheus.Desc webServiceTotalLogonAttempts *prometheus.Desc
totalNonAnonymousUsers *prometheus.Desc webServiceTotalNonAnonymousUsers *prometheus.Desc
totalNotFoundErrors *prometheus.Desc webServiceTotalNotFoundErrors *prometheus.Desc
totalRejectedAsyncIORequests *prometheus.Desc webServiceTotalRejectedAsyncIORequests *prometheus.Desc
} }
const ( const (
CurrentAnonymousUsers = "Current Anonymous Users" webServiceCurrentAnonymousUsers = "Current Anonymous Users"
CurrentBlockedAsyncIORequests = "Current Blocked Async I/O Requests" webServiceCurrentBlockedAsyncIORequests = "Current Blocked Async I/O Requests"
CurrentCGIRequests = "Current CGI Requests" webServiceCurrentCGIRequests = "Current CGI Requests"
CurrentConnections = "Current Connections" webServiceCurrentConnections = "Current Connections"
CurrentISAPIExtensionRequests = "Current ISAPI Extension Requests" webServiceCurrentISAPIExtensionRequests = "Current ISAPI Extension Requests"
CurrentNonAnonymousUsers = "Current NonAnonymous Users" webServiceCurrentNonAnonymousUsers = "Current NonAnonymous Users"
ServiceUptime = "Service Uptime" webServiceServiceUptime = "Service Uptime"
TotalBytesReceived = "Total Bytes Received" webServiceTotalBytesReceived = "Total Bytes Received"
TotalBytesSent = "Total Bytes Sent" webServiceTotalBytesSent = "Total Bytes Sent"
TotalAnonymousUsers = "Total Anonymous Users" webServiceTotalAnonymousUsers = "Total Anonymous Users"
TotalBlockedAsyncIORequests = "Total Blocked Async I/O Requests" webServiceTotalBlockedAsyncIORequests = "Total Blocked Async I/O Requests"
TotalCGIRequests = "Total CGI Requests" webServiceTotalCGIRequests = "Total CGI Requests"
TotalConnectionAttemptsAllInstances = "Total Connection Attempts (all instances)" webServiceTotalConnectionAttemptsAllInstances = "Total Connection Attempts (all instances)"
TotalFilesReceived = "Total Files Received" webServiceTotalFilesReceived = "Total Files Received"
TotalFilesSent = "Total Files Sent" webServiceTotalFilesSent = "Total Files Sent"
TotalISAPIExtensionRequests = "Total ISAPI Extension Requests" webServiceTotalISAPIExtensionRequests = "Total ISAPI Extension Requests"
TotalLockedErrors = "Total Locked Errors" webServiceTotalLockedErrors = "Total Locked Errors"
TotalLogonAttempts = "Total Logon Attempts" webServiceTotalLogonAttempts = "Total Logon Attempts"
TotalNonAnonymousUsers = "Total NonAnonymous Users" webServiceTotalNonAnonymousUsers = "Total NonAnonymous Users"
TotalNotFoundErrors = "Total Not Found Errors" webServiceTotalNotFoundErrors = "Total Not Found Errors"
TotalRejectedAsyncIORequests = "Total Rejected Async I/O Requests" webServiceTotalRejectedAsyncIORequests = "Total Rejected Async I/O Requests"
TotalCopyRequests = "Total Copy Requests" webServiceTotalCopyRequests = "Total Copy Requests"
TotalDeleteRequests = "Total Delete Requests" webServiceTotalDeleteRequests = "Total Delete Requests"
TotalGetRequests = "Total Get Requests" webServiceTotalGetRequests = "Total Get Requests"
TotalHeadRequests = "Total Head Requests" webServiceTotalHeadRequests = "Total Head Requests"
TotalLockRequests = "Total Lock Requests" webServiceTotalLockRequests = "Total Lock Requests"
TotalMkcolRequests = "Total Mkcol Requests" webServiceTotalMkcolRequests = "Total Mkcol Requests"
TotalMoveRequests = "Total Move Requests" webServiceTotalMoveRequests = "Total Move Requests"
TotalOptionsRequests = "Total Options Requests" webServiceTotalOptionsRequests = "Total Options Requests"
TotalOtherRequests = "Total Other Request Methods" webServiceTotalOtherRequests = "Total Other Request Methods"
TotalPostRequests = "Total Post Requests" webServiceTotalPostRequests = "Total Post Requests"
TotalPropfindRequests = "Total Propfind Requests" webServiceTotalPropfindRequests = "Total Propfind Requests"
TotalProppatchRequests = "Total Proppatch Requests" webServiceTotalProppatchRequests = "Total Proppatch Requests"
TotalPutRequests = "Total Put Requests" webServiceTotalPutRequests = "Total Put Requests"
TotalSearchRequests = "Total Search Requests" webServiceTotalSearchRequests = "Total Search Requests"
TotalTraceRequests = "Total Trace Requests" webServiceTotalTraceRequests = "Total Trace Requests"
TotalUnlockRequests = "Total Unlock Requests" webServiceTotalUnlockRequests = "Total Unlock Requests"
) )
func (c *Collector) buildWebService() error { func (c *Collector) buildWebService() error {
var err error var err error
c.perfDataCollectorWebService, err = perfdata.NewCollector("Web Service", perfdata.InstancesAll, []string{ c.perfDataCollectorWebService, err = perfdata.NewCollector("Web Service", perfdata.InstancesAll, []string{
CurrentAnonymousUsers, webServiceCurrentAnonymousUsers,
CurrentBlockedAsyncIORequests, webServiceCurrentBlockedAsyncIORequests,
CurrentCGIRequests, webServiceCurrentCGIRequests,
CurrentConnections, webServiceCurrentConnections,
CurrentISAPIExtensionRequests, webServiceCurrentISAPIExtensionRequests,
CurrentNonAnonymousUsers, webServiceCurrentNonAnonymousUsers,
ServiceUptime, webServiceServiceUptime,
TotalBytesReceived, webServiceTotalBytesReceived,
TotalBytesSent, webServiceTotalBytesSent,
TotalAnonymousUsers, webServiceTotalAnonymousUsers,
TotalBlockedAsyncIORequests, webServiceTotalBlockedAsyncIORequests,
TotalCGIRequests, webServiceTotalCGIRequests,
TotalConnectionAttemptsAllInstances, webServiceTotalConnectionAttemptsAllInstances,
TotalFilesReceived, webServiceTotalFilesReceived,
TotalFilesSent, webServiceTotalFilesSent,
TotalISAPIExtensionRequests, webServiceTotalISAPIExtensionRequests,
TotalLockedErrors, webServiceTotalLockedErrors,
TotalLogonAttempts, webServiceTotalLogonAttempts,
TotalNonAnonymousUsers, webServiceTotalNonAnonymousUsers,
TotalNotFoundErrors, webServiceTotalNotFoundErrors,
TotalRejectedAsyncIORequests, webServiceTotalRejectedAsyncIORequests,
TotalCopyRequests, webServiceTotalCopyRequests,
TotalDeleteRequests, webServiceTotalDeleteRequests,
TotalGetRequests, webServiceTotalGetRequests,
TotalHeadRequests, webServiceTotalHeadRequests,
TotalLockRequests, webServiceTotalLockRequests,
TotalMkcolRequests, webServiceTotalMkcolRequests,
TotalMoveRequests, webServiceTotalMoveRequests,
TotalOptionsRequests, webServiceTotalOptionsRequests,
TotalOtherRequests, webServiceTotalOtherRequests,
TotalPostRequests, webServiceTotalPostRequests,
TotalPropfindRequests, webServiceTotalPropfindRequests,
TotalProppatchRequests, webServiceTotalProppatchRequests,
TotalPutRequests, webServiceTotalPutRequests,
TotalSearchRequests, webServiceTotalSearchRequests,
TotalTraceRequests, webServiceTotalTraceRequests,
TotalUnlockRequests, webServiceTotalUnlockRequests,
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to create Web Service collector: %w", err) return fmt.Errorf("failed to create Web Service collector: %w", err)
} }
c.currentAnonymousUsers = prometheus.NewDesc( c.webServiceCurrentAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_anonymous_users"), prometheus.BuildFQName(types.Namespace, Name, "current_anonymous_users"),
"Number of users who currently have an anonymous connection using the Web service (WebService.CurrentAnonymousUsers)", "Number of users who currently have an anonymous connection using the Web service (WebService.CurrentAnonymousUsers)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.currentBlockedAsyncIORequests = prometheus.NewDesc( c.webServiceCurrentBlockedAsyncIORequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_blocked_async_io_requests"), prometheus.BuildFQName(types.Namespace, Name, "current_blocked_async_io_requests"),
"Current requests temporarily blocked due to bandwidth throttling settings (WebService.CurrentBlockedAsyncIORequests)", "Current requests temporarily blocked due to bandwidth throttling settings (WebService.CurrentBlockedAsyncIORequests)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.currentCGIRequests = prometheus.NewDesc( c.webServiceCurrentCGIRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_cgi_requests"), prometheus.BuildFQName(types.Namespace, Name, "current_cgi_requests"),
"Current number of CGI requests being simultaneously processed by the Web service (WebService.CurrentCGIRequests)", "Current number of CGI requests being simultaneously processed by the Web service (WebService.CurrentCGIRequests)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.currentConnections = prometheus.NewDesc( c.webServiceCurrentConnections = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_connections"), prometheus.BuildFQName(types.Namespace, Name, "current_connections"),
"Current number of connections established with the Web service (WebService.CurrentConnections)", "Current number of connections established with the Web service (WebService.CurrentConnections)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.currentISAPIExtensionRequests = prometheus.NewDesc( c.webServiceCurrentISAPIExtensionRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_isapi_extension_requests"), prometheus.BuildFQName(types.Namespace, Name, "current_isapi_extension_requests"),
"Current number of ISAPI requests being simultaneously processed by the Web service (WebService.CurrentISAPIExtensionRequests)", "Current number of ISAPI requests being simultaneously processed by the Web service (WebService.CurrentISAPIExtensionRequests)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.currentNonAnonymousUsers = prometheus.NewDesc( c.webServiceCurrentNonAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_non_anonymous_users"), 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)", "Number of users who currently have a non-anonymous connection using the Web service (WebService.CurrentNonAnonymousUsers)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.serviceUptime = prometheus.NewDesc( c.webServiceServiceUptime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "service_uptime"), prometheus.BuildFQName(types.Namespace, Name, "service_uptime"),
"Number of seconds the WebService is up (WebService.ServiceUptime)", "Number of seconds the WebService is up (WebService.ServiceUptime)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalBytesReceived = prometheus.NewDesc( c.webServiceTotalBytesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "received_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "received_bytes_total"),
"Number of data bytes that have been received by the Web service (WebService.TotalBytesReceived)", "Number of data bytes that have been received by the Web service (WebService.TotalBytesReceived)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalBytesSent = prometheus.NewDesc( c.webServiceTotalBytesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "sent_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "sent_bytes_total"),
"Number of data bytes that have been sent by the Web service (WebService.TotalBytesSent)", "Number of data bytes that have been sent by the Web service (WebService.TotalBytesSent)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalAnonymousUsers = prometheus.NewDesc( c.webServiceTotalAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "anonymous_users_total"), prometheus.BuildFQName(types.Namespace, Name, "anonymous_users_total"),
"Total number of users who established an anonymous connection with the Web service (WebService.TotalAnonymousUsers)", "Total number of users who established an anonymous connection with the Web service (WebService.TotalAnonymousUsers)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalBlockedAsyncIORequests = prometheus.NewDesc( c.webServiceTotalBlockedAsyncIORequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "blocked_async_io_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "blocked_async_io_requests_total"),
"Total requests temporarily blocked due to bandwidth throttling settings (WebService.TotalBlockedAsyncIORequests)", "Total requests temporarily blocked due to bandwidth throttling settings (WebService.TotalBlockedAsyncIORequests)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalCGIRequests = prometheus.NewDesc( c.webServiceTotalCGIRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cgi_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "cgi_requests_total"),
"Total CGI requests is the total number of CGI requests (WebService.TotalCGIRequests)", "Total CGI requests is the total number of CGI requests (WebService.TotalCGIRequests)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalConnectionAttemptsAllInstances = prometheus.NewDesc( c.webServiceTotalConnectionAttemptsAllInstances = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "connection_attempts_all_instances_total"), prometheus.BuildFQName(types.Namespace, Name, "connection_attempts_all_instances_total"),
"Number of connections that have been attempted using the Web service (WebService.TotalConnectionAttemptsAllInstances)", "Number of connections that have been attempted using the Web service (WebService.TotalConnectionAttemptsAllInstances)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalRequests = prometheus.NewDesc( c.webServiceTotalRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "requests_total"), prometheus.BuildFQName(types.Namespace, Name, "requests_total"),
"Number of HTTP requests (WebService.TotalRequests)", "Number of HTTP requests (WebService.TotalRequests)",
[]string{"site", "method"}, []string{"site", "method"},
nil, nil,
) )
c.totalFilesReceived = prometheus.NewDesc( c.webServiceTotalFilesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "files_received_total"), prometheus.BuildFQName(types.Namespace, Name, "files_received_total"),
"Number of files received by the Web service (WebService.TotalFilesReceived)", "Number of files received by the Web service (WebService.TotalFilesReceived)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalFilesSent = prometheus.NewDesc( c.webServiceTotalFilesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "files_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "files_sent_total"),
"Number of files sent by the Web service (WebService.TotalFilesSent)", "Number of files sent by the Web service (WebService.TotalFilesSent)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalISAPIExtensionRequests = prometheus.NewDesc( c.webServiceTotalISAPIExtensionRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ipapi_extension_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "ipapi_extension_requests_total"),
"ISAPI Extension Requests received (WebService.TotalISAPIExtensionRequests)", "ISAPI Extension Requests received (WebService.TotalISAPIExtensionRequests)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalLockedErrors = prometheus.NewDesc( c.webServiceTotalLockedErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "locked_errors_total"), 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)", "Number of requests that couldn't be satisfied by the server because the requested resource was locked (WebService.TotalLockedErrors)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalLogonAttempts = prometheus.NewDesc( c.webServiceTotalLogonAttempts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "logon_attempts_total"), prometheus.BuildFQName(types.Namespace, Name, "logon_attempts_total"),
"Number of logons attempts to the Web Service (WebService.TotalLogonAttempts)", "Number of logons attempts to the Web Service (WebService.TotalLogonAttempts)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalNonAnonymousUsers = prometheus.NewDesc( c.webServiceTotalNonAnonymousUsers = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "non_anonymous_users_total"), prometheus.BuildFQName(types.Namespace, Name, "non_anonymous_users_total"),
"Number of users who established a non-anonymous connection with the Web service (WebService.TotalNonAnonymousUsers)", "Number of users who established a non-anonymous connection with the Web service (WebService.TotalNonAnonymousUsers)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalNotFoundErrors = prometheus.NewDesc( c.webServiceTotalNotFoundErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "not_found_errors_total"), 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)", "Number of requests that couldn't be satisfied by the server because the requested document could not be found (WebService.TotalNotFoundErrors)",
[]string{"site"}, []string{"site"},
nil, nil,
) )
c.totalRejectedAsyncIORequests = prometheus.NewDesc( c.webServiceTotalRejectedAsyncIORequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rejected_async_io_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "rejected_async_io_requests_total"),
"Requests rejected due to bandwidth throttling settings (WebService.TotalRejectedAsyncIORequests)", "Requests rejected due to bandwidth throttling settings (WebService.TotalRejectedAsyncIORequests)",
[]string{"site"}, []string{"site"},
@@ -286,240 +286,240 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentAnonymousUsers, c.webServiceCurrentAnonymousUsers,
prometheus.GaugeValue, prometheus.GaugeValue,
app[CurrentAnonymousUsers].FirstValue, app[webServiceCurrentAnonymousUsers].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentBlockedAsyncIORequests, c.webServiceCurrentBlockedAsyncIORequests,
prometheus.GaugeValue, prometheus.GaugeValue,
app[CurrentBlockedAsyncIORequests].FirstValue, app[webServiceCurrentBlockedAsyncIORequests].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentCGIRequests, c.webServiceCurrentCGIRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
app[CurrentCGIRequests].FirstValue, app[webServiceCurrentCGIRequests].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentConnections, c.webServiceCurrentConnections,
prometheus.GaugeValue, prometheus.GaugeValue,
app[CurrentConnections].FirstValue, app[webServiceCurrentConnections].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentISAPIExtensionRequests, c.webServiceCurrentISAPIExtensionRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
app[CurrentISAPIExtensionRequests].FirstValue, app[webServiceCurrentISAPIExtensionRequests].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentNonAnonymousUsers, c.webServiceCurrentNonAnonymousUsers,
prometheus.GaugeValue, prometheus.GaugeValue,
app[CurrentNonAnonymousUsers].FirstValue, app[webServiceCurrentNonAnonymousUsers].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceUptime, c.webServiceServiceUptime,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ServiceUptime].FirstValue, app[webServiceServiceUptime].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalBytesReceived, c.webServiceTotalBytesReceived,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalBytesReceived].FirstValue, app[webServiceTotalBytesReceived].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalBytesSent, c.webServiceTotalBytesSent,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalBytesSent].FirstValue, app[webServiceTotalBytesSent].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalAnonymousUsers, c.webServiceTotalAnonymousUsers,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalAnonymousUsers].FirstValue, app[webServiceTotalAnonymousUsers].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalBlockedAsyncIORequests, c.webServiceTotalBlockedAsyncIORequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalBlockedAsyncIORequests].FirstValue, app[webServiceTotalBlockedAsyncIORequests].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalCGIRequests, c.webServiceTotalCGIRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalCGIRequests].FirstValue, app[webServiceTotalCGIRequests].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalConnectionAttemptsAllInstances, c.webServiceTotalConnectionAttemptsAllInstances,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalConnectionAttemptsAllInstances].FirstValue, app[webServiceTotalConnectionAttemptsAllInstances].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalFilesReceived, c.webServiceTotalFilesReceived,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalFilesReceived].FirstValue, app[webServiceTotalFilesReceived].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalFilesSent, c.webServiceTotalFilesSent,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalFilesSent].FirstValue, app[webServiceTotalFilesSent].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalISAPIExtensionRequests, c.webServiceTotalISAPIExtensionRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalISAPIExtensionRequests].FirstValue, app[webServiceTotalISAPIExtensionRequests].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalLockedErrors, c.webServiceTotalLockedErrors,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalLockedErrors].FirstValue, app[webServiceTotalLockedErrors].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalLogonAttempts, c.webServiceTotalLogonAttempts,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalLogonAttempts].FirstValue, app[webServiceTotalLogonAttempts].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalNonAnonymousUsers, c.webServiceTotalNonAnonymousUsers,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalNonAnonymousUsers].FirstValue, app[webServiceTotalNonAnonymousUsers].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalNotFoundErrors, c.webServiceTotalNotFoundErrors,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalNotFoundErrors].FirstValue, app[webServiceTotalNotFoundErrors].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRejectedAsyncIORequests, c.webServiceTotalRejectedAsyncIORequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalRejectedAsyncIORequests].FirstValue, app[webServiceTotalRejectedAsyncIORequests].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalOtherRequests].FirstValue, app[webServiceTotalOtherRequests].FirstValue,
name, name,
"other", "other",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalCopyRequests].FirstValue, app[webServiceTotalCopyRequests].FirstValue,
name, name,
"COPY", "COPY",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalDeleteRequests].FirstValue, app[webServiceTotalDeleteRequests].FirstValue,
name, name,
"DELETE", "DELETE",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalGetRequests].FirstValue, app[webServiceTotalGetRequests].FirstValue,
name, name,
"GET", "GET",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalHeadRequests].FirstValue, app[webServiceTotalHeadRequests].FirstValue,
name, name,
"HEAD", "HEAD",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalLockRequests].FirstValue, app[webServiceTotalLockRequests].FirstValue,
name, name,
"LOCK", "LOCK",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalMkcolRequests].FirstValue, app[webServiceTotalMkcolRequests].FirstValue,
name, name,
"MKCOL", "MKCOL",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalMoveRequests].FirstValue, app[webServiceTotalMoveRequests].FirstValue,
name, name,
"MOVE", "MOVE",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalOptionsRequests].FirstValue, app[webServiceTotalOptionsRequests].FirstValue,
name, name,
"OPTIONS", "OPTIONS",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalPostRequests].FirstValue, app[webServiceTotalPostRequests].FirstValue,
name, name,
"POST", "POST",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalPropfindRequests].FirstValue, app[webServiceTotalPropfindRequests].FirstValue,
name, name,
"PROPFIND", "PROPFIND",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalProppatchRequests].FirstValue, app[webServiceTotalProppatchRequests].FirstValue,
name, name,
"PROPPATCH", "PROPPATCH",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalPutRequests].FirstValue, app[webServiceTotalPutRequests].FirstValue,
name, name,
"PUT", "PUT",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalSearchRequests].FirstValue, app[webServiceTotalSearchRequests].FirstValue,
name, name,
"SEARCH", "SEARCH",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalTraceRequests].FirstValue, app[webServiceTotalTraceRequests].FirstValue,
name, name,
"TRACE", "TRACE",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
app[TotalUnlockRequests].FirstValue, app[webServiceTotalUnlockRequests].FirstValue,
name, name,
"UNLOCK", "UNLOCK",
) )

View File

@@ -24,7 +24,7 @@ import (
) )
type collectorWebServiceCache struct { type collectorWebServiceCache struct {
perfDataCollectorWebServiceCache *perfdata.Collector serviceCachePerfDataCollector *perfdata.Collector
serviceCacheActiveFlushedEntries *prometheus.Desc serviceCacheActiveFlushedEntries *prometheus.Desc
@@ -61,80 +61,80 @@ type collectorWebServiceCache struct {
} }
const ( const (
ServiceCacheActiveFlushedEntries = "Active Flushed Entries" serviceCacheActiveFlushedEntries = "Active Flushed Entries"
ServiceCacheCurrentFileCacheMemoryUsage = "Current File Cache Memory Usage" serviceCacheCurrentFileCacheMemoryUsage = "Current File Cache Memory Usage"
ServiceCacheMaximumFileCacheMemoryUsage = "Maximum File Cache Memory Usage" serviceCacheMaximumFileCacheMemoryUsage = "Maximum File Cache Memory Usage"
ServiceCacheFileCacheFlushesTotal = "File Cache Flushes" serviceCacheFileCacheFlushesTotal = "File Cache Flushes"
ServiceCacheFileCacheHitsTotal = "File Cache Hits" serviceCacheFileCacheHitsTotal = "File Cache Hits"
ServiceCacheFileCacheMissesTotal = "File Cache Misses" serviceCacheFileCacheMissesTotal = "File Cache Misses"
ServiceCacheFilesCached = "Current Files Cached" serviceCacheFilesCached = "Current Files Cached"
ServiceCacheFilesCachedTotal = "Total Files Cached" serviceCacheFilesCachedTotal = "Total Files Cached"
ServiceCacheFilesFlushedTotal = "Total Flushed Files" serviceCacheFilesFlushedTotal = "Total Flushed Files"
ServiceCacheURICacheFlushesTotal = "Total Flushed URIs" serviceCacheURICacheFlushesTotal = "Total Flushed URIs"
ServiceCacheURICacheFlushesTotalKernel = "Total Flushed URIs" serviceCacheURICacheFlushesTotalKernel = "Total Flushed URIs"
ServiceCacheURIsFlushedTotalKernel = "Kernel: Total Flushed URIs" serviceCacheURIsFlushedTotalKernel = "Kernel: Total Flushed URIs"
ServiceCacheURICacheHitsTotal = "URI Cache Hits" serviceCacheURICacheHitsTotal = "URI Cache Hits"
ServiceCacheURICacheHitsTotalKernel = "Kernel: URI Cache Hits" serviceCacheURICacheHitsTotalKernel = "Kernel: URI Cache Hits"
ServiceCacheURICacheMissesTotal = "URI Cache Misses" serviceCacheURICacheMissesTotal = "URI Cache Misses"
ServiceCacheURICacheMissesTotalKernel = "Kernel: URI Cache Misses" serviceCacheURICacheMissesTotalKernel = "Kernel: URI Cache Misses"
ServiceCacheURIsCached = "Current URIs Cached" serviceCacheURIsCached = "Current URIs Cached"
ServiceCacheURIsCachedKernel = "Kernel: Current URIs Cached" serviceCacheURIsCachedKernel = "Kernel: Current URIs Cached"
ServiceCacheURIsCachedTotal = "Total URIs Cached" serviceCacheURIsCachedTotal = "Total URIs Cached"
ServiceCacheURIsCachedTotalKernel = "Total URIs Cached" serviceCacheURIsCachedTotalKernel = "Total URIs Cached"
ServiceCacheURIsFlushedTotal = "Total Flushed URIs" serviceCacheURIsFlushedTotal = "Total Flushed URIs"
ServiceCacheMetaDataCacheHits = "Metadata Cache Hits" serviceCacheMetaDataCacheHits = "Metadata Cache Hits"
ServiceCacheMetaDataCacheMisses = "Metadata Cache Misses" serviceCacheMetaDataCacheMisses = "Metadata Cache Misses"
ServiceCacheMetadataCached = "Current Metadata Cached" serviceCacheMetadataCached = "Current Metadata Cached"
ServiceCacheMetadataCacheFlushes = "Metadata Cache Flushes" serviceCacheMetadataCacheFlushes = "Metadata Cache Flushes"
ServiceCacheMetadataCachedTotal = "Total Metadata Cached" serviceCacheMetadataCachedTotal = "Total Metadata Cached"
ServiceCacheMetadataFlushedTotal = "Total Flushed Metadata" serviceCacheMetadataFlushedTotal = "Total Flushed Metadata"
ServiceCacheOutputCacheActiveFlushedItems = "Output Cache Current Flushed Items" serviceCacheOutputCacheActiveFlushedItems = "Output Cache Current Flushed Items"
ServiceCacheOutputCacheItems = "Output Cache Current Items" serviceCacheOutputCacheItems = "Output Cache Current Items"
ServiceCacheOutputCacheMemoryUsage = "Output Cache Current Memory Usage" serviceCacheOutputCacheMemoryUsage = "Output Cache Current Memory Usage"
ServiceCacheOutputCacheHitsTotal = "Output Cache Total Hits" serviceCacheOutputCacheHitsTotal = "Output Cache Total Hits"
ServiceCacheOutputCacheMissesTotal = "Output Cache Total Misses" serviceCacheOutputCacheMissesTotal = "Output Cache Total Misses"
ServiceCacheOutputCacheFlushedItemsTotal = "Output Cache Total Flushed Items" serviceCacheOutputCacheFlushedItemsTotal = "Output Cache Total Flushed Items"
ServiceCacheOutputCacheFlushesTotal = "Output Cache Total Flushes" serviceCacheOutputCacheFlushesTotal = "Output Cache Total Flushes"
) )
func (c *Collector) buildWebServiceCache() error { func (c *Collector) buildWebServiceCache() error {
var err error var err error
c.perfDataCollectorWebService, err = perfdata.NewCollector("Web Service Cache", perfdata.InstancesAll, []string{ c.perfDataCollectorWebService, err = perfdata.NewCollector("Web Service Cache", perfdata.InstancesAll, []string{
ServiceCacheActiveFlushedEntries, serviceCacheActiveFlushedEntries,
ServiceCacheCurrentFileCacheMemoryUsage, serviceCacheCurrentFileCacheMemoryUsage,
ServiceCacheMaximumFileCacheMemoryUsage, serviceCacheMaximumFileCacheMemoryUsage,
ServiceCacheFileCacheFlushesTotal, serviceCacheFileCacheFlushesTotal,
ServiceCacheFileCacheHitsTotal, serviceCacheFileCacheHitsTotal,
ServiceCacheFileCacheMissesTotal, serviceCacheFileCacheMissesTotal,
ServiceCacheFilesCached, serviceCacheFilesCached,
ServiceCacheFilesCachedTotal, serviceCacheFilesCachedTotal,
ServiceCacheFilesFlushedTotal, serviceCacheFilesFlushedTotal,
ServiceCacheURICacheFlushesTotal, serviceCacheURICacheFlushesTotal,
ServiceCacheURICacheFlushesTotalKernel, serviceCacheURICacheFlushesTotalKernel,
ServiceCacheURIsFlushedTotalKernel, serviceCacheURIsFlushedTotalKernel,
ServiceCacheURICacheHitsTotal, serviceCacheURICacheHitsTotal,
ServiceCacheURICacheHitsTotalKernel, serviceCacheURICacheHitsTotalKernel,
ServiceCacheURICacheMissesTotal, serviceCacheURICacheMissesTotal,
ServiceCacheURICacheMissesTotalKernel, serviceCacheURICacheMissesTotalKernel,
ServiceCacheURIsCached, serviceCacheURIsCached,
ServiceCacheURIsCachedKernel, serviceCacheURIsCachedKernel,
ServiceCacheURIsCachedTotal, serviceCacheURIsCachedTotal,
ServiceCacheURIsCachedTotalKernel, serviceCacheURIsCachedTotalKernel,
ServiceCacheURIsFlushedTotal, serviceCacheURIsFlushedTotal,
ServiceCacheMetaDataCacheHits, serviceCacheMetaDataCacheHits,
ServiceCacheMetaDataCacheMisses, serviceCacheMetaDataCacheMisses,
ServiceCacheMetadataCached, serviceCacheMetadataCached,
ServiceCacheMetadataCacheFlushes, serviceCacheMetadataCacheFlushes,
ServiceCacheMetadataCachedTotal, serviceCacheMetadataCachedTotal,
ServiceCacheMetadataFlushedTotal, serviceCacheMetadataFlushedTotal,
ServiceCacheOutputCacheActiveFlushedItems, serviceCacheOutputCacheActiveFlushedItems,
ServiceCacheOutputCacheItems, serviceCacheOutputCacheItems,
ServiceCacheOutputCacheMemoryUsage, serviceCacheOutputCacheMemoryUsage,
ServiceCacheOutputCacheHitsTotal, serviceCacheOutputCacheHitsTotal,
ServiceCacheOutputCacheMissesTotal, serviceCacheOutputCacheMissesTotal,
ServiceCacheOutputCacheFlushedItemsTotal, serviceCacheOutputCacheFlushedItemsTotal,
ServiceCacheOutputCacheFlushesTotal, serviceCacheOutputCacheFlushesTotal,
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to create Web Service Cache collector: %w", err) return fmt.Errorf("failed to create Web Service Cache collector: %w", err)
@@ -329,184 +329,184 @@ func (c *Collector) collectWebServiceCache(ch chan<- prometheus.Metric) error {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheActiveFlushedEntries, c.serviceCacheActiveFlushedEntries,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ServiceCacheActiveFlushedEntries].FirstValue, app[serviceCacheActiveFlushedEntries].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheCurrentFileCacheMemoryUsage, c.serviceCacheCurrentFileCacheMemoryUsage,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ServiceCacheCurrentFileCacheMemoryUsage].FirstValue, app[serviceCacheCurrentFileCacheMemoryUsage].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMaximumFileCacheMemoryUsage, c.serviceCacheMaximumFileCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheMaximumFileCacheMemoryUsage].FirstValue, app[serviceCacheMaximumFileCacheMemoryUsage].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheFlushesTotal, c.serviceCacheFileCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheFileCacheFlushesTotal].FirstValue, app[serviceCacheFileCacheFlushesTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheQueriesTotal, c.serviceCacheFileCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheFileCacheHitsTotal].FirstValue+app[ServiceCacheFileCacheMissesTotal].FirstValue, app[serviceCacheFileCacheHitsTotal].FirstValue+app[serviceCacheFileCacheMissesTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheHitsTotal, c.serviceCacheFileCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheFileCacheHitsTotal].FirstValue, app[serviceCacheFileCacheHitsTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesCached, c.serviceCacheFilesCached,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ServiceCacheFilesCached].FirstValue, app[serviceCacheFilesCached].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesCachedTotal, c.serviceCacheFilesCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheFilesCachedTotal].FirstValue, app[serviceCacheFilesCachedTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesFlushedTotal, c.serviceCacheFilesFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheFilesFlushedTotal].FirstValue, app[serviceCacheFilesFlushedTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheFlushesTotal, c.serviceCacheURICacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURICacheFlushesTotal].FirstValue, app[serviceCacheURICacheFlushesTotal].FirstValue,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheFlushesTotal, c.serviceCacheURICacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURICacheFlushesTotalKernel].FirstValue, app[serviceCacheURICacheFlushesTotalKernel].FirstValue,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheQueriesTotal, c.serviceCacheURICacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotal].FirstValue+app[ServiceCacheURICacheMissesTotal].FirstValue, app[serviceCacheURICacheHitsTotal].FirstValue+app[serviceCacheURICacheMissesTotal].FirstValue,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheQueriesTotal, c.serviceCacheURICacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotalKernel].FirstValue+app[ServiceCacheURICacheMissesTotalKernel].FirstValue, app[serviceCacheURICacheHitsTotalKernel].FirstValue+app[serviceCacheURICacheMissesTotalKernel].FirstValue,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheHitsTotal, c.serviceCacheURICacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotal].FirstValue, app[serviceCacheURICacheHitsTotal].FirstValue,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheHitsTotal, c.serviceCacheURICacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURICacheHitsTotalKernel].FirstValue, app[serviceCacheURICacheHitsTotalKernel].FirstValue,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCached, c.serviceCacheURIsCached,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ServiceCacheURIsCached].FirstValue, app[serviceCacheURIsCached].FirstValue,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCached, c.serviceCacheURIsCached,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ServiceCacheURIsCachedKernel].FirstValue, app[serviceCacheURIsCachedKernel].FirstValue,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCachedTotal, c.serviceCacheURIsCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURIsCachedTotal].FirstValue, app[serviceCacheURIsCachedTotal].FirstValue,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCachedTotal, c.serviceCacheURIsCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURIsCachedTotalKernel].FirstValue, app[serviceCacheURIsCachedTotalKernel].FirstValue,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsFlushedTotal, c.serviceCacheURIsFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURIsFlushedTotal].FirstValue, app[serviceCacheURIsFlushedTotal].FirstValue,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsFlushedTotal, c.serviceCacheURIsFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheURIsFlushedTotalKernel].FirstValue, app[serviceCacheURIsFlushedTotalKernel].FirstValue,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCached, c.serviceCacheMetadataCached,
prometheus.GaugeValue, prometheus.GaugeValue,
app[ServiceCacheMetadataCached].FirstValue, app[serviceCacheMetadataCached].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheFlushes, c.serviceCacheMetadataCacheFlushes,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheMetadataCacheFlushes].FirstValue, app[serviceCacheMetadataCacheFlushes].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheQueriesTotal, c.serviceCacheMetadataCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheMetaDataCacheHits].FirstValue+app[ServiceCacheMetaDataCacheMisses].FirstValue, app[serviceCacheMetaDataCacheHits].FirstValue+app[serviceCacheMetaDataCacheMisses].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheHitsTotal, c.serviceCacheMetadataCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
0, // app[ServiceCacheMetadataCacheHitsTotal].FirstValue, 0, // app[serviceCacheMetadataCacheHitsTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCachedTotal, c.serviceCacheMetadataCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheMetadataCachedTotal].FirstValue, app[serviceCacheMetadataCachedTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataFlushedTotal, c.serviceCacheMetadataFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheMetadataFlushedTotal].FirstValue, app[serviceCacheMetadataFlushedTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheActiveFlushedItems, c.serviceCacheOutputCacheActiveFlushedItems,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheOutputCacheActiveFlushedItems].FirstValue, app[serviceCacheOutputCacheActiveFlushedItems].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheItems, c.serviceCacheOutputCacheItems,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheOutputCacheItems].FirstValue, app[serviceCacheOutputCacheItems].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheMemoryUsage, c.serviceCacheOutputCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheOutputCacheMemoryUsage].FirstValue, app[serviceCacheOutputCacheMemoryUsage].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheQueriesTotal, c.serviceCacheOutputCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheOutputCacheHitsTotal].FirstValue+app[ServiceCacheOutputCacheMissesTotal].FirstValue, app[serviceCacheOutputCacheHitsTotal].FirstValue+app[serviceCacheOutputCacheMissesTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheHitsTotal, c.serviceCacheOutputCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheOutputCacheHitsTotal].FirstValue, app[serviceCacheOutputCacheHitsTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheFlushedItemsTotal, c.serviceCacheOutputCacheFlushedItemsTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheOutputCacheFlushedItemsTotal].FirstValue, app[serviceCacheOutputCacheFlushedItemsTotal].FirstValue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheFlushesTotal, c.serviceCacheOutputCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
app[ServiceCacheOutputCacheFlushesTotal].FirstValue, app[serviceCacheOutputCacheFlushesTotal].FirstValue,
) )
} }

View File

@@ -27,6 +27,7 @@ import (
const Name = "license" const Name = "license"
//nolint:gochecknoglobals
var labelMap = map[slc.SL_GENUINE_STATE]string{ var labelMap = map[slc.SL_GENUINE_STATE]string{
slc.SL_GEN_STATE_IS_GENUINE: "genuine", slc.SL_GEN_STATE_IS_GENUINE: "genuine",
slc.SL_GEN_STATE_INVALID_LICENSE: "invalid_license", slc.SL_GEN_STATE_INVALID_LICENSE: "invalid_license",
@@ -37,6 +38,7 @@ var labelMap = map[slc.SL_GENUINE_STATE]string{
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics.

View File

@@ -39,6 +39,7 @@ type Config struct {
VolumeExclude *regexp.Regexp `yaml:"volume_exclude"` VolumeExclude *regexp.Regexp `yaml:"volume_exclude"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
VolumeInclude: types.RegExpAny, VolumeInclude: types.RegExpAny,
VolumeExclude: types.RegExpEmpty, VolumeExclude: types.RegExpEmpty,

View File

@@ -30,6 +30,7 @@ const Name = "logon"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.

View File

@@ -35,6 +35,7 @@ const Name = "memory"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for perflib Memory metrics. // A Collector is a Prometheus Collector for perflib Memory metrics.
@@ -430,7 +431,7 @@ func (c *Collector) collectPDH(ch chan<- prometheus.Metric) error {
data, ok := perfData[perfdata.InstanceEmpty] data, ok := perfData[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("perflib query for Memory returned empty result set") return fmt.Errorf("failed to collect Memory metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -42,6 +42,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{ CollectorsEnabled: []string{
subCollectorCluster, subCollectorCluster,

View File

@@ -662,6 +662,11 @@ func (c *Collector) buildCluster() error {
nil, nil,
) )
var dst []msClusterCluster
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.clusterMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }

View File

@@ -86,6 +86,12 @@ func (c *Collector) buildNetwork() error {
nil, nil,
) )
var dst []msClusterNetwork
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.networkMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }

View File

@@ -158,6 +158,12 @@ func (c *Collector) buildNode() error {
nil, nil,
) )
var dst []msClusterNode
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.nodeMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }

View File

@@ -190,6 +190,12 @@ func (c *Collector) buildResource() error {
nil, nil,
) )
var dst []msClusterResource
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }

View File

@@ -164,6 +164,12 @@ func (c *Collector) buildResourceGroup() error {
nil, nil,
) )
var dst []msClusterResourceGroup
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceGroupMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil return nil
} }

View File

@@ -16,8 +16,8 @@
package msmq package msmq
const ( const (
BytesInJournalQueue = "Bytes in Journal Queue" bytesInJournalQueue = "Bytes in Journal Queue"
BytesInQueue = "Bytes in Queue" bytesInQueue = "Bytes in Queue"
MessagesInJournalQueue = "Messages in Journal Queue" messagesInJournalQueue = "Messages in Journal Queue"
MessagesInQueue = "Messages in Queue" messagesInQueue = "Messages in Queue"
) )

View File

@@ -30,6 +30,7 @@ const Name = "msmq"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics.
@@ -75,10 +76,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
var err error var err error
c.perfDataCollector, err = perfdata.NewCollector("MSMQ Queue", perfdata.InstancesAll, []string{ c.perfDataCollector, err = perfdata.NewCollector("MSMQ Queue", perfdata.InstancesAll, []string{
BytesInJournalQueue, bytesInJournalQueue,
BytesInQueue, bytesInQueue,
MessagesInJournalQueue, messagesInJournalQueue,
MessagesInQueue, messagesInQueue,
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to create MSMQ Queue collector: %w", err) return fmt.Errorf("failed to create MSMQ Queue collector: %w", err)
@@ -124,28 +125,28 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesInJournalQueue, c.bytesInJournalQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
data[BytesInJournalQueue].FirstValue, data[bytesInJournalQueue].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesInQueue, c.bytesInQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
data[BytesInQueue].FirstValue, data[bytesInQueue].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesInJournalQueue, c.messagesInJournalQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
data[MessagesInJournalQueue].FirstValue, data[messagesInJournalQueue].FirstValue,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesInQueue, c.messagesInQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
data[MessagesInQueue].FirstValue, data[messagesInQueue].FirstValue,
name, name,
) )
} }

View File

@@ -59,6 +59,7 @@ type Config struct {
Port uint16 `yaml:"port"` Port uint16 `yaml:"port"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{ CollectorsEnabled: []string{
subCollectorAccessMethods, subCollectorAccessMethods,
@@ -175,7 +176,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
fileVersion, productVersion, err := c.getMSSQLServerVersion(c.config.Port) fileVersion, productVersion, err := c.getMSSQLServerVersion(c.config.Port)
if err != nil { if err != nil {
logger.Warn("Failed to get MSSQL server version", logger.Warn("failed to get MSSQL server version",
slog.Any("err", err), slog.Any("err", err),
slog.String("collector", Name), slog.String("collector", Name),
) )
@@ -334,7 +335,7 @@ func (c *Collector) getMSSQLInstances() mssqlInstancesType {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regKey, registry.QUERY_VALUE) k, err := registry.OpenKey(registry.LOCAL_MACHINE, regKey, registry.QUERY_VALUE)
if err != nil { if err != nil {
c.logger.Warn("Couldn't open registry to determine SQL instances", c.logger.Warn("couldn't open registry to determine SQL instances",
slog.Any("err", err), slog.Any("err", err),
) )
@@ -343,7 +344,7 @@ func (c *Collector) getMSSQLInstances() mssqlInstancesType {
defer func(key registry.Key) { defer func(key registry.Key) {
if err := key.Close(); err != nil { if err := key.Close(); err != nil {
c.logger.Warn("Failed to close registry key", c.logger.Warn("failed to close registry key",
slog.Any("err", err), slog.Any("err", err),
) )
} }
@@ -351,7 +352,7 @@ func (c *Collector) getMSSQLInstances() mssqlInstancesType {
instanceNames, err := k.ReadValueNames(0) instanceNames, err := k.ReadValueNames(0)
if err != nil { if err != nil {
c.logger.Warn("Can't ReadSubKeyNames", c.logger.Warn("can't ReadSubKeyNames",
slog.Any("err", err), slog.Any("err", err),
) )
@@ -364,7 +365,7 @@ func (c *Collector) getMSSQLInstances() mssqlInstancesType {
} }
} }
c.logger.Debug(fmt.Sprintf("Detected MSSQL Instances: %#v\n", sqlInstances)) c.logger.Debug(fmt.Sprintf("detected MSSQL Instances: %#v\n", sqlInstances))
return sqlInstances return sqlInstances
} }
@@ -401,23 +402,23 @@ func (c *Collector) collect(
begin := time.Now() begin := time.Now()
success := 1.0 success := 1.0
err := collectFn(ch, sqlInstance, perfDataCollector) err := collectFn(ch, sqlInstance, perfDataCollector)
duration := time.Since(begin).Seconds() duration := time.Since(begin)
if err != nil { if err != nil && !errors.Is(err, perfdata.ErrNoData) {
errs = append(errs, err) errs = append(errs, err)
success = 0.0 success = 0.0
c.logger.Error(fmt.Sprintf("mssql class collector %s failed after %fs", collector, duration), c.logger.Error(fmt.Sprintf("mssql class collector %s for instance %s failed after %s", collector, sqlInstance, duration),
slog.Any("err", err), slog.Any("err", err),
) )
} else { } else {
c.logger.Debug(fmt.Sprintf("mssql class collector %s succeeded after %fs.", collector, duration)) c.logger.Debug(fmt.Sprintf("mssql class collector %s for instance %s succeeded after %s.", collector, sqlInstance, duration))
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.mssqlScrapeDurationDesc, c.mssqlScrapeDurationDesc,
prometheus.GaugeValue, prometheus.GaugeValue,
duration, duration.Seconds(),
collector, sqlInstance, collector, sqlInstance,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -123,6 +124,7 @@ func (c *Collector) buildAccessMethods() error {
var err error var err error
c.accessMethodsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.accessMethodsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
accessMethodsAUCleanupbatchesPerSec, accessMethodsAUCleanupbatchesPerSec,
accessMethodsAUCleanupsPerSec, accessMethodsAUCleanupsPerSec,
@@ -173,7 +175,7 @@ func (c *Collector) buildAccessMethods() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.accessMethodsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Access Methods"), nil, counters) c.accessMethodsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Access Methods"), nil, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create AccessMethods collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create AccessMethods collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -443,7 +445,7 @@ func (c *Collector) buildAccessMethods() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectAccessMethods(ch chan<- prometheus.Metric) error { func (c *Collector) collectAccessMethods(ch chan<- prometheus.Metric) error {
@@ -451,6 +453,10 @@ func (c *Collector) collectAccessMethods(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectAccessMethodsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectAccessMethodsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "AccessMethods"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "AccessMethods"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -54,6 +55,7 @@ func (c *Collector) buildAvailabilityReplica() error {
var err error var err error
c.availabilityReplicaPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.availabilityReplicaPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
availReplicaBytesReceivedFromReplicaPerSec, availReplicaBytesReceivedFromReplicaPerSec,
availReplicaBytesSentToReplicaPerSec, availReplicaBytesSentToReplicaPerSec,
@@ -69,7 +71,7 @@ func (c *Collector) buildAvailabilityReplica() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.availabilityReplicaPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), perfdata.InstancesAll, counters) c.availabilityReplicaPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Availability Replica collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Availability Replica collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -129,7 +131,7 @@ func (c *Collector) buildAvailabilityReplica() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectAvailabilityReplica(ch chan<- prometheus.Metric) error { func (c *Collector) collectAvailabilityReplica(ch chan<- prometheus.Metric) error {
@@ -137,6 +139,10 @@ func (c *Collector) collectAvailabilityReplica(ch chan<- prometheus.Metric) erro
} }
func (c *Collector) collectAvailabilityReplicaInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectAvailabilityReplicaInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -81,6 +82,7 @@ func (c *Collector) buildBufferManager() error {
var err error var err error
c.bufManPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.bufManPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
bufManBackgroundWriterPagesPerSec, bufManBackgroundWriterPagesPerSec,
bufManBufferCacheHitRatio, bufManBufferCacheHitRatio,
@@ -110,7 +112,7 @@ func (c *Collector) buildBufferManager() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.bufManPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), nil, counters) c.bufManPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), nil, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Buffer Manager collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Buffer Manager collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -253,7 +255,7 @@ func (c *Collector) buildBufferManager() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectBufferManager(ch chan<- prometheus.Metric) error { func (c *Collector) collectBufferManager(ch chan<- prometheus.Metric) error {
@@ -261,6 +263,10 @@ func (c *Collector) collectBufferManager(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -131,6 +132,7 @@ func (c *Collector) buildDatabases() error {
var err error var err error
c.databasesPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.databasesPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
databasesActiveParallelRedoThreads, databasesActiveParallelRedoThreads,
databasesActiveTransactions, databasesActiveTransactions,
@@ -185,7 +187,7 @@ func (c *Collector) buildDatabases() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.databasesPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Databases"), perfdata.InstancesAll, counters) c.databasesPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Databases"), perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Databases collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Databases collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -478,7 +480,7 @@ func (c *Collector) buildDatabases() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectDatabases(ch chan<- prometheus.Metric) error { func (c *Collector) collectDatabases(ch chan<- prometheus.Metric) error {
@@ -486,6 +488,10 @@ func (c *Collector) collectDatabases(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Databases"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Databases"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -83,6 +84,7 @@ func (c *Collector) buildDatabaseReplica() error {
var err error var err error
c.dbReplicaPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.dbReplicaPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
dbReplicaDatabaseFlowControlDelay, dbReplicaDatabaseFlowControlDelay,
dbReplicaDatabaseFlowControlsPerSec, dbReplicaDatabaseFlowControlsPerSec,
@@ -113,7 +115,7 @@ func (c *Collector) buildDatabaseReplica() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.dbReplicaPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), perfdata.InstancesAll, counters) c.dbReplicaPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Database Replica collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Database Replica collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -263,7 +265,7 @@ func (c *Collector) buildDatabaseReplica() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectDatabaseReplica(ch chan<- prometheus.Metric) error { func (c *Collector) collectDatabaseReplica(ch chan<- prometheus.Metric) error {
@@ -271,6 +273,10 @@ func (c *Collector) collectDatabaseReplica(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectDatabaseReplicaInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectDatabaseReplicaInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -83,6 +84,7 @@ func (c *Collector) buildGeneralStatistics() error {
var err error var err error
c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
genStatsActiveTempTables, genStatsActiveTempTables,
genStatsConnectionResetPerSec, genStatsConnectionResetPerSec,
@@ -113,7 +115,7 @@ func (c *Collector) buildGeneralStatistics() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), nil, counters) c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), nil, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create General Statistics collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create General Statistics collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -263,7 +265,7 @@ func (c *Collector) buildGeneralStatistics() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectGeneralStatistics(ch chan<- prometheus.Metric) error { func (c *Collector) collectGeneralStatistics(ch chan<- prometheus.Metric) error {
@@ -271,6 +273,10 @@ func (c *Collector) collectGeneralStatistics(ch chan<- prometheus.Metric) error
} }
func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectGeneralStatisticsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -52,6 +53,7 @@ func (c *Collector) buildLocks() error {
var err error var err error
c.locksPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.locksPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
locksAverageWaitTimeMS, locksAverageWaitTimeMS,
locksAverageWaitTimeMSBase, locksAverageWaitTimeMSBase,
@@ -66,7 +68,7 @@ func (c *Collector) buildLocks() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.locksPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Locks"), perfdata.InstancesAll, counters) c.locksPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Locks"), perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Locks collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Locks collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -119,7 +121,7 @@ func (c *Collector) buildLocks() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectLocks(ch chan<- prometheus.Metric) error { func (c *Collector) collectLocks(ch chan<- prometheus.Metric) error {
@@ -127,6 +129,10 @@ func (c *Collector) collectLocks(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectLocksInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectLocksInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Locks"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Locks"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -75,6 +76,7 @@ func (c *Collector) buildMemoryManager() error {
var err error var err error
c.memMgrPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.memMgrPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
memMgrConnectionMemoryKB, memMgrConnectionMemoryKB,
memMgrDatabaseCacheMemoryKB, memMgrDatabaseCacheMemoryKB,
@@ -101,7 +103,7 @@ func (c *Collector) buildMemoryManager() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.memMgrPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Memory Manager"), perfdata.InstancesAll, counters) c.memMgrPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Memory Manager"), perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Locks collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Memory Manager collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -226,7 +228,7 @@ func (c *Collector) buildMemoryManager() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectMemoryManager(ch chan<- prometheus.Metric) error { func (c *Collector) collectMemoryManager(ch chan<- prometheus.Metric) error {
@@ -234,6 +236,10 @@ func (c *Collector) collectMemoryManager(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectMemoryManagerInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectMemoryManagerInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Memory Manager"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Memory Manager"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -38,6 +39,7 @@ func (c *Collector) buildSQLErrors() error {
var err error var err error
c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
sqlErrorsErrorsPerSec, sqlErrorsErrorsPerSec,
} }
@@ -45,7 +47,7 @@ func (c *Collector) buildSQLErrors() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), perfdata.InstancesAll, counters) c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create SQL Errors collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create SQL Errors collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -57,7 +59,7 @@ func (c *Collector) buildSQLErrors() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectSQLErrors(ch chan<- prometheus.Metric) error { func (c *Collector) collectSQLErrors(ch chan<- prometheus.Metric) error {
@@ -65,6 +67,10 @@ func (c *Collector) collectSQLErrors(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectSQLErrorsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectSQLErrorsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -57,6 +58,7 @@ func (c *Collector) buildSQLStats() error {
var err error var err error
c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
sqlStatsAutoParamAttemptsPerSec, sqlStatsAutoParamAttemptsPerSec,
sqlStatsBatchRequestsPerSec, sqlStatsBatchRequestsPerSec,
@@ -74,7 +76,7 @@ func (c *Collector) buildSQLStats() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), nil, counters) c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), nil, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create SQL Statistics collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create SQL Statistics collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -145,7 +147,7 @@ func (c *Collector) buildSQLStats() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectSQLStats(ch chan<- prometheus.Metric) error { func (c *Collector) collectSQLStats(ch chan<- prometheus.Metric) error {
@@ -153,6 +155,10 @@ func (c *Collector) collectSQLStats(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectSQLStatsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectSQLStatsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -61,6 +62,7 @@ func (c *Collector) buildTransactions() error {
var err error var err error
c.transactionsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.transactionsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
transactionsFreeSpaceintempdbKB, transactionsFreeSpaceintempdbKB,
transactionsLongestTransactionRunningTime, transactionsLongestTransactionRunningTime,
@@ -80,7 +82,7 @@ func (c *Collector) buildTransactions() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.transactionsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), nil, counters) c.transactionsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), nil, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Transactions collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Transactions collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -163,7 +165,7 @@ func (c *Collector) buildTransactions() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectTransactions(ch chan<- prometheus.Metric) error { func (c *Collector) collectTransactions(ch chan<- prometheus.Metric) error {
@@ -173,6 +175,10 @@ func (c *Collector) collectTransactions(ch chan<- prometheus.Metric) error {
// Win32_PerfRawData_MSSQLSERVER_Transactions docs: // Win32_PerfRawData_MSSQLSERVER_Transactions docs:
// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-transactions-object // - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-transactions-object
func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectTransactionsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), err)

View File

@@ -16,6 +16,7 @@
package mssql package mssql
import ( import (
"errors"
"fmt" "fmt"
"github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/perfdata"
@@ -59,6 +60,7 @@ func (c *Collector) buildWaitStats() error {
var err error var err error
c.waitStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances)) c.waitStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
errs := make([]error, 0, len(c.mssqlInstances))
counters := []string{ counters := []string{
waitStatsLockWaits, waitStatsLockWaits,
waitStatsMemoryGrantQueueWaits, waitStatsMemoryGrantQueueWaits,
@@ -77,7 +79,7 @@ func (c *Collector) buildWaitStats() error {
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
c.waitStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), perfdata.InstancesAll, counters) c.waitStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), perfdata.InstancesAll, counters)
if err != nil { if err != nil {
return fmt.Errorf("failed to create Wait Statistics collector for instance %s: %w", sqlInstance, err) errs = append(errs, fmt.Errorf("failed to create Wait Statistics collector for instance %s: %w", sqlInstance, err))
} }
} }
@@ -155,7 +157,7 @@ func (c *Collector) buildWaitStats() error {
nil, nil,
) )
return nil return errors.Join(errs...)
} }
func (c *Collector) collectWaitStats(ch chan<- prometheus.Metric) error { func (c *Collector) collectWaitStats(ch chan<- prometheus.Metric) error {
@@ -163,6 +165,10 @@ func (c *Collector) collectWaitStats(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectWaitStatsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error { func (c *Collector) collectWaitStatsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
if perfDataCollector == nil {
return types.ErrCollectorNotInitialized
}
perfData, err := perfDataCollector.Collect() perfData, err := perfDataCollector.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), err) return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), err)

View File

@@ -41,6 +41,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
NicExclude: types.RegExpEmpty, NicExclude: types.RegExpEmpty,
NicInclude: types.RegExpAny, NicInclude: types.RegExpAny,
@@ -392,6 +393,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
return nil return nil
} }
//nolint:gochecknoglobals
var addressFamily = map[uint16]string{ var addressFamily = map[uint16]string{
windows.AF_INET: "ipv4", windows.AF_INET: "ipv4",
windows.AF_INET6: "ipv6", windows.AF_INET6: "ipv6",

View File

@@ -19,7 +19,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"slices" "sort"
"sync"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
@@ -32,6 +33,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{ CollectorsEnabled: []string{
collectorClrExceptions, collectorClrExceptions,
@@ -61,6 +63,8 @@ type Collector struct {
config Config config Config
miSession *mi.Session miSession *mi.Session
collectorFns []func(ch chan<- prometheus.Metric) error
// clrexceptions // clrexceptions
numberOfExceptionsThrown *prometheus.Desc numberOfExceptionsThrown *prometheus.Desc
numberOfFilters *prometheus.Desc numberOfFilters *prometheus.Desc
@@ -152,42 +156,68 @@ func (c *Collector) Close() error {
} }
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error { func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
if len(c.config.CollectorsEnabled) == 0 {
return nil
}
if miSession == nil { if miSession == nil {
return errors.New("miSession is nil") return errors.New("miSession is nil")
} }
c.miSession = miSession c.miSession = miSession
if slices.Contains(c.config.CollectorsEnabled, collectorClrExceptions) { c.collectorFns = make([]func(ch chan<- prometheus.Metric) error, 0, len(c.config.CollectorsEnabled))
c.buildClrExceptions()
subCollectors := map[string]struct {
build func()
collect func(ch chan<- prometheus.Metric) error
close func()
}{
collectorClrExceptions: {
build: c.buildClrExceptions,
collect: c.collectClrExceptions,
},
collectorClrJIT: {
build: c.buildClrJIT,
collect: c.collectClrJIT,
},
collectorClrLoading: {
build: c.buildClrLoading,
collect: c.collectClrLoading,
},
collectorClrInterop: {
build: c.buildClrInterop,
collect: c.collectClrInterop,
},
collectorClrLocksAndThreads: {
build: c.buildClrLocksAndThreads,
collect: c.collectClrLocksAndThreads,
},
collectorClrMemory: {
build: c.buildClrMemory,
collect: c.collectClrMemory,
},
collectorClrRemoting: {
build: c.buildClrRemoting,
collect: c.collectClrRemoting,
},
collectorClrSecurity: {
build: c.buildClrSecurity,
collect: c.collectClrSecurity,
},
} }
if slices.Contains(c.config.CollectorsEnabled, collectorClrInterop) { // Result must order, to prevent test failures.
c.buildClrInterop() sort.Strings(c.config.CollectorsEnabled)
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrJIT) { for _, name := range c.config.CollectorsEnabled {
c.buildClrJIT() if _, ok := subCollectors[name]; !ok {
} return fmt.Errorf("unknown collector: %s", name)
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrLoading) { subCollectors[name].build()
c.buildClrLoading()
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrLocksAndThreads) { c.collectorFns = append(c.collectorFns, subCollectors[name].collect)
c.buildClrLocksAndThreads()
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrMemory) {
c.buildClrMemory()
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrRemoting) {
c.buildClrRemoting()
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrSecurity) {
c.buildClrSecurity()
} }
return nil return nil
@@ -196,57 +226,29 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var ( errCh := make(chan error, len(c.collectorFns))
err error errs := make([]error, 0, len(c.collectorFns))
errs []error
)
if slices.Contains(c.config.CollectorsEnabled, collectorClrExceptions) { wg := sync.WaitGroup{}
if err = c.collectClrExceptions(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrExceptions, err)) for _, fn := range c.collectorFns {
} wg.Add(1)
go func(fn func(ch chan<- prometheus.Metric) error) {
defer wg.Done()
if err := fn(ch); err != nil {
errCh <- err
}
}(fn)
} }
if slices.Contains(c.config.CollectorsEnabled, collectorClrInterop) { wg.Wait()
if err = c.collectClrInterop(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrInterop, err))
}
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrJIT) { close(errCh)
if err = c.collectClrJIT(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrJIT, err))
}
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrLoading) { for err := range errCh {
if err = c.collectClrLoading(ch); err != nil { errs = append(errs, err)
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrLoading, err))
}
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrLocksAndThreads) {
if err = c.collectClrLocksAndThreads(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrLocksAndThreads, err))
}
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrMemory) {
if err = c.collectClrMemory(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrMemory, err))
}
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrRemoting) {
if err = c.collectClrRemoting(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrRemoting, err))
}
}
if slices.Contains(c.config.CollectorsEnabled, collectorClrSecurity) {
if err = c.collectClrSecurity(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect %s metrics: %w", collectorClrSecurity, err))
}
} }
return errors.Join(errs...) return errors.Join(errs...)

View File

@@ -31,6 +31,7 @@ const Name = "nps"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
@@ -313,7 +314,7 @@ func (c *Collector) collectAccept(ch chan<- prometheus.Metric) error {
data, ok := perfData[perfdata.InstanceEmpty] data, ok := perfData[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("perflib query for NPS Authentication Server returned empty result set") return fmt.Errorf("failed to collect NPS Authentication Server metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -405,7 +406,7 @@ func (c *Collector) collectAccounting(ch chan<- prometheus.Metric) error {
data, ok := perfData[perfdata.InstanceEmpty] data, ok := perfData[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("perflib query for NPS Accounting Server returned empty result set") return fmt.Errorf("failed to collect NPS Accounting Server metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -37,6 +37,7 @@ const Name = "os"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.
@@ -109,26 +110,23 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
slog.String("collector", Name), slog.String("collector", Name),
) )
workstationInfo, err := netapi32.GetWorkstationInfo() productName, revision, err := c.getWindowsVersion()
if err != nil {
return fmt.Errorf("failed to get workstation info: %w", err)
}
productName, buildNumber, revision, err := c.getWindowsVersion()
if err != nil { if err != nil {
return fmt.Errorf("failed to get Windows version: %w", err) return fmt.Errorf("failed to get Windows version: %w", err)
} }
version := windows.RtlGetVersion()
c.osInformation = prometheus.NewDesc( c.osInformation = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"), prometheus.BuildFQName(types.Namespace, Name, "info"),
`Contains full product name & version in labels. Note that the "major_version" for Windows 11 is \"10\"; a build number greater than 22000 represents Windows 11.`, `Contains full product name & version in labels. Note that the "major_version" for Windows 11 is \"10\"; a build number greater than 22000 represents Windows 11.`,
nil, nil,
prometheus.Labels{ prometheus.Labels{
"product": productName, "product": productName,
"version": fmt.Sprintf("%d.%d.%s", workstationInfo.VersionMajor, workstationInfo.VersionMinor, buildNumber), "version": fmt.Sprintf("%d.%d.%d", version.MajorVersion, version.MinorVersion, version.BuildNumber),
"major_version": strconv.FormatUint(uint64(workstationInfo.VersionMajor), 10), "major_version": strconv.FormatUint(uint64(version.MajorVersion), 10),
"minor_version": strconv.FormatUint(uint64(workstationInfo.VersionMinor), 10), "minor_version": strconv.FormatUint(uint64(version.MinorVersion), 10),
"build_number": buildNumber, "build_number": strconv.FormatUint(uint64(version.BuildNumber), 10),
"revision": revision, "revision": revision,
}, },
) )
@@ -352,31 +350,26 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) {
) )
} }
func (c *Collector) getWindowsVersion() (string, string, string, error) { func (c *Collector) getWindowsVersion() (string, string, error) {
// Get build number and product name from registry // Get build number and product name from registry
ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
if err != nil { if err != nil {
return "", "", "", fmt.Errorf("failed to open registry key: %w", err) return "", "", fmt.Errorf("failed to open registry key: %w", err)
} }
defer ntKey.Close() defer ntKey.Close()
productName, _, err := ntKey.GetStringValue("ProductName") productName, _, err := ntKey.GetStringValue("ProductName")
if err != nil { if err != nil {
return "", "", "", err return "", "", err
}
buildNumber, _, err := ntKey.GetStringValue("CurrentBuildNumber")
if err != nil {
return "", "", "", err
} }
revision, _, err := ntKey.GetIntegerValue("UBR") revision, _, err := ntKey.GetIntegerValue("UBR")
if errors.Is(err, registry.ErrNotExist) { if errors.Is(err, registry.ErrNotExist) {
revision = 0 revision = 0
} else if err != nil { } else if err != nil {
return "", "", "", err return "", "", err
} }
return productName, buildNumber, strconv.FormatUint(revision, 10), nil return productName, strconv.FormatUint(revision, 10), nil
} }

View File

@@ -33,6 +33,7 @@ const Name = "pagefile"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.

View File

@@ -36,6 +36,7 @@ type Config struct {
Objects []Object `yaml:"objects"` Objects []Object `yaml:"objects"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
Objects: make([]Object, 0), Objects: make([]Object, 0),
} }

View File

@@ -35,6 +35,7 @@ type Config struct {
DiskExclude *regexp.Regexp `yaml:"disk_exclude"` DiskExclude *regexp.Regexp `yaml:"disk_exclude"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
DiskInclude: types.RegExpAny, DiskInclude: types.RegExpAny,
DiskExclude: types.RegExpEmpty, DiskExclude: types.RegExpEmpty,

View File

@@ -31,6 +31,8 @@ import (
const Name = "printer" const Name = "printer"
// printerStatusMap source: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-printer#:~:text=Power%20Save-,PrinterStatus,Offline%20(7),-PrintJobDataType // printerStatusMap source: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-printer#:~:text=Power%20Save-,PrinterStatus,Offline%20(7),-PrintJobDataType
//
//nolint:gochecknoglobals
var printerStatusMap = map[uint16]string{ var printerStatusMap = map[uint16]string{
1: "Other", 1: "Other",
2: "Unknown", 2: "Unknown",
@@ -46,6 +48,7 @@ type Config struct {
PrinterExclude *regexp.Regexp `yaml:"printer_exclude"` PrinterExclude *regexp.Regexp `yaml:"printer_exclude"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
PrinterInclude: types.RegExpAny, PrinterInclude: types.RegExpAny,
PrinterExclude: types.RegExpEmpty, PrinterExclude: types.RegExpEmpty,

View File

@@ -20,8 +20,10 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"regexp" "regexp"
"runtime/debug"
"strconv" "strconv"
"strings" "strings"
"sync"
"unsafe" "unsafe"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
@@ -40,6 +42,7 @@ type Config struct {
EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
ProcessInclude: types.RegExpAny, ProcessInclude: types.RegExpAny,
ProcessExclude: types.RegExpEmpty, ProcessExclude: types.RegExpEmpty,
@@ -56,7 +59,10 @@ type Collector struct {
perfDataCollector *perfdata.Collector perfDataCollector *perfdata.Collector
lookupCache map[string]string lookupCache sync.Map
workerCh chan processWorkerRequest
mu sync.RWMutex
info *prometheus.Desc info *prometheus.Desc
cpuTimeTotal *prometheus.Desc cpuTimeTotal *prometheus.Desc
@@ -76,6 +82,14 @@ type Collector struct {
workingSetPrivate *prometheus.Desc workingSetPrivate *prometheus.Desc
} }
type processWorkerRequest struct {
ch chan<- prometheus.Metric
name string
performanceCounterValues map[string]perfdata.CounterValue
waitGroup *sync.WaitGroup
workerProcesses []WorkerProcess
}
func New(config *Config) *Collector { func New(config *Config) *Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
@@ -115,7 +129,7 @@ func NewWithFlags(app *kingpin.Application) *Collector {
app.Flag( app.Flag(
"collector.process.iis", "collector.process.iis",
"Enable IIS worker process name queries. May cause the collector to leak memory.", "Enable IIS collectWorker process name queries. May cause the collector to leak memory.",
).Default(strconv.FormatBool(c.config.EnableWorkerProcess)).BoolVar(&c.config.EnableWorkerProcess) ).Default(strconv.FormatBool(c.config.EnableWorkerProcess)).BoolVar(&c.config.EnableWorkerProcess)
app.Action(func(*kingpin.ParseContext) error { app.Action(func(*kingpin.ParseContext) error {
@@ -142,8 +156,13 @@ func (c *Collector) GetName() string {
} }
func (c *Collector) Close() error { func (c *Collector) Close() error {
c.mu.Lock()
defer c.mu.Unlock()
c.perfDataCollector.Close() c.perfDataCollector.Close()
close(c.workerCh)
return nil return nil
} }
@@ -204,6 +223,14 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
return fmt.Errorf("failed to create Process collector: %w", err) return fmt.Errorf("failed to create Process collector: %w", err)
} }
c.workerCh = make(chan processWorkerRequest, 32)
c.mu = sync.RWMutex{}
c.lookupCache = sync.Map{}
for range 4 {
go c.collectWorker()
}
if c.config.ProcessInclude.String() == "^(?:.*)$" && c.config.ProcessExclude.String() == "^(?:)$" { if c.config.ProcessInclude.String() == "^(?:.*)$" && c.config.ProcessExclude.String() == "^(?:)$" {
logger.Warn("No filters specified for process collector. This will generate a very large number of metrics!") logger.Warn("No filters specified for process collector. This will generate a very large number of metrics!")
} }
@@ -306,8 +333,6 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
nil, nil,
) )
c.lookupCache = make(map[string]string)
return nil return nil
} }
@@ -333,6 +358,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
} }
} }
wg := &sync.WaitGroup{}
for name, process := range perfData { for name, process := range perfData {
// Duplicate processes are suffixed #, and an index number. Remove those. // Duplicate processes are suffixed #, and an index number. Remove those.
name, _, _ = strings.Cut(name, "#") name, _, _ = strings.Cut(name, "#")
@@ -341,194 +368,230 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
continue continue
} }
var pid uint64 wg.Add(1)
if v, ok := process[processID]; ok { c.workerCh <- processWorkerRequest{
pid = uint64(v.FirstValue) ch: ch,
} else if v, ok = process[idProcess]; ok { name: name,
pid = uint64(v.FirstValue) performanceCounterValues: process,
workerProcesses: workerProcesses,
waitGroup: wg,
} }
parentPID := strconv.FormatUint(uint64(process[creatingProcessID].FirstValue), 10)
if c.config.EnableWorkerProcess {
for _, wp := range workerProcesses {
if wp.ProcessId == pid {
name = strings.Join([]string{name, wp.AppPoolName}, "_")
break
}
}
}
cmdLine, processOwner, processGroupID, err := c.getProcessInformation(uint32(pid))
if err != nil {
c.logger.Debug("Failed to get process information",
slog.Uint64("pid", pid),
slog.Any("err", err),
)
}
pidString := strconv.FormatUint(pid, 10)
ch <- prometheus.MustNewConstMetric(
c.info,
prometheus.GaugeValue,
1.0,
name, pidString, parentPID, strconv.Itoa(int(processGroupID)), processOwner, cmdLine,
)
ch <- prometheus.MustNewConstMetric(
c.startTime,
prometheus.GaugeValue,
process[elapsedTime].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.handleCount,
prometheus.GaugeValue,
process[handleCount].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
process[percentPrivilegedTime].FirstValue,
name, pidString, "privileged",
)
ch <- prometheus.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
process[percentUserTime].FirstValue,
name, pidString, "user",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
process[ioOtherBytesPerSec].FirstValue,
name, pidString, "other",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
process[ioOtherOperationsPerSec].FirstValue,
name, pidString, "other",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
process[ioReadBytesPerSec].FirstValue,
name, pidString, "read",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
process[ioReadOperationsPerSec].FirstValue,
name, pidString, "read",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
process[ioWriteBytesPerSec].FirstValue,
name, pidString, "write",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
process[ioWriteOperationsPerSec].FirstValue,
name, pidString, "write",
)
ch <- prometheus.MustNewConstMetric(
c.pageFaultsTotal,
prometheus.CounterValue,
process[pageFaultsPerSec].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.pageFileBytes,
prometheus.GaugeValue,
process[pageFileBytes].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
process[poolNonPagedBytes].FirstValue,
name, pidString, "nonpaged",
)
ch <- prometheus.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
process[poolPagedBytes].FirstValue,
name, pidString, "paged",
)
ch <- prometheus.MustNewConstMetric(
c.priorityBase,
prometheus.GaugeValue,
process[priorityBase].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.privateBytes,
prometheus.GaugeValue,
process[privateBytes].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.threadCount,
prometheus.GaugeValue,
process[threadCount].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.virtualBytes,
prometheus.GaugeValue,
process[virtualBytes].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSetPrivate,
prometheus.GaugeValue,
process[workingSetPrivate].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSetPeak,
prometheus.GaugeValue,
process[workingSetPeak].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSet,
prometheus.GaugeValue,
process[workingSet].FirstValue,
name, pidString,
)
} }
wg.Wait()
return nil return nil
} }
func (c *Collector) collectWorker() {
defer func() {
if r := recover(); r != nil {
c.logger.Error("Worker panic",
slog.Any("panic", r),
slog.String("stack", string(debug.Stack())),
)
// Restart the collectWorker
go c.collectWorker()
}
}()
for req := range c.workerCh {
(func() {
defer req.waitGroup.Done()
ch := req.ch
name := req.name
process := req.performanceCounterValues
var pid uint64
if v, ok := process[processID]; ok {
pid = uint64(v.FirstValue)
} else if v, ok = process[idProcess]; ok {
pid = uint64(v.FirstValue)
}
parentPID := strconv.FormatUint(uint64(process[creatingProcessID].FirstValue), 10)
if c.config.EnableWorkerProcess {
for _, wp := range req.workerProcesses {
if wp.ProcessId == pid {
name = strings.Join([]string{name, wp.AppPoolName}, "_")
break
}
}
}
cmdLine, processOwner, processGroupID, err := c.getProcessInformation(uint32(pid))
if err != nil {
c.logger.Debug("Failed to get process information",
slog.Uint64("pid", pid),
slog.Any("err", err),
)
}
pidString := strconv.FormatUint(pid, 10)
ch <- prometheus.MustNewConstMetric(
c.info,
prometheus.GaugeValue,
1.0,
name, pidString, parentPID, strconv.Itoa(int(processGroupID)), processOwner, cmdLine,
)
ch <- prometheus.MustNewConstMetric(
c.startTime,
prometheus.GaugeValue,
process[elapsedTime].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.handleCount,
prometheus.GaugeValue,
process[handleCount].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
process[percentPrivilegedTime].FirstValue,
name, pidString, "privileged",
)
ch <- prometheus.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
process[percentUserTime].FirstValue,
name, pidString, "user",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
process[ioOtherBytesPerSec].FirstValue,
name, pidString, "other",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
process[ioOtherOperationsPerSec].FirstValue,
name, pidString, "other",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
process[ioReadBytesPerSec].FirstValue,
name, pidString, "read",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
process[ioReadOperationsPerSec].FirstValue,
name, pidString, "read",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
process[ioWriteBytesPerSec].FirstValue,
name, pidString, "write",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
process[ioWriteOperationsPerSec].FirstValue,
name, pidString, "write",
)
ch <- prometheus.MustNewConstMetric(
c.pageFaultsTotal,
prometheus.CounterValue,
process[pageFaultsPerSec].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.pageFileBytes,
prometheus.GaugeValue,
process[pageFileBytes].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
process[poolNonPagedBytes].FirstValue,
name, pidString, "nonpaged",
)
ch <- prometheus.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
process[poolPagedBytes].FirstValue,
name, pidString, "paged",
)
ch <- prometheus.MustNewConstMetric(
c.priorityBase,
prometheus.GaugeValue,
process[priorityBase].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.privateBytes,
prometheus.GaugeValue,
process[privateBytes].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.threadCount,
prometheus.GaugeValue,
process[threadCount].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.virtualBytes,
prometheus.GaugeValue,
process[virtualBytes].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSetPrivate,
prometheus.GaugeValue,
process[workingSetPrivate].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSetPeak,
prometheus.GaugeValue,
process[workingSetPeak].FirstValue,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSet,
prometheus.GaugeValue,
process[workingSet].FirstValue,
name, pidString,
)
})()
}
}
// ref: https://github.com/microsoft/hcsshim/blob/8beabacfc2d21767a07c20f8dd5f9f3932dbf305/internal/uvm/stats.go#L25 // ref: https://github.com/microsoft/hcsshim/blob/8beabacfc2d21767a07c20f8dd5f9f3932dbf305/internal/uvm/stats.go#L25
func (c *Collector) getProcessInformation(pid uint32) (string, string, uint32, error) { func (c *Collector) getProcessInformation(pid uint32) (string, string, uint32, error) {
if pid == 0 { if pid == 0 {
@@ -646,7 +709,14 @@ func (c *Collector) getProcessOwner(logger *slog.Logger, hProcess windows.Handle
sid := tokenUser.User.Sid.String() sid := tokenUser.User.Sid.String()
owner, ok := c.lookupCache[sid] var owner string
ownerVal, ok := c.lookupCache.Load(sid)
if ok {
owner, ok = ownerVal.(string)
}
if !ok { if !ok {
account, domain, _, err := tokenUser.User.Sid.LookupAccount("") account, domain, _, err := tokenUser.User.Sid.LookupAccount("")
if err != nil { if err != nil {
@@ -655,7 +725,7 @@ func (c *Collector) getProcessOwner(logger *slog.Logger, hProcess windows.Handle
owner = fmt.Sprintf(`%s\%s`, account, domain) owner = fmt.Sprintf(`%s\%s`, account, domain)
} }
c.lookupCache[sid] = owner c.lookupCache.Store(sid, owner)
} }
return owner, nil return owner, nil

View File

@@ -33,6 +33,7 @@ const Name = "remote_fx"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// Collector // Collector

View File

@@ -20,24 +20,30 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"regexp" "regexp"
"runtime"
"strings" "strings"
"sync"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-ole/go-ole" "github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil" "github.com/go-ole/go-ole/oleutil"
"github.com/prometheus-community/windows_exporter/internal/headers/schedule_service"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const Name = "scheduled_task" const (
Name = "scheduled_task"
workerCount = 4
)
type Config struct { type Config struct {
TaskExclude *regexp.Regexp `yaml:"task_exclude"` TaskExclude *regexp.Regexp `yaml:"task_exclude"`
TaskInclude *regexp.Regexp `yaml:"task_include"` TaskInclude *regexp.Regexp `yaml:"task_include"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
TaskExclude: types.RegExpEmpty, TaskExclude: types.RegExpEmpty,
TaskInclude: types.RegExpAny, TaskInclude: types.RegExpAny,
@@ -46,8 +52,11 @@ var ConfigDefaults = Config{
type Collector struct { type Collector struct {
config Config config Config
scheduledTasksReqCh chan struct{} logger *slog.Logger
scheduledTasksCh chan *scheduledTaskResults
scheduledTasksReqCh chan struct{}
scheduledTasksWorker chan scheduledTaskWorkerRequest
scheduledTasksCh chan scheduledTaskResults
lastResult *prometheus.Desc lastResult *prometheus.Desc
missedRuns *prometheus.Desc missedRuns *prometheus.Desc
@@ -73,6 +82,7 @@ const (
SCHED_S_TASK_HAS_NOT_RUN TaskResult = 0x00041303 SCHED_S_TASK_HAS_NOT_RUN TaskResult = 0x00041303
) )
//nolint:gochecknoglobals
var taskStates = []string{"disabled", "queued", "ready", "running", "unknown"} var taskStates = []string{"disabled", "queued", "ready", "running", "unknown"}
type scheduledTask struct { type scheduledTask struct {
@@ -85,8 +95,13 @@ type scheduledTask struct {
} }
type scheduledTaskResults struct { type scheduledTaskResults struct {
scheduledTasks []scheduledTask tasks []scheduledTask
err error err error
}
type scheduledTaskWorkerRequest struct {
folderPath string
results chan<- scheduledTaskResults
} }
func New(config *Config) *Collector { func New(config *Config) *Collector {
@@ -157,10 +172,13 @@ func (c *Collector) Close() error {
return nil return nil
} }
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
initErrCh := make(chan error) initErrCh := make(chan error)
c.scheduledTasksReqCh = make(chan struct{}) c.scheduledTasksReqCh = make(chan struct{})
c.scheduledTasksCh = make(chan *scheduledTaskResults) c.scheduledTasksCh = make(chan scheduledTaskResults)
c.scheduledTasksWorker = make(chan scheduledTaskWorkerRequest, 100)
go c.initializeScheduleService(initErrCh) go c.initializeScheduleService(initErrCh)
@@ -256,68 +274,41 @@ func (c *Collector) getScheduledTasks() ([]scheduledTask, error) {
return []scheduledTask{}, nil return []scheduledTask{}, nil
} }
if scheduledTasks == nil { return scheduledTasks.tasks, scheduledTasks.err
return nil, errors.New("scheduled tasks channel is nil")
}
if scheduledTasks.err != nil {
return nil, scheduledTasks.err
}
return scheduledTasks.scheduledTasks, scheduledTasks.err
} }
func (c *Collector) initializeScheduleService(initErrCh chan<- error) { func (c *Collector) initializeScheduleService(initErrCh chan<- error) {
// The only way to run WMI queries in parallel while being thread-safe is to service := schedule_service.New()
// ensure the CoInitialize[Ex]() call is bound to its current OS thread. if err := service.Connect(); err != nil {
// Otherwise, attempting to initialize and run parallel queries across initErrCh <- fmt.Errorf("failed to connect to schedule service: %w", err)
// goroutines will result in protected memory errors.
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil { return
var oleCode *ole.OleError }
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != 0x00000001 {
initErrCh <- err
return defer service.Close()
errs := make([]error, 0, workerCount)
for range workerCount {
errCh := make(chan error, workerCount)
go c.collectWorker(errCh)
if err := <-errCh; err != nil {
errs = append(errs, err)
} }
} }
defer ole.CoUninitialize() if err := errors.Join(errs...); err != nil {
scheduleClassID, err := ole.ClassIDFrom("Schedule.Service.1")
if err != nil {
initErrCh <- err initErrCh <- err
return return
} }
taskSchedulerObj, err := ole.CreateInstance(scheduleClassID, nil)
if err != nil || taskSchedulerObj == nil {
initErrCh <- err
return
}
defer taskSchedulerObj.Release()
taskServiceObj := taskSchedulerObj.MustQueryInterface(ole.IID_IDispatch)
defer taskServiceObj.Release()
taskService, err := oleutil.CallMethod(taskServiceObj, "Connect")
if err != nil {
initErrCh <- err
return
}
defer func(taskService *ole.VARIANT) {
_ = taskService.Clear()
}(taskService)
close(initErrCh) close(initErrCh)
scheduledTasks := make([]scheduledTask, 0, 100) taskServiceObj := service.GetOLETaskServiceObj()
scheduledTasks := make([]scheduledTask, 0, 500)
for range c.scheduledTasksReqCh { for range c.scheduledTasksReqCh {
func() { func() {
@@ -327,30 +318,102 @@ func (c *Collector) initializeScheduleService(initErrCh chan<- error) {
res, err := oleutil.CallMethod(taskServiceObj, "GetFolder", `\`) res, err := oleutil.CallMethod(taskServiceObj, "GetFolder", `\`)
if err != nil { if err != nil {
c.scheduledTasksCh <- &scheduledTaskResults{err: err} c.scheduledTasksCh <- scheduledTaskResults{err: err}
return
} }
rootFolderObj := res.ToIDispatch() rootFolderObj := res.ToIDispatch()
defer rootFolderObj.Release() defer rootFolderObj.Release()
err = fetchTasksRecursively(rootFolderObj, &scheduledTasks) errs := make([]error, 0)
scheduledTasksWorkerResults := make(chan scheduledTaskResults)
c.scheduledTasksCh <- &scheduledTaskResults{scheduledTasks: scheduledTasks, err: err} wg := &sync.WaitGroup{}
go func() {
for workerResults := range scheduledTasksWorkerResults {
wg.Done()
if workerResults.err != nil {
errs = append(errs, workerResults.err)
}
if workerResults.tasks != nil {
errs = append(errs, workerResults.err)
scheduledTasks = append(scheduledTasks, workerResults.tasks...)
}
}
}()
if err := c.fetchRecursively(rootFolderObj, wg, scheduledTasksWorkerResults); err != nil {
errs = append(errs, err)
}
wg.Wait()
close(scheduledTasksWorkerResults)
c.scheduledTasksCh <- scheduledTaskResults{tasks: scheduledTasks, err: errors.Join(errs...)}
}() }()
} }
close(c.scheduledTasksCh) close(c.scheduledTasksCh)
close(c.scheduledTasksWorker)
c.scheduledTasksCh = nil c.scheduledTasksCh = nil
c.scheduledTasksWorker = nil
} }
func fetchTasksRecursively(folder *ole.IDispatch, scheduledTasks *[]scheduledTask) error { func (c *Collector) collectWorker(errCh chan<- error) {
if err := fetchTasksInFolder(folder, scheduledTasks); err != nil { defer func() {
return err if r := recover(); r != nil {
c.logger.Error("worker panic",
slog.Any("panic", r),
)
errCh := make(chan error, 1)
// Restart the collectWorker
go c.collectWorker(errCh)
if err := <-errCh; err != nil {
c.logger.Error("failed to restart worker",
slog.Any("err", err),
)
}
}
}()
service := schedule_service.New()
if err := service.Connect(); err != nil {
errCh <- fmt.Errorf("failed to connect to schedule service: %w", err)
return
} }
close(errCh)
defer service.Close()
taskServiceObj := service.GetOLETaskServiceObj()
for task := range c.scheduledTasksWorker {
scheduledTasks, err := fetchTasksInFolder(taskServiceObj, task.folderPath)
task.results <- scheduledTaskResults{tasks: scheduledTasks, err: err}
}
}
func (c *Collector) fetchRecursively(folder *ole.IDispatch, wg *sync.WaitGroup, results chan<- scheduledTaskResults) error {
folderPathVariant, err := oleutil.GetProperty(folder, "Path")
if err != nil {
return fmt.Errorf("failed to get folder path: %w", err)
}
folderPath := folderPathVariant.ToString()
wg.Add(1)
c.scheduledTasksWorker <- scheduledTaskWorkerRequest{folderPath: folderPath, results: results}
res, err := oleutil.CallMethod(folder, "GetFolders", 1) res, err := oleutil.CallMethod(folder, "GetFolders", 1)
if err != nil { if err != nil {
return err return err
@@ -359,25 +422,41 @@ func fetchTasksRecursively(folder *ole.IDispatch, scheduledTasks *[]scheduledTas
subFolders := res.ToIDispatch() subFolders := res.ToIDispatch()
defer subFolders.Release() defer subFolders.Release()
err = oleutil.ForEach(subFolders, func(v *ole.VARIANT) error { return oleutil.ForEach(subFolders, func(v *ole.VARIANT) error {
subFolder := v.ToIDispatch() subFolder := v.ToIDispatch()
defer subFolder.Release() defer subFolder.Release()
return fetchTasksRecursively(subFolder, scheduledTasks) return c.fetchRecursively(subFolder, wg, results)
}) })
return err
} }
func fetchTasksInFolder(folder *ole.IDispatch, scheduledTasks *[]scheduledTask) error { func fetchTasksInFolder(taskServiceObj *ole.IDispatch, folderPath string) ([]scheduledTask, error) {
res, err := oleutil.CallMethod(folder, "GetTasks", 1) folderObjRes, err := oleutil.CallMethod(taskServiceObj, "GetFolder", folderPath)
if err != nil { if err != nil {
return err return nil, fmt.Errorf("failed to get folder %s: %w", folderPath, err)
} }
tasks := res.ToIDispatch() folderObj := folderObjRes.ToIDispatch()
defer folderObj.Release()
tasksRes, err := oleutil.CallMethod(folderObj, "GetTasks", 1)
if err != nil {
return nil, fmt.Errorf("failed to get tasks in folder %s: %w", folderPath, err)
}
tasks := tasksRes.ToIDispatch()
defer tasks.Release() defer tasks.Release()
// Get task count
countVariant, err := oleutil.GetProperty(tasks, "Count")
if err != nil {
return nil, fmt.Errorf("failed to get task count: %w", err)
}
taskCount := int(countVariant.Val)
scheduledTasks := make([]scheduledTask, 0, taskCount)
err = oleutil.ForEach(tasks, func(v *ole.VARIANT) error { err = oleutil.ForEach(tasks, func(v *ole.VARIANT) error {
task := v.ToIDispatch() task := v.ToIDispatch()
defer task.Release() defer task.Release()
@@ -387,12 +466,15 @@ func fetchTasksInFolder(folder *ole.IDispatch, scheduledTasks *[]scheduledTask)
return err return err
} }
*scheduledTasks = append(*scheduledTasks, parsedTask) scheduledTasks = append(scheduledTasks, parsedTask)
return nil return nil
}) })
if err != nil {
return nil, fmt.Errorf("failed to iterate over tasks: %w", err)
}
return err return scheduledTasks, nil
} }
func parseTask(task *ole.IDispatch) (scheduledTask, error) { func parseTask(task *ole.IDispatch) (scheduledTask, error) {

View File

@@ -39,6 +39,7 @@ type Config struct {
ServiceExclude *regexp.Regexp `yaml:"service_exclude"` ServiceExclude *regexp.Regexp `yaml:"service_exclude"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
ServiceInclude: types.RegExpAny, ServiceInclude: types.RegExpAny,
ServiceExclude: types.RegExpEmpty, ServiceExclude: types.RegExpEmpty,

View File

@@ -30,6 +30,7 @@ const Name = "smb"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
@@ -133,7 +134,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
nil, nil,
) )
c.filesOpened = prometheus.NewDesc( c.filesOpened = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "server_shares_filed_opened_count_total"), prometheus.BuildFQName(types.Namespace, Name, "server_shares_files_opened_count_total"),
"Files opened on the SMB Server Share", "Files opened on the SMB Server Share",
[]string{"share"}, []string{"share"},
nil, nil,

View File

@@ -33,6 +33,7 @@ const (
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {

View File

@@ -34,6 +34,7 @@ type Config struct {
ServerExclude *regexp.Regexp `yaml:"server_exclude"` ServerExclude *regexp.Regexp `yaml:"server_exclude"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
ServerInclude: types.RegExpAny, ServerInclude: types.RegExpAny,
ServerExclude: types.RegExpEmpty, ServerExclude: types.RegExpEmpty,

View File

@@ -31,6 +31,7 @@ const Name = "system"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.

View File

@@ -37,6 +37,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{ CollectorsEnabled: []string{
"metrics", "metrics",
@@ -248,7 +249,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
return nil return nil
} }
func (c *Collector) writeTCPCounters(ch chan<- prometheus.Metric, metrics map[string]perfdata.CounterValues, labels []string) { func (c *Collector) writeTCPCounters(ch chan<- prometheus.Metric, metrics map[string]perfdata.CounterValue, labels []string) {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.connectionFailures, c.connectionFailures,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -39,6 +39,7 @@ const (
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Win32_ServerFeature struct { type Win32_ServerFeature struct {

View File

@@ -42,6 +42,7 @@ type Config struct {
TextFileDirectories []string `yaml:"text_file_directories"` TextFileDirectories []string `yaml:"text_file_directories"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
TextFileDirectories: []string{getDefaultPath()}, TextFileDirectories: []string{getDefaultPath()},
} }

View File

@@ -29,6 +29,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
//nolint:gochecknoglobals
var baseDir = "../../../tools/textfile-test" var baseDir = "../../../tools/textfile-test"
//nolint:paralleltest //nolint:paralleltest

View File

@@ -0,0 +1,20 @@
// Copyright 2024 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package thermalzone
const (
highPrecisionTemperature = "High Precision Temperature"
percentPassiveLimit = "% Passive Limit"
throttleReasons = "Throttle Reasons"
)

View File

@@ -16,12 +16,12 @@
package thermalzone package thermalzone
import ( import (
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
@@ -30,13 +30,14 @@ const Name = "thermalzone"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics.
type Collector struct { type Collector struct {
config Config config Config
miSession *mi.Session
miQuery mi.Query perfDataCollector *perfdata.Collector
percentPassiveLimit *prometheus.Desc percentPassiveLimit *prometheus.Desc
temperature *prometheus.Desc temperature *prometheus.Desc
@@ -67,19 +68,18 @@ func (c *Collector) Close() error {
return nil return nil
} }
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
if miSession == nil { var err error
return errors.New("miSession is nil")
}
miQuery, err := mi.NewQuery("SELECT Name, HighPrecisionTemperature, PercentPassiveLimit, ThrottleReasons FROM Win32_PerfRawData_Counters_ThermalZoneInformation") c.perfDataCollector, err = perfdata.NewCollector("Thermal Zone Information", perfdata.InstancesAll, []string{
highPrecisionTemperature,
percentPassiveLimit,
throttleReasons,
})
if err != nil { if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err) return fmt.Errorf("failed to create Thermal Zone Information collector: %w", err)
} }
c.miQuery = miQuery
c.miSession = miSession
c.temperature = prometheus.NewDesc( c.temperature = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "temperature_celsius"), prometheus.BuildFQName(types.Namespace, Name, "temperature_celsius"),
"(Temperature)", "(Temperature)",
@@ -111,53 +111,32 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
if err := c.collect(ch); err != nil { perfData, err := c.perfDataCollector.Collect()
return fmt.Errorf("failed collecting thermalzone metrics: %w", err) if err != nil {
return fmt.Errorf("failed to collect Thermal Zone Information metrics: %w", err)
} }
return nil for sensorName, data := range perfData {
}
// Win32_PerfRawData_Counters_ThermalZoneInformation docs:
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_thermalzoneinformation/
type Win32_PerfRawData_Counters_ThermalZoneInformation struct {
Name string `mi:"Name"`
HighPrecisionTemperature uint32 `mi:"HighPrecisionTemperature"`
PercentPassiveLimit uint32 `mi:"PercentPassiveLimit"`
ThrottleReasons uint32 `mi:"ThrottleReasons"`
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_Counters_ThermalZoneInformation
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
if len(dst) == 0 {
return errors.New("WMI query returned empty result set")
}
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( ch <- prometheus.MustNewConstMetric(
c.temperature, c.temperature,
prometheus.GaugeValue, prometheus.GaugeValue,
(float64(info.HighPrecisionTemperature)/10.0)-273.15, (data[highPrecisionTemperature].FirstValue/10.0)-273.15,
info.Name, sensorName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.percentPassiveLimit, c.percentPassiveLimit,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(info.PercentPassiveLimit), data[percentPassiveLimit].FirstValue,
info.Name, sensorName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.throttleReasons, c.throttleReasons,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(info.ThrottleReasons), data[throttleReasons].FirstValue,
info.Name, sensorName,
) )
} }

View File

@@ -43,6 +43,7 @@ type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{ CollectorsEnabled: []string{
collectorSystemTime, collectorSystemTime,
@@ -242,7 +243,7 @@ func (c *Collector) collectNTP(ch chan<- prometheus.Metric) error {
data, ok := perfData[perfdata.InstanceEmpty] data, ok := perfData[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("query for Windows Time Service returned empty result set") return fmt.Errorf("failed to collect VM Memory metrics: %w", err)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -31,6 +31,7 @@ const Name = "udp"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics.
@@ -157,7 +158,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
return nil return nil
} }
func (c *Collector) writeUDPCounters(ch chan<- prometheus.Metric, metrics map[string]perfdata.CounterValues, labels []string) { func (c *Collector) writeUDPCounters(ch chan<- prometheus.Metric, metrics map[string]perfdata.CounterValue, labels []string) {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.datagramsNoPortTotal, c.datagramsNoPortTotal,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -41,6 +41,7 @@ type Config struct {
scrapeInterval time.Duration `yaml:"scrape_interval"` scrapeInterval time.Duration `yaml:"scrape_interval"`
} }
//nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
online: false, online: false,
scrapeInterval: 6 * time.Hour, scrapeInterval: 6 * time.Hour,

View File

@@ -32,6 +32,7 @@ const Name = "vmware"
type Config struct{} type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics.
@@ -266,7 +267,7 @@ func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
data, ok := perfData[perfdata.InstanceEmpty] data, ok := perfData[perfdata.InstanceEmpty]
if !ok { if !ok {
return errors.New("query for VM Memory returned empty result set") return fmt.Errorf("failed to collect VM Memory metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -347,12 +348,12 @@ func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
func (c *Collector) collectCpu(ch chan<- prometheus.Metric) error { func (c *Collector) collectCpu(ch chan<- prometheus.Metric) error {
perfData, err := c.perfDataCollectorCPU.Collect() perfData, err := c.perfDataCollectorCPU.Collect()
if err != nil { if err != nil {
return fmt.Errorf("failed to collect VM Memory metrics: %w", err) return fmt.Errorf("failed to collect VM CPU metrics: %w", err)
} }
data, ok := perfData[perfdata.InstanceTotal] data, ok := perfData[perfdata.InstanceTotal]
if !ok { if !ok {
return errors.New("query for VM CPU returned empty result set") return fmt.Errorf("failed to collect VM CPU metrics: %w", types.ErrNoData)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -23,6 +23,7 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
//nolint:gochecknoglobals
var ( var (
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
procGetExtendedTcpTable = modiphlpapi.NewProc("GetExtendedTcpTable") procGetExtendedTcpTable = modiphlpapi.NewProc("GetExtendedTcpTable")

View File

@@ -21,6 +21,7 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
//nolint:gochecknoglobals
var ( var (
kernel32 = windows.NewLazySystemDLL("kernel32.dll") kernel32 = windows.NewLazySystemDLL("kernel32.dll")

View File

@@ -45,6 +45,7 @@ type WorkstationInfo struct {
LoggedOnUsers uint32 LoggedOnUsers uint32
} }
//nolint:gochecknoglobals
var ( var (
netapi32 = windows.NewLazySystemDLL("netapi32") netapi32 = windows.NewLazySystemDLL("netapi32")
procNetWkstaGetInfo = netapi32.NewProc("NetWkstaGetInfo") procNetWkstaGetInfo = netapi32.NewProc("NetWkstaGetInfo")
@@ -53,6 +54,8 @@ var (
// NetApiStatus is a map of Network Management Error Codes. // NetApiStatus is a map of Network Management Error Codes.
// https://docs.microsoft.com/en-gb/windows/win32/netmgmt/network-management-error-codes?redirectedfrom=MSDN // https://docs.microsoft.com/en-gb/windows/win32/netmgmt/network-management-error-codes?redirectedfrom=MSDN
//
//nolint:gochecknoglobals
var NetApiStatus = map[uint32]string{ var NetApiStatus = map[uint32]string{
// Success // Success
0: "NERR_Success", 0: "NERR_Success",

View File

@@ -40,6 +40,7 @@ type PerformanceInformation struct {
ThreadCount uint32 ThreadCount uint32
} }
//nolint:gochecknoglobals
var ( var (
psapi = windows.NewLazySystemDLL("psapi.dll") psapi = windows.NewLazySystemDLL("psapi.dll")
procGetPerformanceInfo = psapi.NewProc("GetPerformanceInfo") procGetPerformanceInfo = psapi.NewProc("GetPerformanceInfo")

Some files were not shown because too many files have changed in this diff Show More