chore: Refactor Config Collector API (#1558)

This commit is contained in:
Jan-Otto Kröpke
2024-08-11 13:28:39 +02:00
committed by GitHub
parent 7bb16d2f5b
commit dd956c986b
62 changed files with 1186 additions and 791 deletions

View File

@@ -77,7 +77,7 @@ jobs:
run: | run: |
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$Version = git describe --tag $Version = git describe --tags --always
$Version = $Version -replace 'v', '' $Version = $Version -replace 'v', ''
# '+' symbols are invalid characters in image tags # '+' symbols are invalid characters in image tags
$Version = $Version -replace '\+', '_' $Version = $Version -replace '\+', '_'

View File

@@ -38,9 +38,6 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
// https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
const PROCESS_ALL_ACCESS = windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | windows.SPECIFIC_RIGHTS_ALL
// Same struct prometheus uses for their /version endpoint. // Same struct prometheus uses for their /version endpoint.
// Separate copy to avoid pulling all of prometheus as a dependency. // Separate copy to avoid pulling all of prometheus as a dependency.
type prometheusVersion struct { type prometheusVersion struct {
@@ -63,18 +60,23 @@ var priorityStringToInt = map[string]uint32{
} }
func setPriorityWindows(pid int, priority uint32) error { func setPriorityWindows(pid int, priority uint32) error {
handle, err := windows.OpenProcess(PROCESS_ALL_ACCESS, false, uint32(pid)) // https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
handle, err := windows.OpenProcess(
windows.STANDARD_RIGHTS_REQUIRED|windows.SYNCHRONIZE|windows.SPECIFIC_RIGHTS_ALL,
false, uint32(pid),
)
if err != nil { if err != nil {
return err return err
} }
//nolint:errcheck
defer windows.CloseHandle(handle) // Technically this can fail, but we ignore it
err = windows.SetPriorityClass(handle, priority) if err = windows.SetPriorityClass(handle, priority); err != nil {
if err != nil {
return err return err
} }
if err = windows.CloseHandle(handle); err != nil {
return fmt.Errorf("failed to close handle: %w", err)
}
return nil return nil
} }

View File

@@ -21,6 +21,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
addressBookClientSessions *prometheus.Desc addressBookClientSessions *prometheus.Desc
@@ -87,8 +88,15 @@ type Collector struct {
tombstonesObjectsVisitedTotal *prometheus.Desc tombstonesObjectsVisitedTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -22,6 +22,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
challengeResponseProcessingTime *prometheus.Desc challengeResponseProcessingTime *prometheus.Desc
@@ -39,8 +40,15 @@ type Collector struct {
signedCertificateTimestampListsPerSecond *prometheus.Desc signedCertificateTimestampListsPerSecond *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
adLoginConnectionFailures *prometheus.Desc adLoginConnectionFailures *prometheus.Desc
@@ -66,8 +67,15 @@ type Collector struct {
wstrustTokenRequests *prometheus.Desc wstrustTokenRequests *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -20,6 +20,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for Perflib Cache metrics. // A Collector is a Prometheus Collector for Perflib Cache metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
asyncCopyReadsTotal *prometheus.Desc asyncCopyReadsTotal *prometheus.Desc
@@ -53,8 +54,15 @@ type Collector struct {
syncPinReadsTotal *prometheus.Desc syncPinReadsTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -22,6 +22,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for containers metrics. // A Collector is a Prometheus Collector for containers metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
// Presence // Presence
@@ -56,8 +57,15 @@ type Collector struct {
} }
// New constructs a new Collector. // New constructs a new Collector.
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -20,6 +20,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
cStateSecondsTotal *prometheus.Desc cStateSecondsTotal *prometheus.Desc
@@ -37,8 +38,15 @@ type Collector struct {
processorPrivilegedUtility *prometheus.Desc processorPrivilegedUtility *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -27,13 +27,21 @@ 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.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
cpuInfo *prometheus.Desc cpuInfo *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
physicalMemoryBytes *prometheus.Desc physicalMemoryBytes *prometheus.Desc
@@ -26,8 +27,15 @@ type Collector struct {
hostname *prometheus.Desc hostname *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -3,31 +3,32 @@
package dfsr package dfsr
import ( import (
"slices"
"strings"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const Name = "dfsr" const Name = "dfsr"
type Config struct { type Config struct {
EnabledCollectors string `yaml:"enabled_collectors"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
EnabledCollectors: "connection,folder,volume", CollectorsEnabled: []string{"connection", "folder", "volume"},
} }
// Collector contains the metric and state data of the DFSR collectors. // Collector contains the metric and state data of the DFSR collectors.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
dfsrEnabledCollectors *string
// connection source // connection source
connectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc connectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc
connectionBytesReceivedTotal *prometheus.Desc connectionBytesReceivedTotal *prometheus.Desc
@@ -102,21 +103,29 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.CollectorsEnabled == nil {
dfsrEnabledCollectors: &config.EnabledCollectors, config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
} }
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{ c := &Collector{
dfsrEnabledCollectors: app. config: ConfigDefaults,
Flag("collectors.dfsr.sources-enabled", "Comma-separated list of DFSR Perflib sources to use.").
Default(ConfigDefaults.EnabledCollectors).
String(),
} }
c.config.CollectorsEnabled = make([]string, 0)
app.Flag("collectors.dfsr.sources-enabled", "Comma-separated list of DFSR Perflib sources to use.").
Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringsVar(&c.config.CollectorsEnabled)
return c
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -129,8 +138,9 @@ func (c *Collector) SetLogger(logger log.Logger) {
func (c *Collector) GetPerfCounter() ([]string, error) { func (c *Collector) GetPerfCounter() ([]string, error) {
// Perflib sources are dynamic, depending on the enabled child collectors // Perflib sources are dynamic, depending on the enabled child collectors
expandedChildCollectors := utils.ExpandEnabledChildCollectors(*c.dfsrEnabledCollectors) expandedChildCollectors := slices.Compact(c.config.CollectorsEnabled)
perflibDependencies := make([]string, 0, len(expandedChildCollectors)) perflibDependencies := make([]string, 0, len(expandedChildCollectors))
for _, source := range expandedChildCollectors { for _, source := range expandedChildCollectors {
perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source)) perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source))
} }
@@ -209,8 +219,8 @@ func (c *Collector) Build() error {
nil, nil,
) )
c. // folder // folder
folderBandwidthSavingsUsingDFSReplicationTotal = prometheus.NewDesc( c.folderBandwidthSavingsUsingDFSReplicationTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "folder_bandwidth_savings_using_dfs_replication_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "folder_bandwidth_savings_using_dfs_replication_bytes_total"),
"Total bytes of bandwidth saved using DFS Replication for this folder", "Total bytes of bandwidth saved using DFS Replication for this folder",
[]string{"name"}, []string{"name"},
@@ -435,7 +445,9 @@ func (c *Collector) Build() error {
nil, nil,
) )
c.dfsrChildCollectors = c.getDFSRChildCollectors(utils.ExpandEnabledChildCollectors(*c.dfsrEnabledCollectors)) // Perflib sources are dynamic, depending on the enabled child collectors
expandedChildCollectors := slices.Compact(c.config.CollectorsEnabled)
c.dfsrChildCollectors = c.getDFSRChildCollectors(expandedChildCollectors)
return nil return nil
} }

View File

@@ -18,6 +18,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector perflib DHCP metrics. // A Collector is a Prometheus Collector perflib DHCP metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
acksTotal *prometheus.Desc acksTotal *prometheus.Desc
@@ -47,8 +48,15 @@ type Collector struct {
requestsTotal *prometheus.Desc requestsTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -25,6 +25,7 @@ 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.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
availability *prometheus.Desc availability *prometheus.Desc
@@ -34,8 +35,15 @@ type Collector struct {
status *prometheus.Desc status *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -21,6 +21,7 @@ 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.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
dynamicUpdatesFailures *prometheus.Desc dynamicUpdatesFailures *prometheus.Desc
@@ -47,8 +48,15 @@ type Collector struct {
zoneTransferSuccessSent *prometheus.Desc zoneTransferSuccessSent *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -13,26 +13,23 @@ import (
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const Name = "exchange" const Name = "exchange"
type Config struct { type Config struct {
CollectorsEnabled string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: "", CollectorsEnabled: []string{},
} }
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
exchangeListAllCollectors *bool
exchangeCollectorsEnabled *string
activeMailboxDeliveryQueueLength *prometheus.Desc activeMailboxDeliveryQueueLength *prometheus.Desc
activeSyncRequestsPerSec *prometheus.Desc activeSyncRequestsPerSec *prometheus.Desc
activeTasks *prometheus.Desc activeTasks *prometheus.Desc
@@ -94,28 +91,68 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
exchangeListAllCollectors := false if config.CollectorsEnabled == nil {
c := &Collector{ config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
exchangeCollectorsEnabled: &config.CollectorsEnabled,
exchangeListAllCollectors: &exchangeListAllCollectors,
} }
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{ c := &Collector{
exchangeListAllCollectors: app.Flag( config: ConfigDefaults,
"collectors.exchange.list",
"List the collectors along with their perflib object name/ids",
).Bool(),
exchangeCollectorsEnabled: app.Flag(
"collectors.exchange.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default(ConfigDefaults.CollectorsEnabled).String(),
} }
c.config.CollectorsEnabled = make([]string, 0)
var listAllCollectors bool
app.Flag(
"collectors.exchange.list",
"List the collectors along with their perflib object name/ids",
).BoolVar(&listAllCollectors)
app.Flag(
"collectors.exchange.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringsVar(&c.config.CollectorsEnabled)
app.PreAction(func(*kingpin.ParseContext) error {
if listAllCollectors {
collectorDesc := map[string]string{
"ADAccessProcesses": "[19108] MSExchange ADAccess Processes",
"TransportQueues": "[20524] MSExchangeTransport Queues",
"HttpProxy": "[36934] MSExchange HttpProxy",
"ActiveSync": "[25138] MSExchange ActiveSync",
"AvailabilityService": "[24914] MSExchange Availability Service",
"OutlookWebAccess": "[24618] MSExchange OWA",
"Autodiscover": "[29240] MSExchange Autodiscover",
"WorkloadManagement": "[19430] MSExchange WorkloadManagement Workloads",
"RpcClientAccess": "[29336] MSExchange RpcClientAccess",
"MapiHttpEmsmdb": "[26463] MSExchange MapiHttp Emsmdb",
}
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object"))
for _, cname := range exchangeAllCollectorNames {
sb.WriteString(fmt.Sprintf("%-32s %-32s\n", cname, collectorDesc[cname]))
}
app.UsageTemplate(sb.String()).Usage(nil)
os.Exit(0)
}
return nil
})
return c
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -195,40 +232,20 @@ func (c *Collector) Build() error {
c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder") c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder")
c.activeUserCountMapiHttpEmsMDB = desc("mapihttp_emsmdb_active_user_count", "Number of unique outlook users that have shown some kind of activity in the last 2 minutes") c.activeUserCountMapiHttpEmsMDB = desc("mapihttp_emsmdb_active_user_count", "Number of unique outlook users that have shown some kind of activity in the last 2 minutes")
c.enabledCollectors = make([]string, 0, len(exchangeAllCollectorNames)) if len(c.config.CollectorsEnabled) == 0 {
c.enabledCollectors = exchangeAllCollectorNames
collectorDesc := map[string]string{
"ADAccessProcesses": "[19108] MSExchange ADAccess Processes",
"TransportQueues": "[20524] MSExchangeTransport Queues",
"HttpProxy": "[36934] MSExchange HttpProxy",
"ActiveSync": "[25138] MSExchange ActiveSync",
"AvailabilityService": "[24914] MSExchange Availability Service",
"OutlookWebAccess": "[24618] MSExchange OWA",
"Autodiscover": "[29240] MSExchange Autodiscover",
"WorkloadManagement": "[19430] MSExchange WorkloadManagement Workloads",
"RpcClientAccess": "[29336] MSExchange RpcClientAccess",
"MapiHttpEmsmdb": "[26463] MSExchange MapiHttp Emsmdb",
}
if *c.exchangeListAllCollectors {
fmt.Printf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object") //nolint:forbidigo
for _, cname := range exchangeAllCollectorNames {
fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) //nolint:forbidigo
}
os.Exit(0)
}
if utils.IsEmpty(c.exchangeCollectorsEnabled) {
c.enabledCollectors = append(c.enabledCollectors, exchangeAllCollectorNames...)
} else { } else {
for _, collectorName := range strings.Split(*c.exchangeCollectorsEnabled, ",") { c.enabledCollectors = make([]string, 0, len(exchangeAllCollectorNames))
if slices.Contains(exchangeAllCollectorNames, collectorName) {
c.enabledCollectors = append(c.enabledCollectors, collectorName) for _, collectorName := range c.config.CollectorsEnabled {
} else { if !slices.Contains(exchangeAllCollectorNames, collectorName) {
return fmt.Errorf("unknown exchange collector: %s", collectorName) return fmt.Errorf("unknown exchange collector: %s", collectorName)
} }
c.enabledCollectors = append(c.enabledCollectors, collectorName)
} }
c.enabledCollectors = slices.Clip(c.enabledCollectors)
} }
return nil return nil

View File

@@ -19,6 +19,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
quotasCount *prometheus.Desc quotasCount *prometheus.Desc
@@ -33,8 +34,15 @@ type Collector struct {
template *prometheus.Desc template *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -22,6 +22,7 @@ var ConfigDefaults = Config{}
// Collector is a Prometheus Collector for hyper-v. // Collector is a Prometheus Collector for hyper-v.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary // Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
@@ -139,8 +140,15 @@ type Collector struct {
vmMemoryRemovedMemory *prometheus.Desc vmMemoryRemovedMemory *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -20,64 +20,23 @@ import (
const Name = "iis" const Name = "iis"
type Config struct { type Config struct {
SiteInclude string `yaml:"site_include"` SiteInclude *regexp.Regexp `yaml:"site_include"`
SiteExclude string `yaml:"site_exclude"` SiteExclude *regexp.Regexp `yaml:"site_exclude"`
AppInclude string `yaml:"app_include"` AppInclude *regexp.Regexp `yaml:"app_include"`
AppExclude string `yaml:"app_exclude"` AppExclude *regexp.Regexp `yaml:"app_exclude"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
SiteInclude: ".+", SiteInclude: types.RegExpAny,
SiteExclude: "", SiteExclude: types.RegExpEmpty,
AppInclude: ".+", AppInclude: types.RegExpAny,
AppExclude: "", AppExclude: types.RegExpEmpty,
}
type simple_version struct {
major uint64
minor uint64
}
func getIISVersion(logger log.Logger) simple_version {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE)
if err != nil {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simple_version{}
}
defer func() {
err = k.Close()
if err != nil {
_ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err)
}
}()
major, _, err := k.GetIntegerValue("MajorVersion")
if err != nil {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simple_version{}
}
minor, _, err := k.GetIntegerValue("MinorVersion")
if err != nil {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simple_version{}
}
_ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected IIS %d.%d\n", major, minor))
return simple_version{
major: major,
minor: minor,
}
} }
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
siteInclude *string
siteExclude *string
appInclude *string
appExclude *string
info *prometheus.Desc info *prometheus.Desc
// Web Service // Web Service
@@ -104,9 +63,6 @@ type Collector struct {
totalNotFoundErrors *prometheus.Desc totalNotFoundErrors *prometheus.Desc
totalRejectedAsyncIORequests *prometheus.Desc totalRejectedAsyncIORequests *prometheus.Desc
siteIncludePattern *regexp.Regexp
siteExcludePattern *regexp.Regexp
// APP_POOL_WAS // APP_POOL_WAS
currentApplicationPoolState *prometheus.Desc currentApplicationPoolState *prometheus.Desc
currentApplicationPoolUptime *prometheus.Desc currentApplicationPoolUptime *prometheus.Desc
@@ -203,10 +159,7 @@ type Collector struct {
serviceCacheOutputCacheFlushedItemsTotal *prometheus.Desc serviceCacheOutputCacheFlushedItemsTotal *prometheus.Desc
serviceCacheOutputCacheFlushesTotal *prometheus.Desc serviceCacheOutputCacheFlushesTotal *prometheus.Desc
appIncludePattern *regexp.Regexp iisVersion simpleVersion
appExcludePattern *regexp.Regexp
iisVersion simple_version
} }
func New(logger log.Logger, config *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
@@ -214,11 +167,24 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
if config.AppExclude == nil {
config.AppExclude = ConfigDefaults.AppExclude
}
if config.AppInclude == nil {
config.AppInclude = ConfigDefaults.AppInclude
}
if config.SiteExclude == nil {
config.SiteExclude = ConfigDefaults.SiteExclude
}
if config.SiteInclude == nil {
config.SiteInclude = ConfigDefaults.SiteInclude
}
c := &Collector{ c := &Collector{
appInclude: &config.AppInclude, config: *config,
appExclude: &config.AppExclude,
siteInclude: &config.SiteInclude,
siteExclude: &config.SiteExclude,
} }
c.SetLogger(logger) c.SetLogger(logger)
@@ -228,27 +194,57 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
siteInclude: app.Flag( config: ConfigDefaults,
"collector.iis.site-include",
"Regexp of sites to include. Site name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.SiteInclude).String(),
siteExclude: app.Flag(
"collector.iis.site-exclude",
"Regexp of sites to exclude. Site name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.SiteExclude).String(),
appInclude: app.Flag(
"collector.iis.app-include",
"Regexp of apps to include. App name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.AppInclude).String(),
appExclude: app.Flag(
"collector.iis.app-exclude",
"Regexp of apps to exclude. App name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.AppExclude).String(),
} }
var appExclude, appInclude, siteExclude, siteInclude string
app.Flag(
"collector.iis.app-exclude",
"Regexp of apps to exclude. App name must both match include and not match exclude to be included.",
).Default(c.config.AppExclude.String()).StringVar(&appExclude)
app.Flag(
"collector.iis.app-include",
"Regexp of apps to include. App name must both match include and not match exclude to be included.",
).Default(c.config.AppInclude.String()).StringVar(&appInclude)
app.Flag(
"collector.iis.site-exclude",
"Regexp of sites to exclude. Site name must both match include and not match exclude to be included.",
).Default(c.config.SiteExclude.String()).StringVar(&siteExclude)
app.Flag(
"collector.iis.site-include",
"Regexp of sites to include. Site name must both match include and not match exclude to be included.",
).Default(c.config.SiteInclude.String()).StringVar(&siteInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.AppExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", appExclude))
if err != nil {
return fmt.Errorf("collector.iis.app-exclude: %w", err)
}
c.config.AppInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", appInclude))
if err != nil {
return fmt.Errorf("collector.iis.app-include: %w", err)
}
c.config.SiteExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", siteExclude))
if err != nil {
return fmt.Errorf("collector.iis.site-exclude: %w", err)
}
c.config.SiteInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", siteInclude))
if err != nil {
return fmt.Errorf("collector.iis.site-include: %w", err)
}
return nil
})
return c return c
} }
@@ -276,27 +272,6 @@ func (c *Collector) Close() error {
func (c *Collector) Build() error { func (c *Collector) Build() error {
c.iisVersion = getIISVersion(c.logger) c.iisVersion = getIISVersion(c.logger)
var err error
c.siteIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.siteInclude))
if err != nil {
return err
}
c.siteExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.siteExclude))
if err != nil {
return err
}
c.appIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.appInclude))
if err != nil {
return err
}
c.appExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.appExclude))
if err != nil {
return err
}
c.info = prometheus.NewDesc( c.info = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"), prometheus.BuildFQName(types.Namespace, Name, "info"),
"ISS information", "ISS information",
@@ -918,6 +893,43 @@ func (c *Collector) Build() error {
return nil return nil
} }
type simpleVersion struct {
major uint64
minor uint64
}
func getIISVersion(logger log.Logger) simpleVersion {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE)
if err != nil {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simpleVersion{}
}
defer func() {
err = k.Close()
if err != nil {
_ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err)
}
}()
major, _, err := k.GetIntegerValue("MajorVersion")
if err != nil {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simpleVersion{}
}
minor, _, err := k.GetIntegerValue("MinorVersion")
if err != nil {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simpleVersion{}
}
_ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected IIS %d.%d\n", major, minor))
return simpleVersion{
major: major,
minor: minor,
}
}
// 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(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
@@ -1049,7 +1061,7 @@ func (c *Collector) collectWebService(ctx *types.ScrapeContext, ch chan<- promet
webServiceDeDuplicated := dedupIISNames(webService) webServiceDeDuplicated := dedupIISNames(webService)
for name, app := range webServiceDeDuplicated { for name, app := range webServiceDeDuplicated {
if name == "_Total" || c.siteExcludePattern.MatchString(name) || !c.siteIncludePattern.MatchString(name) { if name == "_Total" || c.config.SiteExclude.MatchString(name) || !c.config.SiteInclude.MatchString(name) {
continue continue
} }
@@ -1336,8 +1348,8 @@ func (c *Collector) collectAPP_POOL_WAS(ctx *types.ScrapeContext, ch chan<- prom
for name, app := range appPoolDeDuplicated { for name, app := range appPoolDeDuplicated {
if name == "_Total" || if name == "_Total" ||
c.appExcludePattern.MatchString(name) || c.config.AppExclude.MatchString(name) ||
!c.appIncludePattern.MatchString(name) { !c.config.AppInclude.MatchString(name) {
continue continue
} }
@@ -1516,8 +1528,8 @@ func (c *Collector) collectW3SVC_W3WP(ctx *types.ScrapeContext, ch chan<- promet
pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1") pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2") name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2")
if name == "" || name == "_Total" || if name == "" || name == "_Total" ||
c.appExcludePattern.MatchString(name) || c.config.AppExclude.MatchString(name) ||
!c.appIncludePattern.MatchString(name) { !c.config.AppInclude.MatchString(name) {
continue continue
} }
@@ -1774,8 +1786,8 @@ func (c *Collector) collectW3SVC_W3WP(ctx *types.ScrapeContext, ch chan<- promet
pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1") pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2") name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2")
if name == "" || name == "_Total" || if name == "" || name == "_Total" ||
c.appExcludePattern.MatchString(name) || c.config.AppExclude.MatchString(name) ||
!c.appIncludePattern.MatchString(name) { !c.config.AppInclude.MatchString(name) {
continue continue
} }

View File

@@ -27,13 +27,21 @@ 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.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
licenseStatus *prometheus.Desc licenseStatus *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -22,24 +22,20 @@ import (
const Name = "logical_disk" const Name = "logical_disk"
type Config struct { type Config struct {
VolumeInclude string `yaml:"volume_include"` VolumeInclude *regexp.Regexp `yaml:"volume_include"`
VolumeExclude string `yaml:"volume_exclude"` VolumeExclude *regexp.Regexp `yaml:"volume_exclude"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
VolumeInclude: ".+", VolumeInclude: types.RegExpAny,
VolumeExclude: "", VolumeExclude: types.RegExpEmpty,
} }
// A Collector is a Prometheus Collector for perflib logicalDisk metrics. // A Collector is a Prometheus Collector for perflib logicalDisk metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
volumeInclude *string
volumeExclude *string
volumeIncludePattern *regexp.Regexp
volumeExcludePattern *regexp.Regexp
avgReadQueue *prometheus.Desc avgReadQueue *prometheus.Desc
avgWriteQueue *prometheus.Desc avgWriteQueue *prometheus.Desc
freeSpace *prometheus.Desc freeSpace *prometheus.Desc
@@ -73,10 +69,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.VolumeExclude == nil {
volumeExclude: &config.VolumeExclude, config.VolumeExclude = ConfigDefaults.VolumeExclude
volumeInclude: &config.VolumeInclude,
} }
if config.VolumeInclude == nil {
config.VolumeInclude = ConfigDefaults.VolumeInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
@@ -84,16 +88,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
volumeInclude: app.Flag( config: ConfigDefaults,
"collector.logical_disk.volume-include",
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.VolumeInclude).String(),
volumeExclude: app.Flag(
"collector.logical_disk.volume-exclude",
"Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.VolumeExclude).String(),
} }
var volumeExclude, volumeInclude string
app.Flag(
"collector.logical_disk.volume-exclude",
"Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.",
).Default(c.config.VolumeExclude.String()).StringVar(&volumeExclude)
app.Flag(
"collector.logical_disk.volume-include",
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.",
).Default(c.config.VolumeInclude.String()).StringVar(&volumeInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.VolumeExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeExclude))
if err != nil {
return fmt.Errorf("collector.logical_disk.volume-exclude: %w", err)
}
c.config.VolumeInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeInclude))
if err != nil {
return fmt.Errorf("collector.logical_disk.volume-include: %w", err)
}
return nil
})
return c return c
} }
@@ -238,17 +263,6 @@ func (c *Collector) Build() error {
nil, nil,
) )
var err error
c.volumeIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeInclude))
if err != nil {
return err
}
c.volumeExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeExclude))
if err != nil {
return err
}
return nil return nil
} }
@@ -299,8 +313,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
for _, volume := range dst { for _, volume := range dst {
if volume.Name == "_Total" || if volume.Name == "_Total" ||
c.volumeExcludePattern.MatchString(volume.Name) || c.config.VolumeExclude.MatchString(volume.Name) ||
!c.volumeIncludePattern.MatchString(volume.Name) { !c.config.VolumeInclude.MatchString(volume.Name) {
continue continue
} }

View File

@@ -21,13 +21,21 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
logonType *prometheus.Desc logonType *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -22,6 +22,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for perflib Memory metrics. // A Collector is a Prometheus Collector for perflib Memory metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
availableBytes *prometheus.Desc availableBytes *prometheus.Desc
@@ -58,8 +59,15 @@ type Collector struct {
writeCopiesTotal *prometheus.Desc writeCopiesTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -16,6 +16,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics. // A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
addEvictDelay *prometheus.Desc addEvictDelay *prometheus.Desc
@@ -97,8 +98,15 @@ type Collector struct {
witnessRestartInterval *prometheus.Desc witnessRestartInterval *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -16,6 +16,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_Network metrics. // A Collector is a Prometheus Collector for WMI MSCluster_Network metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
characteristics *prometheus.Desc characteristics *prometheus.Desc
@@ -25,8 +26,15 @@ type Collector struct {
state *prometheus.Desc state *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var NodeName []string
// A Collector is a Prometheus Collector for WMI MSCluster_Node metrics. // A Collector is a Prometheus Collector for WMI MSCluster_Node metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
buildNumber *prometheus.Desc buildNumber *prometheus.Desc
@@ -37,8 +38,15 @@ type Collector struct {
statusInformation *prometheus.Desc statusInformation *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -17,6 +17,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_Resource metrics. // A Collector is a Prometheus Collector for WMI MSCluster_Resource metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
characteristics *prometheus.Desc characteristics *prometheus.Desc
@@ -38,8 +39,15 @@ type Collector struct {
subclass *prometheus.Desc subclass *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -17,6 +17,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_ResourceGroup metrics. // A Collector is a Prometheus Collector for WMI MSCluster_ResourceGroup metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
autoFailbackType *prometheus.Desc autoFailbackType *prometheus.Desc
@@ -35,8 +36,15 @@ type Collector struct {
state *prometheus.Desc state *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -17,19 +17,18 @@ import (
const Name = "msmq" const Name = "msmq"
type Config struct { type Config struct {
QueryWhereClause string `yaml:"query_where_clause"` QueryWhereClause *string `yaml:"query_where_clause"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
QueryWhereClause: "", QueryWhereClause: utils.ToPTR(""),
} }
// 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.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
queryWhereClause *string
bytesInJournalQueue *prometheus.Desc bytesInJournalQueue *prometheus.Desc
bytesInQueue *prometheus.Desc bytesInQueue *prometheus.Desc
messagesInJournalQueue *prometheus.Desc messagesInJournalQueue *prometheus.Desc
@@ -41,20 +40,29 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.QueryWhereClause == nil {
queryWhereClause: &config.QueryWhereClause, config.QueryWhereClause = ConfigDefaults.QueryWhereClause
} }
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{ c := &Collector{
queryWhereClause: app. config: ConfigDefaults,
Flag("collector.msmq.msmq-where", "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").
Default(ConfigDefaults.QueryWhereClause).String(),
} }
app.Flag("collector.msmq.msmq-where", "WQL 'where' clause to use in WMI metrics query. "+
"Limits the response to the msmqs you specify and reduces the size of the response.").
Default(*c.config.QueryWhereClause).StringVar(c.config.QueryWhereClause)
return c
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -74,7 +82,7 @@ func (c *Collector) Close() error {
} }
func (c *Collector) Build() error { func (c *Collector) Build() error {
if utils.IsEmpty(c.queryWhereClause) { if *c.config.QueryWhereClause == "" {
_ = level.Warn(c.logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!") _ = level.Warn(c.logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!")
} }
@@ -115,18 +123,19 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
return nil return nil
} }
type Win32_PerfRawData_MSMQ_MSMQQueue struct { type msmqQueue struct {
Name string Name string
BytesinJournalQueue uint64 BytesInJournalQueue uint64
BytesinQueue uint64 BytesInQueue uint64
MessagesinJournalQueue uint64 MessagesInJournalQueue uint64
MessagesinQueue uint64 MessagesInQueue uint64
} }
func (c *Collector) collect(ch chan<- prometheus.Metric) error { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_MSMQ_MSMQQueue var dst []msmqQueue
q := wmi.QueryAllWhere(&dst, *c.queryWhereClause, c.logger)
q := wmi.QueryAllForClassWhere(&dst, "Win32_PerfRawData_MSMQ_MSMQQueue", *c.config.QueryWhereClause, c.logger)
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return err return err
} }
@@ -135,30 +144,31 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesInJournalQueue, c.bytesInJournalQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.BytesinJournalQueue), float64(msmq.BytesInJournalQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesInQueue, c.bytesInQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.BytesinQueue), float64(msmq.BytesInQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesInJournalQueue, c.messagesInJournalQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.MessagesinJournalQueue), float64(msmq.MessagesInJournalQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesInQueue, c.messagesInQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.MessagesinQueue), float64(msmq.MessagesInQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
} }
return nil return nil
} }

View File

@@ -6,6 +6,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"slices"
"sort"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -15,7 +17,6 @@ import (
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows/registry" "golang.org/x/sys/windows/registry"
) )
@@ -23,11 +24,24 @@ import (
const Name = "mssql" const Name = "mssql"
type Config struct { type Config struct {
EnabledCollectors string `yaml:"collectors_enabled"` //nolint:tagliatelle CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
EnabledCollectors: "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions,waitstats", CollectorsEnabled: []string{
"accessmethods",
"availreplica",
"bufman",
"databases",
"dbreplica",
"genstats",
"locks",
"memmgr",
"sqlstats",
"sqlerrors",
"transactions",
"waitstats",
},
} }
type mssqlInstancesType map[string]string type mssqlInstancesType map[string]string
@@ -39,8 +53,8 @@ func getMSSQLInstances(logger log.Logger) mssqlInstancesType {
sqlDefaultInstance := make(mssqlInstancesType) sqlDefaultInstance := make(mssqlInstancesType)
sqlDefaultInstance["MSSQLSERVER"] = "" sqlDefaultInstance["MSSQLSERVER"] = ""
regkey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL` regKey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL`
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 {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine SQL instances", "err", err) _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine SQL instances", "err", err)
return sqlDefaultInstance return sqlDefaultInstance
@@ -128,11 +142,9 @@ func mssqlGetPerfObjectName(sqlInstance string, collector string) string {
// A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics. // A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
mssqlEnabledCollectors *string
mssqlPrintCollectors *bool
// meta // meta
mssqlScrapeDurationDesc *prometheus.Desc mssqlScrapeDurationDesc *prometheus.Desc
mssqlScrapeSuccessDesc *prometheus.Desc mssqlScrapeSuccessDesc *prometheus.Desc
@@ -408,29 +420,55 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
printCollectors := false if config.CollectorsEnabled == nil {
config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
}
c := &Collector{ c := &Collector{
mssqlEnabledCollectors: &config.EnabledCollectors, config: *config,
mssqlPrintCollectors: &printCollectors,
} }
c.SetLogger(logger) c.SetLogger(logger)
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{ c := &Collector{
mssqlEnabledCollectors: app.Flag( config: ConfigDefaults,
"collectors.mssql.classes-enabled",
"Comma-separated list of mssql WMI classes to use.").
Default(ConfigDefaults.EnabledCollectors).String(),
mssqlPrintCollectors: app.Flag(
"collectors.mssql.class-print",
"If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.",
).Bool(),
} }
c.config.CollectorsEnabled = make([]string, 0)
var listAllCollectors bool
app.Flag(
"collectors.mssql.class-print",
"If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.",
).BoolVar(&listAllCollectors)
app.Flag(
"collectors.mssql.classes-enabled",
"Comma-separated list of mssql WMI classes to use.",
).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringsVar(&c.config.CollectorsEnabled)
app.PreAction(func(*kingpin.ParseContext) error {
if listAllCollectors {
sb := strings.Builder{}
sb.WriteString("Available SQLServer Classes:\n - ")
for name := range c.mssqlCollectors {
sb.WriteString(fmt.Sprintf(" - %s\n", name))
}
app.UsageTemplate(sb.String()).Usage(nil)
os.Exit(0)
}
return nil
})
return c
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -442,9 +480,14 @@ func (c *Collector) SetLogger(logger log.Logger) {
} }
func (c *Collector) GetPerfCounter() ([]string, error) { func (c *Collector) GetPerfCounter() ([]string, error) {
enabled := utils.ExpandEnabledChildCollectors(*c.mssqlEnabledCollectors) enabled := slices.Compact(c.config.CollectorsEnabled)
// Result must order, to prevent test failures.
sort.Strings(enabled)
c.mssqlInstances = getMSSQLInstances(c.logger) c.mssqlInstances = getMSSQLInstances(c.logger)
perfCounters := make([]string, 0, len(c.mssqlInstances)*len(enabled)) perfCounters := make([]string, 0, len(c.mssqlInstances)*len(enabled))
for instance := range c.mssqlInstances { for instance := range c.mssqlInstances {
for _, c := range enabled { for _, c := range enabled {
perfCounters = append(perfCounters, mssqlGetPerfObjectName(instance, c)) perfCounters = append(perfCounters, mssqlGetPerfObjectName(instance, c))
@@ -1922,15 +1965,6 @@ func (c *Collector) Build() error {
c.mssqlCollectors = c.getMSSQLCollectors() c.mssqlCollectors = c.getMSSQLCollectors()
if *c.mssqlPrintCollectors {
fmt.Printf("Available SQLServer Classes:\n") //nolint:forbidigo
for name := range c.mssqlCollectors {
fmt.Printf(" - %s\n", name) //nolint:forbidigo
}
os.Exit(0)
}
return nil return nil
} }
@@ -1973,7 +2007,11 @@ func (c *Collector) execute(ctx *types.ScrapeContext, name string, fn mssqlColle
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
enabled := utils.ExpandEnabledChildCollectors(*c.mssqlEnabledCollectors) enabled := slices.Compact(c.config.CollectorsEnabled)
// Result must order, to prevent test failures.
sort.Strings(enabled)
for sqlInstance := range c.mssqlInstances { for sqlInstance := range c.mssqlInstances {
for _, name := range enabled { for _, name := range enabled {
function := c.mssqlCollectors[name] function := c.mssqlCollectors[name]
@@ -1982,12 +2020,14 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
go c.execute(ctx, name, function, ch, sqlInstance, &wg) go c.execute(ctx, name, function, ch, sqlInstance, &wg)
} }
} }
wg.Wait() wg.Wait()
// this should return an error if any? some? children errord. // this should return an error if any? some? children errored.
if c.mssqlChildCollectorFailure > 0 { if c.mssqlChildCollectorFailure > 0 {
return errors.New("at least one child collector failed") return errors.New("at least one child collector failed")
} }
return nil return nil
} }

View File

@@ -17,24 +17,22 @@ import (
const Name = "net" const Name = "net"
type Config struct { type Config struct {
NicInclude string `yaml:"nic_include"` NicExclude *regexp.Regexp `yaml:"nic_exclude"`
NicExclude string `yaml:"nic_exclude"` NicInclude *regexp.Regexp `yaml:"nic_include"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
NicInclude: ".+", NicExclude: types.RegExpEmpty,
NicExclude: "", NicInclude: types.RegExpAny,
} }
var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
// A Collector is a Prometheus Collector for Perflib Network Interface metrics. // A Collector is a Prometheus Collector for Perflib Network Interface metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
nicInclude *string
nicExclude *string
bytesReceivedTotal *prometheus.Desc bytesReceivedTotal *prometheus.Desc
bytesSentTotal *prometheus.Desc bytesSentTotal *prometheus.Desc
bytesTotal *prometheus.Desc bytesTotal *prometheus.Desc
@@ -48,9 +46,6 @@ type Collector struct {
packetsReceivedUnknown *prometheus.Desc packetsReceivedUnknown *prometheus.Desc
packetsSentTotal *prometheus.Desc packetsSentTotal *prometheus.Desc
currentBandwidth *prometheus.Desc currentBandwidth *prometheus.Desc
nicIncludePattern *regexp.Regexp
nicExcludePattern *regexp.Regexp
} }
func New(logger log.Logger, config *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
@@ -58,10 +53,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.NicExclude == nil {
nicExclude: &config.NicExclude, config.NicExclude = ConfigDefaults.NicExclude
nicInclude: &config.NicInclude,
} }
if config.NicInclude == nil {
config.NicInclude = ConfigDefaults.NicInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
@@ -69,17 +72,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
nicInclude: app.Flag( config: ConfigDefaults,
"collector.net.nic-include",
"Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.NicInclude).String(),
nicExclude: app.Flag(
"collector.net.nic-exclude",
"Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.NicExclude).String(),
} }
var nicExclude, nicInclude string
app.Flag(
"collector.net.nic-exclude",
"Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.",
).Default(c.config.NicExclude.String()).StringVar(&nicExclude)
app.Flag(
"collector.net.nic-include",
"Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.",
).Default(c.config.NicInclude.String()).StringVar(&nicInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.NicExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", nicExclude))
if err != nil {
return fmt.Errorf("collector.net.nic-exclude: %w", err)
}
c.config.NicInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", nicInclude))
if err != nil {
return fmt.Errorf("collector.net.nic-include: %w", err)
}
return nil
})
return c return c
} }
@@ -179,17 +202,6 @@ func (c *Collector) Build() error {
nil, nil,
) )
var err error
c.nicIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicInclude))
if err != nil {
return err
}
c.nicExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicExclude))
if err != nil {
return err
}
return nil return nil
} }
@@ -236,8 +248,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
} }
for _, nic := range dst { for _, nic := range dst {
if c.nicExcludePattern.MatchString(nic.Name) || if c.config.NicExclude.MatchString(nic.Name) ||
!c.nicIncludePattern.MatchString(nic.Name) { !c.config.NicInclude.MatchString(nic.Name) {
continue continue
} }

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
numberOfExceptionsThrown *prometheus.Desc numberOfExceptionsThrown *prometheus.Desc
@@ -27,8 +28,15 @@ type Collector struct {
throwToCatchDepth *prometheus.Desc throwToCatchDepth *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
numberOfCCWs *prometheus.Desc numberOfCCWs *prometheus.Desc
@@ -26,8 +27,15 @@ type Collector struct {
numberOfStubs *prometheus.Desc numberOfStubs *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
numberOfMethodsJitted *prometheus.Desc numberOfMethodsJitted *prometheus.Desc
@@ -27,8 +28,15 @@ type Collector struct {
totalNumberOfILBytesJitted *prometheus.Desc totalNumberOfILBytesJitted *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
bytesInLoaderHeap *prometheus.Desc bytesInLoaderHeap *prometheus.Desc
@@ -32,8 +33,15 @@ type Collector struct {
totalNumberOfLoadFailures *prometheus.Desc totalNumberOfLoadFailures *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
currentQueueLength *prometheus.Desc currentQueueLength *prometheus.Desc
@@ -30,8 +31,15 @@ type Collector struct {
totalNumberOfContentions *prometheus.Desc totalNumberOfContentions *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
allocatedBytes *prometheus.Desc allocatedBytes *prometheus.Desc
@@ -35,8 +36,15 @@ type Collector struct {
timeInGC *prometheus.Desc timeInGC *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
channels *prometheus.Desc channels *prometheus.Desc
@@ -29,8 +30,15 @@ type Collector struct {
totalRemoteCalls *prometheus.Desc totalRemoteCalls *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics. // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
numberLinkTimeChecks *prometheus.Desc numberLinkTimeChecks *prometheus.Desc
@@ -27,8 +28,15 @@ type Collector struct {
totalRuntimeChecks *prometheus.Desc totalRuntimeChecks *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics. // Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
accessAccepts *prometheus.Desc accessAccepts *prometheus.Desc
@@ -49,8 +50,15 @@ type Collector struct {
accountingUnknownType *prometheus.Desc accountingUnknownType *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -32,6 +32,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
osInformation *prometheus.Desc osInformation *prometheus.Desc
@@ -55,8 +56,15 @@ type pagingFileCounter struct {
UsagePeak float64 `perflib:"% Usage Peak"` UsagePeak float64 `perflib:"% Usage Peak"`
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -18,28 +18,20 @@ import (
const Name = "physical_disk" const Name = "physical_disk"
type Config struct { type Config struct {
DiskInclude string `yaml:"disk_include"` DiskInclude *regexp.Regexp `yaml:"disk_include"`
DiskExclude string `yaml:"disk_exclude"` DiskExclude *regexp.Regexp `yaml:"disk_exclude"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
DiskInclude: ".+", DiskInclude: types.RegExpAny,
DiskExclude: "", DiskExclude: types.RegExpEmpty,
} }
// A Collector is a Prometheus Collector for perflib PhysicalDisk metrics. // A Collector is a Prometheus Collector for perflib PhysicalDisk metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
diskInclude *string
diskExclude *string
diskIncludeSet bool
diskExcludeSet bool
diskIncludePattern *regexp.Regexp
diskExcludePattern *regexp.Regexp
idleTime *prometheus.Desc idleTime *prometheus.Desc
readBytesTotal *prometheus.Desc readBytesTotal *prometheus.Desc
readLatency *prometheus.Desc readLatency *prometheus.Desc
@@ -59,33 +51,55 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.DiskExclude == nil {
diskExclude: &config.DiskExclude, config.DiskExclude = ConfigDefaults.DiskExclude
diskInclude: &config.DiskInclude,
} }
if config.DiskInclude == nil {
config.DiskInclude = ConfigDefaults.DiskInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{} c := &Collector{
config: ConfigDefaults,
}
c.diskInclude = app.Flag( var diskExclude, diskInclude string
"collector.physical_disk.disk-include",
"Regexp of disks to include. Disk number must both match include and not match exclude to be included.",
).Default(ConfigDefaults.DiskInclude).PreAction(func(_ *kingpin.ParseContext) error {
c.diskIncludeSet = true
return nil
}).String()
c.diskExclude = app.Flag( app.Flag(
"collector.physical_disk.disk-exclude", "collector.physical_disk.disk-exclude",
"Regexp of disks to exclude. Disk number must both match include and not match exclude to be included.", "Regexp of disks to exclude. Disk number must both match include and not match exclude to be included.",
).Default(ConfigDefaults.DiskExclude).PreAction(func(_ *kingpin.ParseContext) error { ).Default(c.config.DiskExclude.String()).StringVar(&diskExclude)
c.diskExcludeSet = true
app.Flag(
"collector.physical_disk.disk-include",
"Regexp of disks to include. Disk number must both match include and not match exclude to be included.",
).Default(c.config.DiskInclude.String()).StringVar(&diskInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.DiskExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", diskExclude))
if err != nil {
return fmt.Errorf("collector.physical_disk.disk-exclude: %w", err)
}
c.config.DiskInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", diskInclude))
if err != nil {
return fmt.Errorf("collector.physical_disk.disk-include: %w", err)
}
return nil return nil
}).String() })
return c return c
} }
@@ -191,17 +205,6 @@ func (c *Collector) Build() error {
nil, nil,
) )
var err error
c.diskIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.diskInclude))
if err != nil {
return err
}
c.diskExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.diskExclude))
if err != nil {
return err
}
return nil return nil
} }
@@ -242,8 +245,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
for _, disk := range dst { for _, disk := range dst {
if disk.Name == "_Total" || if disk.Name == "_Total" ||
c.diskExcludePattern.MatchString(disk.Name) || c.config.DiskExclude.MatchString(disk.Name) ||
!c.diskIncludePattern.MatchString(disk.Name) { !c.config.DiskInclude.MatchString(disk.Name) {
continue continue
} }

View File

@@ -29,37 +29,41 @@ var printerStatusMap = map[uint16]string{
} }
type Config struct { type Config struct {
PrinterInclude string `yaml:"printer_include"` PrinterInclude *regexp.Regexp `yaml:"printer_include"`
PrinterExclude string `yaml:"printer_exclude"` PrinterExclude *regexp.Regexp `yaml:"printer_exclude"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
PrinterInclude: ".+", PrinterInclude: types.RegExpAny,
PrinterExclude: "", PrinterExclude: types.RegExpEmpty,
} }
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
printerInclude *string
printerExclude *string
printerStatus *prometheus.Desc printerStatus *prometheus.Desc
printerJobStatus *prometheus.Desc printerJobStatus *prometheus.Desc
printerJobCount *prometheus.Desc printerJobCount *prometheus.Desc
printerIncludePattern *regexp.Regexp
printerExcludePattern *regexp.Regexp
} }
func New(logger log.Logger, config *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{
printerInclude: &config.PrinterInclude, if config.PrinterExclude == nil {
printerExclude: &config.PrinterExclude, config.PrinterExclude = ConfigDefaults.PrinterExclude
} }
if config.PrinterInclude == nil {
config.PrinterInclude = ConfigDefaults.PrinterInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
@@ -67,17 +71,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
printerInclude: app.Flag( config: ConfigDefaults,
"collector.printer.include",
"Regular expression to match printers to collect metrics for",
).Default(ConfigDefaults.PrinterInclude).String(),
printerExclude: app.Flag(
"collector.printer.exclude",
"Regular expression to match printers to exclude",
).Default(ConfigDefaults.PrinterExclude).String(),
} }
var printerInclude, printerExclude string
app.Flag(
"collector.printer.include",
"Regular expression to match printers to collect metrics for",
).Default(c.config.PrinterInclude.String()).StringVar(&printerInclude)
app.Flag(
"collector.printer.exclude",
"Regular expression to match printers to exclude",
).Default(c.config.PrinterExclude.String()).StringVar(&printerExclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.PrinterInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", printerInclude))
if err != nil {
return fmt.Errorf("collector.printer.include: %w", err)
}
c.config.PrinterExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", printerExclude))
if err != nil {
return fmt.Errorf("collector.printer.exclude: %w", err)
}
return nil
})
return c return c
} }
@@ -109,27 +133,21 @@ func (c *Collector) Build() error {
nil, nil,
) )
var err error return nil
c.printerIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.printerInclude))
if err != nil {
return err
}
c.printerExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.printerExclude))
return err
} }
func (c *Collector) GetName() string { return Name } func (c *Collector) GetName() string { return Name }
func (c *Collector) GetPerfCounter() ([]string, error) { return []string{"Printer"}, nil } func (c *Collector) GetPerfCounter() ([]string, error) { return []string{"Printer"}, nil }
type win32_Printer struct { type wmiPrinter struct {
Name string Name string
Default bool Default bool
PrinterStatus uint16 PrinterStatus uint16
JobCountSinceLastReset uint32 JobCountSinceLastReset uint32
} }
type win32_PrintJob struct { type wmiPrintJob struct {
Name string Name string
Status string Status string
} }
@@ -139,23 +157,26 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
_ = level.Error(c.logger).Log("msg", "failed to collect printer status metrics", "err", err) _ = level.Error(c.logger).Log("msg", "failed to collect printer status metrics", "err", err)
return err return err
} }
if err := c.collectPrinterJobStatus(ch); err != nil { if err := c.collectPrinterJobStatus(ch); err != nil {
_ = level.Error(c.logger).Log("msg", "failed to collect printer job status metrics", "err", err) _ = level.Error(c.logger).Log("msg", "failed to collect printer job status metrics", "err", err)
return err return err
} }
return nil return nil
} }
func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error { func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
var printers []win32_Printer var printers []wmiPrinter
q := wmi.QueryAll(&printers, c.logger)
q := wmi.QueryAllForClass(&printers, "win32_Printer", c.logger)
if err := wmi.Query(q, &printers); err != nil { if err := wmi.Query(q, &printers); err != nil {
return err return err
} }
for _, printer := range printers { for _, printer := range printers {
if c.printerExcludePattern.MatchString(printer.Name) || if c.config.PrinterExclude.MatchString(printer.Name) ||
!c.printerIncludePattern.MatchString(printer.Name) { !c.config.PrinterInclude.MatchString(printer.Name) {
continue continue
} }
@@ -186,8 +207,9 @@ func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error { func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error {
var printJobs []win32_PrintJob var printJobs []wmiPrintJob
q := wmi.QueryAll(&printJobs, c.logger)
q := wmi.QueryAllForClass(&printJobs, "win32_PrintJob", c.logger)
if err := wmi.Query(q, &printJobs); err != nil { if err := wmi.Query(q, &printJobs); err != nil {
return err return err
} }
@@ -202,6 +224,7 @@ func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error {
group.status, group.status,
) )
} }
return nil return nil
} }
@@ -210,19 +233,22 @@ type PrintJobStatusGroup struct {
status string status string
} }
func (c *Collector) groupPrintJobs(printJobs []win32_PrintJob) map[PrintJobStatusGroup]int { func (c *Collector) groupPrintJobs(printJobs []wmiPrintJob) map[PrintJobStatusGroup]int {
groupedPrintJobs := make(map[PrintJobStatusGroup]int) groupedPrintJobs := make(map[PrintJobStatusGroup]int)
for _, printJob := range printJobs { for _, printJob := range printJobs {
printerName := strings.Split(printJob.Name, ",")[0] printerName := strings.Split(printJob.Name, ",")[0]
if c.printerExcludePattern.MatchString(printerName) || if c.config.PrinterExclude.MatchString(printerName) ||
!c.printerIncludePattern.MatchString(printerName) { !c.config.PrinterInclude.MatchString(printerName) {
continue continue
} }
groupedPrintJobs[PrintJobStatusGroup{ groupedPrintJobs[PrintJobStatusGroup{
printerName: printerName, printerName: printerName,
status: printJob.Status, status: printJob.Status,
}]++ }]++
} }
return groupedPrintJobs return groupedPrintJobs
} }

View File

@@ -15,7 +15,6 @@ import (
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@@ -24,31 +23,23 @@ import (
const Name = "process" const Name = "process"
type Config struct { type Config struct {
ProcessInclude string `yaml:"process_include"` ProcessInclude *regexp.Regexp `yaml:"process_include"`
ProcessExclude string `yaml:"process_exclude"` ProcessExclude *regexp.Regexp `yaml:"process_exclude"`
EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle
EnableReportOwner bool `yaml:"enable_report_owner"` EnableReportOwner bool `yaml:"enable_report_owner"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
ProcessInclude: ".+", ProcessInclude: types.RegExpAny,
ProcessExclude: "", ProcessExclude: types.RegExpEmpty,
EnableWorkerProcess: false, EnableWorkerProcess: false,
EnableReportOwner: false, EnableReportOwner: false,
} }
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
enableWorkerProcess *bool
enableReportOwner *bool
processInclude *string
processExclude *string
processIncludePattern *regexp.Regexp
processExcludePattern *regexp.Regexp
lookupCache map[string]string lookupCache map[string]string
cpuTimeTotal *prometheus.Desc cpuTimeTotal *prometheus.Desc
@@ -73,11 +64,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.ProcessExclude == nil {
processExclude: &config.ProcessExclude, config.ProcessExclude = ConfigDefaults.ProcessExclude
processInclude: &config.ProcessInclude,
enableWorkerProcess: &config.EnableWorkerProcess,
} }
if config.ProcessInclude == nil {
config.ProcessInclude = ConfigDefaults.ProcessInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
@@ -85,26 +83,47 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
processInclude: app.Flag( config: ConfigDefaults,
"collector.process.include",
"Regexp of processes to include. Process name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.ProcessInclude).String(),
processExclude: app.Flag(
"collector.process.exclude",
"Regexp of processes to exclude. Process name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.ProcessExclude).String(),
enableWorkerProcess: app.Flag(
"collector.process.iis",
"Enable IIS worker process name queries. May cause the collector to leak memory.",
).Default("false").Bool(),
enableReportOwner: app.Flag(
"collector.process.report-owner",
"Enable reporting of process owner.",
).Default("false").Bool(),
} }
var processExclude, processInclude string
app.Flag(
"collector.process.exclude",
"Regexp of processes to exclude. Process name must both match include and not match exclude to be included.",
).Default(c.config.ProcessExclude.String()).StringVar(&processExclude)
app.Flag(
"collector.process.include",
"Regexp of processes to include. Process name must both match include and not match exclude to be included.",
).Default(c.config.ProcessInclude.String()).StringVar(&processInclude)
app.Flag(
"collector.process.iis",
"Enable IIS worker process name queries. May cause the collector to leak memory.",
).Default(strconv.FormatBool(c.config.EnableWorkerProcess)).BoolVar(&c.config.EnableWorkerProcess)
app.Flag(
"collector.process.report-owner",
"Enable reporting of process owner.",
).Default(strconv.FormatBool(c.config.EnableReportOwner)).BoolVar(&c.config.EnableReportOwner)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.ProcessExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", processExclude))
if err != nil {
return fmt.Errorf("collector.process.exclude: %w", err)
}
c.config.ProcessInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", processInclude))
if err != nil {
return fmt.Errorf("collector.process.include: %w", err)
}
return nil
})
return c return c
} }
@@ -125,12 +144,12 @@ func (c *Collector) Close() error {
} }
func (c *Collector) Build() error { func (c *Collector) Build() error {
if c.processInclude != nil && *c.processInclude == ".*" && utils.IsEmpty(c.processExclude) { if c.config.ProcessInclude.String() == "^(?:.*)$" && c.config.ProcessExclude.String() == "^(?:)$" {
_ = level.Warn(c.logger).Log("msg", "No filters specified for process collector. This will generate a very large number of metrics!") _ = level.Warn(c.logger).Log("msg", "No filters specified for process collector. This will generate a very large number of metrics!")
} }
commonLabels := make([]string, 0) commonLabels := make([]string, 0)
if *c.enableReportOwner { if c.config.EnableReportOwner {
commonLabels = []string{"owner"} commonLabels = []string{"owner"}
} }
@@ -227,18 +246,6 @@ func (c *Collector) Build() error {
c.lookupCache = make(map[string]string) c.lookupCache = make(map[string]string)
var err error
c.processIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.processInclude))
if err != nil {
return err
}
c.processExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.processExclude))
if err != nil {
return err
}
return nil return nil
} }
@@ -262,7 +269,7 @@ type perflibProcess struct {
PageFaultsPerSec float64 `perflib:"Page Faults/sec"` PageFaultsPerSec float64 `perflib:"Page Faults/sec"`
PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"` PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"`
PageFileBytes float64 `perflib:"Page File Bytes"` PageFileBytes float64 `perflib:"Page File Bytes"`
PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` PoolNonPagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` PoolPagedBytes float64 `perflib:"Pool Paged Bytes"`
PriorityBase float64 `perflib:"Priority Base"` PriorityBase float64 `perflib:"Priority Base"`
PrivateBytes float64 `perflib:"Private Bytes"` PrivateBytes float64 `perflib:"Private Bytes"`
@@ -286,10 +293,10 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return err return err
} }
var dst_wp []WorkerProcess var workerProcesses []WorkerProcess
if *c.enableWorkerProcess { if c.config.EnableWorkerProcess {
q_wp := wmi.QueryAll(&dst_wp, c.logger) queryWorkerProcess := wmi.QueryAllForClass(&workerProcesses, "WorkerProcess", c.logger)
if err := wmi.QueryNamespace(q_wp, &dst_wp, "root\\WebAdministration"); err != nil { if err := wmi.QueryNamespace(queryWorkerProcess, &workerProcesses, "root\\WebAdministration"); err != nil {
_ = level.Debug(c.logger).Log("msg", "Could not query WebAdministration namespace for IIS worker processes", "err", err) _ = level.Debug(c.logger).Log("msg", "Could not query WebAdministration namespace for IIS worker processes", "err", err)
} }
} }
@@ -298,17 +305,18 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
for _, process := range data { for _, process := range data {
if process.Name == "_Total" || if process.Name == "_Total" ||
c.processExcludePattern.MatchString(process.Name) || c.config.ProcessExclude.MatchString(process.Name) ||
!c.processIncludePattern.MatchString(process.Name) { !c.config.ProcessInclude.MatchString(process.Name) {
continue continue
} }
// Duplicate processes are suffixed # and an index number. Remove those.
processName := strings.Split(process.Name, "#")[0]
pid := strconv.FormatUint(uint64(process.IDProcess), 10)
cpid := strconv.FormatUint(uint64(process.CreatingProcessID), 10)
if *c.enableWorkerProcess { // Duplicate processes are suffixed #, and an index number. Remove those.
for _, wp := range dst_wp { processName, _, _ := strings.Cut(process.Name, "#")
pid := strconv.FormatUint(uint64(process.IDProcess), 10)
parentPID := strconv.FormatUint(uint64(process.CreatingProcessID), 10)
if c.config.EnableWorkerProcess {
for _, wp := range workerProcesses {
if wp.ProcessId == uint64(process.IDProcess) { if wp.ProcessId == uint64(process.IDProcess) {
processName = strings.Join([]string{processName, wp.AppPoolName}, "_") processName = strings.Join([]string{processName, wp.AppPoolName}, "_")
break break
@@ -318,7 +326,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
labels := make([]string, 0, 4) labels := make([]string, 0, 4)
if *c.enableReportOwner { if c.config.EnableReportOwner {
owner, err = c.getProcessOwner(int(process.IDProcess)) owner, err = c.getProcessOwner(int(process.IDProcess))
if err != nil { if err != nil {
owner = "unknown" owner = "unknown"
@@ -327,7 +335,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
labels = []string{owner} labels = []string{owner}
} }
labels = append(labels, processName, pid, cpid) labels = append(labels, processName, pid, parentPID)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.startTime, c.startTime,
@@ -416,7 +424,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.poolBytes, c.poolBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
process.PoolNonpagedBytes, process.PoolNonPagedBytes,
append(labels, "nonpaged")..., append(labels, "nonpaged")...,
) )

View File

@@ -26,6 +26,7 @@ var ConfigDefaults = Config{}
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxnetwork/ // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxnetwork/
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxgraphics/ // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxgraphics/
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
// net // net
@@ -53,8 +54,15 @@ type Collector struct {
sourceFramesPerSecond *prometheus.Desc sourceFramesPerSecond *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -18,35 +18,25 @@ import (
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const ( const Name = "scheduled_task"
Name = "scheduled_task"
FlagScheduledTaskExclude = "collector.scheduled_task.exclude"
FlagScheduledTaskInclude = "collector.scheduled_task.include"
)
type Config struct { type Config struct {
TaskExclude string `yaml:"task_exclude"` TaskExclude *regexp.Regexp `yaml:"task_exclude"`
TaskInclude string `yaml:"task_include"` TaskInclude *regexp.Regexp `yaml:"task_include"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
TaskExclude: "", TaskExclude: types.RegExpEmpty,
TaskInclude: ".+", TaskInclude: types.RegExpAny,
} }
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
taskExclude *string
taskInclude *string
lastResult *prometheus.Desc lastResult *prometheus.Desc
missedRuns *prometheus.Desc missedRuns *prometheus.Desc
state *prometheus.Desc state *prometheus.Desc
taskIncludePattern *regexp.Regexp
taskExcludePattern *regexp.Regexp
} }
// TaskState ... // TaskState ...
@@ -80,10 +70,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.TaskExclude == nil {
taskExclude: &config.TaskExclude, config.TaskExclude = ConfigDefaults.TaskExclude
taskInclude: &config.TaskInclude,
} }
if config.TaskInclude == nil {
config.TaskInclude = ConfigDefaults.TaskInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
@@ -91,17 +89,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
taskInclude: app.Flag( config: ConfigDefaults,
FlagScheduledTaskInclude,
"Regexp of tasks to include. Task path must both match include and not match exclude to be included.",
).Default(ConfigDefaults.TaskInclude).String(),
taskExclude: app.Flag(
FlagScheduledTaskExclude,
"Regexp of tasks to exclude. Task path must both match include and not match exclude to be included.",
).Default(ConfigDefaults.TaskExclude).String(),
} }
var taskExclude, taskInclude string
app.Flag(
"collector.scheduled_task.exclude",
"Regexp of tasks to exclude. Task path must both match include and not match exclude to be included.",
).Default(c.config.TaskExclude.String()).StringVar(&taskExclude)
app.Flag(
"collector.scheduled_task.include",
"Regexp of tasks to include. Task path must both match include and not match exclude to be included.",
).Default(c.config.TaskExclude.String()).StringVar(&taskInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.TaskExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", taskExclude))
if err != nil {
return fmt.Errorf("collector.physical_disk.disk-exclude: %w", err)
}
c.config.TaskInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", taskInclude))
if err != nil {
return fmt.Errorf("collector.physical_disk.disk-include: %w", err)
}
return nil
})
return c return c
} }
@@ -143,18 +161,6 @@ func (c *Collector) Build() error {
nil, nil,
) )
var err error
c.taskIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.taskInclude))
if err != nil {
return err
}
c.taskExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.taskExclude))
if err != nil {
return err
}
return nil return nil
} }
@@ -176,8 +182,8 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
} }
for _, task := range scheduledTasks { for _, task := range scheduledTasks {
if c.taskExcludePattern.MatchString(task.Path) || if c.config.TaskExclude.MatchString(task.Path) ||
!c.taskIncludePattern.MatchString(task.Path) { !c.config.TaskInclude.MatchString(task.Path) {
continue continue
} }

View File

@@ -226,7 +226,7 @@ var (
func (c *Collector) collectWMI(ch chan<- prometheus.Metric) error { func (c *Collector) collectWMI(ch chan<- prometheus.Metric) error {
var dst []Win32_Service var dst []Win32_Service
q := wmi.QueryAllWhere(&dst, *c.serviceWhereClause, c.logger) q := wmi.QueryAllWhere(&dst, *c.serviceWhereClause, c.logger) //nolint:staticcheck
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return err return err
} }

View File

@@ -3,9 +3,6 @@
package smb package smb
import ( import (
"fmt"
"os"
"slices"
"strings" "strings"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
@@ -18,29 +15,16 @@ import (
const Name = "smb" const Name = "smb"
type Config struct { type Config struct{}
CollectorsEnabled string `yaml:"collectors_enabled"`
}
var ConfigDefaults = Config{ var ConfigDefaults = Config{}
CollectorsEnabled: "",
}
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
smbListAllCollectors *bool
smbCollectorsEnabled *string
treeConnectCount *prometheus.Desc treeConnectCount *prometheus.Desc
currentOpenFileCount *prometheus.Desc currentOpenFileCount *prometheus.Desc
enabledCollectors []string
}
// All available Collector functions.
var smbAllCollectorNames = []string{
"ServerShares",
} }
func New(logger log.Logger, config *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
@@ -48,10 +32,8 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
smbListAllCollectors := false
c := &Collector{ c := &Collector{
smbCollectorsEnabled: &config.CollectorsEnabled, config: *config,
smbListAllCollectors: &smbListAllCollectors,
} }
c.SetLogger(logger) c.SetLogger(logger)
@@ -59,18 +41,8 @@ func New(logger log.Logger, config *Config) *Collector {
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{ return &Collector{}
smbListAllCollectors: app.Flag(
"collectors.smb.list",
"List the collectors along with their perflib object name/ids",
).Bool(),
smbCollectorsEnabled: app.Flag(
"collectors.smb.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default(ConfigDefaults.CollectorsEnabled).String(),
}
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -105,48 +77,17 @@ func (c *Collector) Build() error {
c.currentOpenFileCount = desc("server_shares_current_open_file_count", "Current total count open files on the SMB Server") c.currentOpenFileCount = desc("server_shares_current_open_file_count", "Current total count open files on the SMB Server")
c.treeConnectCount = desc("server_shares_tree_connect_count", "Count of user connections to the SMB Server") c.treeConnectCount = desc("server_shares_tree_connect_count", "Count of user connections to the SMB Server")
c.enabledCollectors = make([]string, 0, len(smbAllCollectorNames))
collectorDesc := map[string]string{
"ServerShares": "SMB Server Shares",
}
if *c.smbListAllCollectors {
fmt.Printf("%-32s %-32s\n", "Collector Name", "Perflib Object") //nolint:forbidigo
for _, cname := range smbAllCollectorNames {
fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) //nolint:forbidigo
}
os.Exit(0)
}
if *c.smbCollectorsEnabled == "" {
c.enabledCollectors = append(c.enabledCollectors, smbAllCollectorNames...)
} else {
for _, collectorName := range strings.Split(*c.smbCollectorsEnabled, ",") {
if slices.Contains(smbAllCollectorNames, collectorName) {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
} else {
return fmt.Errorf("unknown smb collector: %s", collectorName)
}
}
}
return nil return nil
} }
// Collect collects smb metrics and sends them to prometheus. // Collect collects smb metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ if err := c.collectServerShares(ctx, ch); err != nil {
"ServerShares": c.collectServerShares, _ = level.Error(c.logger).Log("msg", "failed to collect server share metrics", "err", err)
return err
} }
for _, collectorName := range c.enabledCollectors {
if err := collectorFuncs[collectorName](ctx, ch); err != nil {
_ = level.Error(c.logger).Log("msg", "Error in "+collectorName, "err", err)
return err
}
}
return nil return nil
} }

View File

@@ -3,9 +3,6 @@
package smbclient package smbclient
import ( import (
"fmt"
"os"
"slices"
"strings" "strings"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
@@ -20,22 +17,14 @@ const (
Name = "smbclient" Name = "smbclient"
) )
type Config struct { type Config struct{}
CollectorsEnabled string `yaml:"collectors_enabled"`
}
var ConfigDefaults = Config{ var ConfigDefaults = Config{}
CollectorsEnabled: "",
}
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
enabledCollectors []string
smbClientListAllCollectors *bool
smbClientCollectorsEnabled *string
readBytesTotal *prometheus.Desc readBytesTotal *prometheus.Desc
readBytesTransmittedViaSMBDirectTotal *prometheus.Desc readBytesTransmittedViaSMBDirectTotal *prometheus.Desc
readRequestQueueSecsTotal *prometheus.Desc readRequestQueueSecsTotal *prometheus.Desc
@@ -60,38 +49,22 @@ type Collector struct {
requestSecs *prometheus.Desc requestSecs *prometheus.Desc
} }
// All available collector functions.
var smbclientAllCollectorNames = []string{
"ClientShares",
}
func New(logger log.Logger, config *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
} }
smbclientListAllCollectors := false
c := &Collector{ c := &Collector{
smbClientCollectorsEnabled: &config.CollectorsEnabled, config: *config,
smbClientListAllCollectors: &smbclientListAllCollectors,
} }
c.SetLogger(logger) c.SetLogger(logger)
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{ return &Collector{}
smbClientListAllCollectors: app.Flag(
"collectors.smbclient.list",
"List the collectors along with their perflib object name/ids",
).Bool(),
smbClientCollectorsEnabled: app.Flag(
"collectors.smbclient.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default(ConfigDefaults.CollectorsEnabled).String(),
}
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -208,48 +181,16 @@ func (c *Collector) Build() error {
[]string{"server", "share"}, []string{"server", "share"},
) )
c.enabledCollectors = make([]string, 0, len(smbclientAllCollectorNames))
collectorDesc := map[string]string{
"ClientShares": "SMB Client Shares",
}
if *c.smbClientListAllCollectors {
fmt.Printf("%-32s %-32s\n", "Collector Name", "Perflib Object") //nolint:forbidigo
for _, cname := range smbclientAllCollectorNames {
fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) //nolint:forbidigo
}
os.Exit(0)
}
if *c.smbClientCollectorsEnabled == "" {
c.enabledCollectors = append(c.enabledCollectors, smbclientAllCollectorNames...)
} else {
for _, collectorName := range strings.Split(*c.smbClientCollectorsEnabled, ",") {
if slices.Contains(smbclientAllCollectorNames, collectorName) {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
} else {
return fmt.Errorf("unknown smbclient Collector: %s", collectorName)
}
}
}
return nil return nil
} }
// Collect collects smb client metrics and sends them to prometheus. // Collect collects smb client metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ if err := c.collectClientShares(ctx, ch); err != nil {
"ClientShares": c.collectClientShares, _ = level.Error(c.logger).Log("msg", "Error in ClientShares", "err", err)
return err
} }
for _, collectorName := range c.enabledCollectors {
if err := collectorFuncs[collectorName](ctx, ch); err != nil {
_ = level.Error(c.logger).Log("msg", "Error in "+collectorName, "err", err)
return err
}
}
return nil return nil
} }

View File

@@ -17,23 +17,19 @@ import (
const Name = "smtp" const Name = "smtp"
type Config struct { type Config struct {
ServerInclude string `yaml:"server_include"` ServerInclude *regexp.Regexp `yaml:"server_include"`
ServerExclude string `yaml:"server_exclude"` ServerExclude *regexp.Regexp `yaml:"server_exclude"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
ServerInclude: ".+", ServerInclude: types.RegExpAny,
ServerExclude: "", ServerExclude: types.RegExpEmpty,
} }
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
serverInclude *string
serverExclude *string
serverIncludePattern *regexp.Regexp
serverExcludePattern *regexp.Regexp
badMailedMessagesBadPickupFileTotal *prometheus.Desc badMailedMessagesBadPickupFileTotal *prometheus.Desc
badMailedMessagesGeneralFailureTotal *prometheus.Desc badMailedMessagesGeneralFailureTotal *prometheus.Desc
badMailedMessagesHopCountExceededTotal *prometheus.Desc badMailedMessagesHopCountExceededTotal *prometheus.Desc
@@ -83,10 +79,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.ServerExclude == nil {
serverExclude: &config.ServerExclude, config.ServerExclude = ConfigDefaults.ServerExclude
serverInclude: &config.ServerInclude,
} }
if config.ServerInclude == nil {
config.ServerInclude = ConfigDefaults.ServerInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
@@ -94,17 +98,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
serverInclude: app.Flag( config: ConfigDefaults,
"collector.smtp.server-include",
"Regexp of virtual servers to include. Server name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.ServerInclude).String(),
serverExclude: app.Flag(
"collector.smtp.server-exclude",
"Regexp of virtual servers to exclude. Server name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.ServerExclude).String(),
} }
var serverExclude, serverInclude string
app.Flag(
"collector.smtp.server-exclude",
"Regexp of virtual servers to exclude. Server name must both match include and not match exclude to be included.",
).Default(c.config.ServerExclude.String()).StringVar(&serverExclude)
app.Flag(
"collector.smtp.server-include",
"Regexp of virtual servers to include. Server name must both match include and not match exclude to be included.",
).Default(c.config.ServerInclude.String()).StringVar(&serverInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.ServerExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", serverExclude))
if err != nil {
return fmt.Errorf("collector.smtp.server-exclude: %w", err)
}
c.config.ServerInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", serverInclude))
if err != nil {
return fmt.Errorf("collector.smtp.server-include: %w", err)
}
return nil
})
return c return c
} }
@@ -380,18 +404,6 @@ func (c *Collector) Build() error {
nil, nil,
) )
var err error
c.serverIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.serverInclude))
if err != nil {
return err
}
c.serverExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.serverExclude))
if err != nil {
return err
}
return nil return nil
} }
@@ -461,8 +473,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
for _, server := range dst { for _, server := range dst {
if server.Name == "_Total" || if server.Name == "_Total" ||
c.serverExcludePattern.MatchString(server.Name) || c.config.ServerExclude.MatchString(server.Name) ||
!c.serverIncludePattern.MatchString(server.Name) { !c.config.ServerInclude.MatchString(server.Name) {
continue continue
} }

View File

@@ -19,6 +19,7 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics. // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
contextSwitchesTotal *prometheus.Desc contextSwitchesTotal *prometheus.Desc
@@ -29,8 +30,15 @@ type Collector struct {
threads *prometheus.Desc threads *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -19,6 +19,7 @@ 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.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
connectionFailures *prometheus.Desc connectionFailures *prometheus.Desc
@@ -32,8 +33,15 @@ type Collector struct {
segmentsSentTotal *prometheus.Desc segmentsSentTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -26,6 +26,7 @@ var ConfigDefaults = Config{}
// win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics. // win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
audioBytesReceived *prometheus.Desc audioBytesReceived *prometheus.Desc
@@ -71,8 +72,15 @@ type Collector struct {
usbTXBWKBitPerSec *prometheus.Desc usbTXBWKBitPerSec *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -51,6 +51,7 @@ func isConnectionBrokerServer(logger log.Logger) bool {
// https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85) // https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85)
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/ // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
connectionBrokerEnabled bool connectionBrokerEnabled bool
@@ -74,8 +75,15 @@ type Collector struct {
workingSetPeak *prometheus.Desc workingSetPeak *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -31,7 +31,6 @@ import (
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt" "github.com/prometheus/common/expfmt"
@@ -40,19 +39,17 @@ import (
const Name = "textfile" const Name = "textfile"
type Config struct { type Config struct {
TextFileDirectories string `yaml:"text_file_directories"` TextFileDirectories []string `yaml:"text_file_directories"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
TextFileDirectories: getDefaultPath(), TextFileDirectories: []string{getDefaultPath()},
} }
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
textFileDirectories *string
directories string
// Only set for testing to get predictable output. // Only set for testing to get predictable output.
mTime *float64 mTime *float64
@@ -64,21 +61,31 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &Collector{ if config.TextFileDirectories == nil {
textFileDirectories: &config.TextFileDirectories, config.TextFileDirectories = ConfigDefaults.TextFileDirectories
} }
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c
} }
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{ c := &Collector{
textFileDirectories: app.Flag( config: ConfigDefaults,
"collector.textfile.directories",
"Directory or Directories to read text files with metrics from.",
).Default(ConfigDefaults.TextFileDirectories).String(),
} }
c.config.TextFileDirectories = make([]string, 0)
app.Flag(
"collector.textfile.directories",
"Directory or Directories to read text files with metrics from.",
).Default(strings.Join(ConfigDefaults.TextFileDirectories, ",")).StringsVar(&c.config.TextFileDirectories)
return c
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -98,12 +105,8 @@ func (c *Collector) Close() error {
} }
func (c *Collector) Build() error { func (c *Collector) Build() error {
c.directories = "" _ = level.Info(c.logger).
if utils.HasValue(c.textFileDirectories) { Log("msg", "textfile Collector directories: "+strings.Join(c.config.TextFileDirectories, ","))
c.directories = strings.Trim(*c.textFileDirectories, ",")
}
_ = level.Info(c.logger).Log("msg", "textfile Collector directories: "+c.directories)
c.mTimeDesc = prometheus.NewDesc( c.mTimeDesc = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, "textfile", "mtime_seconds"), prometheus.BuildFQName(types.Namespace, "textfile", "mtime_seconds"),
@@ -242,18 +245,18 @@ func (c *Collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<
} }
} }
func (c *Collector) exportMTimes(mtimes map[string]time.Time, ch chan<- prometheus.Metric) { func (c *Collector) exportMTimes(mTimes map[string]time.Time, ch chan<- prometheus.Metric) {
// Export the mtimes of the successful files. // Export the mtimes of the successful files.
if len(mtimes) > 0 { if len(mTimes) > 0 {
// Sorting is needed for predictable output comparison in tests. // Sorting is needed for predictable output comparison in tests.
filenames := make([]string, 0, len(mtimes)) filenames := make([]string, 0, len(mTimes))
for filename := range mtimes { for filename := range mTimes {
filenames = append(filenames, filename) filenames = append(filenames, filename)
} }
sort.Strings(filenames) sort.Strings(filenames)
for _, filename := range filenames { for _, filename := range filenames {
mtime := float64(mtimes[filename].UnixNano() / 1e9) mtime := float64(mTimes[filename].UnixNano() / 1e9)
if c.mTime != nil { if c.mTime != nil {
mtime = *c.mTime mtime = *c.mTime
} }
@@ -289,14 +292,15 @@ func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) {
// Collect implements the Collector interface. // Collect implements the Collector interface.
func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error {
errorMetric := 0.0 errorMetric := 0.0
mtimes := map[string]time.Time{} mTimes := map[string]time.Time{}
// Create empty metricFamily slice here and append parsedFamilies to it inside the loop. // Create empty metricFamily slice here and append parsedFamilies to it inside the loop.
// Once loop is complete, raise error if any duplicates are present. // Once loop is complete, raise error if any duplicates are present.
// This will ensure that duplicate metrics are correctly detected between multiple .prom files. // This will ensure that duplicate metrics are correctly detected between multiple .prom files.
metricFamilies := []*dto.MetricFamily{} var metricFamilies []*dto.MetricFamily
// Iterate over files and accumulate their metrics. // Iterate over files and accumulate their metrics.
for _, directory := range strings.Split(c.directories, ",") { for _, directory := range c.config.TextFileDirectories {
err := filepath.WalkDir(directory, func(path string, dirEntry os.DirEntry, err error) error { err := filepath.WalkDir(directory, func(path string, dirEntry os.DirEntry, err error) error {
if err != nil { if err != nil {
_ = level.Error(c.logger).Log("msg", "Error reading directory: "+path, "err", err) _ = level.Error(c.logger).Log("msg", "Error reading directory: "+path, "err", err)
@@ -317,18 +321,18 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
errorMetric = 1.0 errorMetric = 1.0
return nil return nil
} }
if _, hasName := mtimes[fileInfo.Name()]; hasName { if _, hasName := mTimes[fileInfo.Name()]; hasName {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Duplicate filename detected: %q. Skip File.", path)) _ = level.Error(c.logger).Log("msg", fmt.Sprintf("Duplicate filename detected: %q. Skip File.", path))
errorMetric = 1.0 errorMetric = 1.0
return nil return nil
} }
mtimes[fileInfo.Name()] = fileInfo.ModTime() mTimes[fileInfo.Name()] = fileInfo.ModTime()
metricFamilies = append(metricFamilies, families_array...) metricFamilies = append(metricFamilies, families_array...)
} }
return nil return nil
}) })
if err != nil && directory != "" { if err != nil && directory != "" {
_ = level.Error(c.logger).Log("msg", "Error reading textfile Collector directory: "+c.directories, "err", err) _ = level.Error(c.logger).Log("msg", "Error reading textfile Collector directory: "+directory, "err", err)
errorMetric = 1.0 errorMetric = 1.0
} }
} }
@@ -343,7 +347,7 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
} }
} }
c.exportMTimes(mtimes, ch) c.exportMTimes(mTimes, ch)
// Export if there were errors. // Export if there were errors.
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc( prometheus.NewDesc(

View File

@@ -22,11 +22,11 @@ func TestMultipleDirectories(t *testing.T) {
testDir := baseDir + "/multiple-dirs" testDir := baseDir + "/multiple-dirs"
testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir) testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir)
textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ textFileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{
TextFileDirectories: testDirs, TextFileDirectories: strings.Split(testDirs, ","),
}) })
collectors := collector.New(map[string]collector.Collector{textfile.Name: textfileCollector}) collectors := collector.New(map[string]collector.Collector{textfile.Name: textFileCollector})
require.NoError(t, collectors.Build()) require.NoError(t, collectors.Build())
scrapeContext, err := collectors.PrepareScrapeContext() scrapeContext, err := collectors.PrepareScrapeContext()
@@ -47,7 +47,7 @@ func TestMultipleDirectories(t *testing.T) {
} }
}() }()
err = textfileCollector.Collect(scrapeContext, metrics) err = textFileCollector.Collect(scrapeContext, metrics)
if err != nil { if err != nil {
t.Errorf("Unexpected error %s", err) t.Errorf("Unexpected error %s", err)
} }
@@ -63,11 +63,11 @@ func TestDuplicateFileName(t *testing.T) {
t.Parallel() t.Parallel()
testDir := baseDir + "/duplicate-filename" testDir := baseDir + "/duplicate-filename"
textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ textFileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{
TextFileDirectories: testDir, TextFileDirectories: []string{testDir},
}) })
collectors := collector.New(map[string]collector.Collector{textfile.Name: textfileCollector}) collectors := collector.New(map[string]collector.Collector{textfile.Name: textFileCollector})
require.NoError(t, collectors.Build()) require.NoError(t, collectors.Build())
scrapeContext, err := collectors.PrepareScrapeContext() scrapeContext, err := collectors.PrepareScrapeContext()
@@ -87,13 +87,15 @@ func TestDuplicateFileName(t *testing.T) {
got += metric.String() got += metric.String()
} }
}() }()
err = textfileCollector.Collect(scrapeContext, metrics) err = textFileCollector.Collect(scrapeContext, metrics)
if err != nil { if err != nil {
t.Errorf("Unexpected error %s", err) t.Errorf("Unexpected error %s", err)
} }
if !strings.Contains(got, "file") { if !strings.Contains(got, "file") {
t.Errorf("Unexpected output %q", got) t.Errorf("Unexpected output %q", got)
} }
if strings.Contains(got, "sub_file") { if strings.Contains(got, "sub_file") {
t.Errorf("Unexpected output %q", got) t.Errorf("Unexpected output %q", got)
} }

View File

@@ -21,6 +21,7 @@ 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
logger log.Logger logger log.Logger
percentPassiveLimit *prometheus.Desc percentPassiveLimit *prometheus.Desc
@@ -28,8 +29,15 @@ type Collector struct {
throttleReasons *prometheus.Desc throttleReasons *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -22,6 +22,7 @@ var ConfigDefaults = Config{}
// Collector is a Prometheus Collector for Perflib counter metrics. // Collector is a Prometheus Collector for Perflib counter metrics.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
clockFrequencyAdjustmentPPBTotal *prometheus.Desc clockFrequencyAdjustmentPPBTotal *prometheus.Desc
@@ -32,8 +33,15 @@ type Collector struct {
ntpServerOutgoingResponsesTotal *prometheus.Desc ntpServerOutgoingResponsesTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -22,6 +22,7 @@ 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.
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
memActive *prometheus.Desc memActive *prometheus.Desc
@@ -46,8 +47,15 @@ type Collector struct {
hostProcessorSpeedMHz *prometheus.Desc hostProcessorSpeedMHz *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

View File

@@ -32,6 +32,7 @@ var ConfigDefaults = Config{}
// win32_PerfRawData_Counters_VMwareBlastWindowsMediaMMRCounters // win32_PerfRawData_Counters_VMwareBlastWindowsMediaMMRCounters
type Collector struct { type Collector struct {
config Config
logger log.Logger logger log.Logger
audioReceivedBytes *prometheus.Desc audioReceivedBytes *prometheus.Desc
@@ -116,8 +117,15 @@ type Collector struct {
windowsMediaMMRTransmittedPackets *prometheus.Desc windowsMediaMMRTransmittedPackets *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, config *Config) *Collector {
c := &Collector{} if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger) c.SetLogger(logger)
return c return c

8
pkg/types/regexp.go Normal file
View File

@@ -0,0 +1,8 @@
package types
import "regexp"
var (
RegExpAny = regexp.MustCompile(".+")
RegExpEmpty = regexp.MustCompile("^$")
)

View File

@@ -20,3 +20,7 @@ func HasValue(v *string) bool {
func IsEmpty(v *string) bool { func IsEmpty(v *string) bool {
return v == nil || *v == "" return v == nil || *v == ""
} }
func ToPTR[t any](v t) *t {
return &v
}

View File

@@ -62,6 +62,7 @@ func QueryAllForClass(_ interface{}, class string, logger log.Logger) string {
return b.String() return b.String()
} }
// Deprecated: Use QueryAllForClassWhere instead.
func QueryAllWhere(src interface{}, where string, logger log.Logger) string { func QueryAllWhere(src interface{}, where string, logger log.Logger) string {
var b bytes.Buffer var b bytes.Buffer
b.WriteString("SELECT * FROM ") b.WriteString("SELECT * FROM ")