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: |
$ErrorActionPreference = "Stop"
$Version = git describe --tag
$Version = git describe --tags --always
$Version = $Version -replace 'v', ''
# '+' symbols are invalid characters in image tags
$Version = $Version -replace '\+', '_'

View File

@@ -38,9 +38,6 @@ import (
"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.
// Separate copy to avoid pulling all of prometheus as a dependency.
type prometheusVersion struct {
@@ -63,18 +60,23 @@ var priorityStringToInt = map[string]uint32{
}
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 {
return err
}
//nolint:errcheck
defer windows.CloseHandle(handle) // Technically this can fail, but we ignore it
err = windows.SetPriorityClass(handle, priority)
if err != nil {
if err = windows.SetPriorityClass(handle, priority); err != nil {
return err
}
if err = windows.CloseHandle(handle); err != nil {
return fmt.Errorf("failed to close handle: %w", err)
}
return nil
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,26 +13,23 @@ import (
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus"
)
const Name = "exchange"
type Config struct {
CollectorsEnabled string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"collectors_enabled"`
}
var ConfigDefaults = Config{
CollectorsEnabled: "",
CollectorsEnabled: []string{},
}
type Collector struct {
config Config
logger log.Logger
exchangeListAllCollectors *bool
exchangeCollectorsEnabled *string
activeMailboxDeliveryQueueLength *prometheus.Desc
activeSyncRequestsPerSec *prometheus.Desc
activeTasks *prometheus.Desc
@@ -94,28 +91,68 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
exchangeListAllCollectors := false
c := &Collector{
exchangeCollectorsEnabled: &config.CollectorsEnabled,
exchangeListAllCollectors: &exchangeListAllCollectors,
if config.CollectorsEnabled == nil {
config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
}
func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{
exchangeListAllCollectors: app.Flag(
"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 := &Collector{
config: ConfigDefaults,
}
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 {
@@ -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.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))
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...)
if len(c.config.CollectorsEnabled) == 0 {
c.enabledCollectors = exchangeAllCollectorNames
} else {
for _, collectorName := range strings.Split(*c.exchangeCollectorsEnabled, ",") {
if slices.Contains(exchangeAllCollectorNames, collectorName) {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
} else {
c.enabledCollectors = make([]string, 0, len(exchangeAllCollectorNames))
for _, collectorName := range c.config.CollectorsEnabled {
if !slices.Contains(exchangeAllCollectorNames, collectorName) {
return fmt.Errorf("unknown exchange collector: %s", collectorName)
}
c.enabledCollectors = append(c.enabledCollectors, collectorName)
}
c.enabledCollectors = slices.Clip(c.enabledCollectors)
}
return nil

View File

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

View File

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

View File

@@ -20,64 +20,23 @@ import (
const Name = "iis"
type Config struct {
SiteInclude string `yaml:"site_include"`
SiteExclude string `yaml:"site_exclude"`
AppInclude string `yaml:"app_include"`
AppExclude string `yaml:"app_exclude"`
SiteInclude *regexp.Regexp `yaml:"site_include"`
SiteExclude *regexp.Regexp `yaml:"site_exclude"`
AppInclude *regexp.Regexp `yaml:"app_include"`
AppExclude *regexp.Regexp `yaml:"app_exclude"`
}
var ConfigDefaults = Config{
SiteInclude: ".+",
SiteExclude: "",
AppInclude: ".+",
AppExclude: "",
}
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,
}
SiteInclude: types.RegExpAny,
SiteExclude: types.RegExpEmpty,
AppInclude: types.RegExpAny,
AppExclude: types.RegExpEmpty,
}
type Collector struct {
config Config
logger log.Logger
siteInclude *string
siteExclude *string
appInclude *string
appExclude *string
info *prometheus.Desc
// Web Service
@@ -104,9 +63,6 @@ type Collector struct {
totalNotFoundErrors *prometheus.Desc
totalRejectedAsyncIORequests *prometheus.Desc
siteIncludePattern *regexp.Regexp
siteExcludePattern *regexp.Regexp
// APP_POOL_WAS
currentApplicationPoolState *prometheus.Desc
currentApplicationPoolUptime *prometheus.Desc
@@ -203,10 +159,7 @@ type Collector struct {
serviceCacheOutputCacheFlushedItemsTotal *prometheus.Desc
serviceCacheOutputCacheFlushesTotal *prometheus.Desc
appIncludePattern *regexp.Regexp
appExcludePattern *regexp.Regexp
iisVersion simple_version
iisVersion simpleVersion
}
func New(logger log.Logger, config *Config) *Collector {
@@ -214,11 +167,24 @@ func New(logger log.Logger, config *Config) *Collector {
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{
appInclude: &config.AppInclude,
appExclude: &config.AppExclude,
siteInclude: &config.SiteInclude,
siteExclude: &config.SiteExclude,
config: *config,
}
c.SetLogger(logger)
@@ -228,27 +194,57 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
siteInclude: 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(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(),
config: ConfigDefaults,
}
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
}
@@ -276,27 +272,6 @@ func (c *Collector) Close() error {
func (c *Collector) Build() error {
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(
prometheus.BuildFQName(types.Namespace, Name, "info"),
"ISS information",
@@ -918,6 +893,43 @@ func (c *Collector) Build() error {
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
// to the provided prometheus Metric channel.
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)
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
}
@@ -1336,8 +1348,8 @@ func (c *Collector) collectAPP_POOL_WAS(ctx *types.ScrapeContext, ch chan<- prom
for name, app := range appPoolDeDuplicated {
if name == "_Total" ||
c.appExcludePattern.MatchString(name) ||
!c.appIncludePattern.MatchString(name) {
c.config.AppExclude.MatchString(name) ||
!c.config.AppInclude.MatchString(name) {
continue
}
@@ -1516,8 +1528,8 @@ func (c *Collector) collectW3SVC_W3WP(ctx *types.ScrapeContext, ch chan<- promet
pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2")
if name == "" || name == "_Total" ||
c.appExcludePattern.MatchString(name) ||
!c.appIncludePattern.MatchString(name) {
c.config.AppExclude.MatchString(name) ||
!c.config.AppInclude.MatchString(name) {
continue
}
@@ -1774,8 +1786,8 @@ func (c *Collector) collectW3SVC_W3WP(ctx *types.ScrapeContext, ch chan<- promet
pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2")
if name == "" || name == "_Total" ||
c.appExcludePattern.MatchString(name) ||
!c.appIncludePattern.MatchString(name) {
c.config.AppExclude.MatchString(name) ||
!c.config.AppInclude.MatchString(name) {
continue
}

View File

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

View File

@@ -22,24 +22,20 @@ import (
const Name = "logical_disk"
type Config struct {
VolumeInclude string `yaml:"volume_include"`
VolumeExclude string `yaml:"volume_exclude"`
VolumeInclude *regexp.Regexp `yaml:"volume_include"`
VolumeExclude *regexp.Regexp `yaml:"volume_exclude"`
}
var ConfigDefaults = Config{
VolumeInclude: ".+",
VolumeExclude: "",
VolumeInclude: types.RegExpAny,
VolumeExclude: types.RegExpEmpty,
}
// A Collector is a Prometheus Collector for perflib logicalDisk metrics.
type Collector struct {
config Config
logger log.Logger
volumeInclude *string
volumeExclude *string
volumeIncludePattern *regexp.Regexp
volumeExcludePattern *regexp.Regexp
avgReadQueue *prometheus.Desc
avgWriteQueue *prometheus.Desc
freeSpace *prometheus.Desc
@@ -73,10 +69,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
c := &Collector{
volumeExclude: &config.VolumeExclude,
volumeInclude: &config.VolumeInclude,
if config.VolumeExclude == nil {
config.VolumeExclude = ConfigDefaults.VolumeExclude
}
if config.VolumeInclude == nil {
config.VolumeInclude = ConfigDefaults.VolumeInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
@@ -84,16 +88,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
volumeInclude: 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(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(),
config: ConfigDefaults,
}
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
}
@@ -238,17 +263,6 @@ func (c *Collector) Build() error {
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
}
@@ -299,8 +313,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
for _, volume := range dst {
if volume.Name == "_Total" ||
c.volumeExcludePattern.MatchString(volume.Name) ||
!c.volumeIncludePattern.MatchString(volume.Name) {
c.config.VolumeExclude.MatchString(volume.Name) ||
!c.config.VolumeInclude.MatchString(volume.Name) {
continue
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -17,19 +17,18 @@ import (
const Name = "msmq"
type Config struct {
QueryWhereClause string `yaml:"query_where_clause"`
QueryWhereClause *string `yaml:"query_where_clause"`
}
var ConfigDefaults = Config{
QueryWhereClause: "",
QueryWhereClause: utils.ToPTR(""),
}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics.
type Collector struct {
config Config
logger log.Logger
queryWhereClause *string
bytesInJournalQueue *prometheus.Desc
bytesInQueue *prometheus.Desc
messagesInJournalQueue *prometheus.Desc
@@ -41,20 +40,29 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
c := &Collector{
queryWhereClause: &config.QueryWhereClause,
if config.QueryWhereClause == nil {
config.QueryWhereClause = ConfigDefaults.QueryWhereClause
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
}
func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{
queryWhereClause: 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(ConfigDefaults.QueryWhereClause).String(),
c := &Collector{
config: ConfigDefaults,
}
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 {
@@ -74,7 +82,7 @@ func (c *Collector) Close() 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!")
}
@@ -115,18 +123,19 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
return nil
}
type Win32_PerfRawData_MSMQ_MSMQQueue struct {
type msmqQueue struct {
Name string
BytesinJournalQueue uint64
BytesinQueue uint64
MessagesinJournalQueue uint64
MessagesinQueue uint64
BytesInJournalQueue uint64
BytesInQueue uint64
MessagesInJournalQueue uint64
MessagesInQueue uint64
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_MSMQ_MSMQQueue
q := wmi.QueryAllWhere(&dst, *c.queryWhereClause, c.logger)
var dst []msmqQueue
q := wmi.QueryAllForClassWhere(&dst, "Win32_PerfRawData_MSMQ_MSMQQueue", *c.config.QueryWhereClause, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return err
}
@@ -135,30 +144,31 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
ch <- prometheus.MustNewConstMetric(
c.bytesInJournalQueue,
prometheus.GaugeValue,
float64(msmq.BytesinJournalQueue),
float64(msmq.BytesInJournalQueue),
strings.ToLower(msmq.Name),
)
ch <- prometheus.MustNewConstMetric(
c.bytesInQueue,
prometheus.GaugeValue,
float64(msmq.BytesinQueue),
float64(msmq.BytesInQueue),
strings.ToLower(msmq.Name),
)
ch <- prometheus.MustNewConstMetric(
c.messagesInJournalQueue,
prometheus.GaugeValue,
float64(msmq.MessagesinJournalQueue),
float64(msmq.MessagesInJournalQueue),
strings.ToLower(msmq.Name),
)
ch <- prometheus.MustNewConstMetric(
c.messagesInQueue,
prometheus.GaugeValue,
float64(msmq.MessagesinQueue),
float64(msmq.MessagesInQueue),
strings.ToLower(msmq.Name),
)
}
return nil
}

View File

@@ -6,6 +6,8 @@ import (
"errors"
"fmt"
"os"
"slices"
"sort"
"strings"
"sync"
"time"
@@ -15,7 +17,6 @@ import (
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows/registry"
)
@@ -23,11 +24,24 @@ import (
const Name = "mssql"
type Config struct {
EnabledCollectors string `yaml:"collectors_enabled"` //nolint:tagliatelle
CollectorsEnabled []string `yaml:"collectors_enabled"`
}
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
@@ -39,8 +53,8 @@ func getMSSQLInstances(logger log.Logger) mssqlInstancesType {
sqlDefaultInstance := make(mssqlInstancesType)
sqlDefaultInstance["MSSQLSERVER"] = ""
regkey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.QUERY_VALUE)
regKey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regKey, registry.QUERY_VALUE)
if err != nil {
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine SQL instances", "err", err)
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.
type Collector struct {
config Config
logger log.Logger
mssqlEnabledCollectors *string
mssqlPrintCollectors *bool
// meta
mssqlScrapeDurationDesc *prometheus.Desc
mssqlScrapeSuccessDesc *prometheus.Desc
@@ -408,29 +420,55 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
printCollectors := false
if config.CollectorsEnabled == nil {
config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
}
c := &Collector{
mssqlEnabledCollectors: &config.EnabledCollectors,
mssqlPrintCollectors: &printCollectors,
config: *config,
}
c.SetLogger(logger)
return c
}
func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{
mssqlEnabledCollectors: app.Flag(
"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 := &Collector{
config: ConfigDefaults,
}
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 {
@@ -442,9 +480,14 @@ func (c *Collector) SetLogger(logger log.Logger) {
}
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)
perfCounters := make([]string, 0, len(c.mssqlInstances)*len(enabled))
for instance := range c.mssqlInstances {
for _, c := range enabled {
perfCounters = append(perfCounters, mssqlGetPerfObjectName(instance, c))
@@ -1922,15 +1965,6 @@ func (c *Collector) Build() error {
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
}
@@ -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 {
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 _, name := range enabled {
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)
}
}
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 {
return errors.New("at least one child collector failed")
}
return nil
}

View File

@@ -17,24 +17,22 @@ import (
const Name = "net"
type Config struct {
NicInclude string `yaml:"nic_include"`
NicExclude string `yaml:"nic_exclude"`
NicExclude *regexp.Regexp `yaml:"nic_exclude"`
NicInclude *regexp.Regexp `yaml:"nic_include"`
}
var ConfigDefaults = Config{
NicInclude: ".+",
NicExclude: "",
NicExclude: types.RegExpEmpty,
NicInclude: types.RegExpAny,
}
var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
// A Collector is a Prometheus Collector for Perflib Network Interface metrics.
type Collector struct {
config Config
logger log.Logger
nicInclude *string
nicExclude *string
bytesReceivedTotal *prometheus.Desc
bytesSentTotal *prometheus.Desc
bytesTotal *prometheus.Desc
@@ -48,9 +46,6 @@ type Collector struct {
packetsReceivedUnknown *prometheus.Desc
packetsSentTotal *prometheus.Desc
currentBandwidth *prometheus.Desc
nicIncludePattern *regexp.Regexp
nicExcludePattern *regexp.Regexp
}
func New(logger log.Logger, config *Config) *Collector {
@@ -58,10 +53,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
c := &Collector{
nicExclude: &config.NicExclude,
nicInclude: &config.NicInclude,
if config.NicExclude == nil {
config.NicExclude = ConfigDefaults.NicExclude
}
if config.NicInclude == nil {
config.NicInclude = ConfigDefaults.NicInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
@@ -69,17 +72,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
nicInclude: 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(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(),
config: ConfigDefaults,
}
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
}
@@ -179,17 +202,6 @@ func (c *Collector) Build() error {
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
}
@@ -236,8 +248,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
}
for _, nic := range dst {
if c.nicExcludePattern.MatchString(nic.Name) ||
!c.nicIncludePattern.MatchString(nic.Name) {
if c.config.NicExclude.MatchString(nic.Name) ||
!c.config.NicInclude.MatchString(nic.Name) {
continue
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,7 +15,6 @@ import (
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows"
@@ -24,31 +23,23 @@ import (
const Name = "process"
type Config struct {
ProcessInclude string `yaml:"process_include"`
ProcessExclude string `yaml:"process_exclude"`
EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle
EnableReportOwner bool `yaml:"enable_report_owner"`
ProcessInclude *regexp.Regexp `yaml:"process_include"`
ProcessExclude *regexp.Regexp `yaml:"process_exclude"`
EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle
EnableReportOwner bool `yaml:"enable_report_owner"`
}
var ConfigDefaults = Config{
ProcessInclude: ".+",
ProcessExclude: "",
ProcessInclude: types.RegExpAny,
ProcessExclude: types.RegExpEmpty,
EnableWorkerProcess: false,
EnableReportOwner: false,
}
type Collector struct {
config Config
logger log.Logger
enableWorkerProcess *bool
enableReportOwner *bool
processInclude *string
processExclude *string
processIncludePattern *regexp.Regexp
processExcludePattern *regexp.Regexp
lookupCache map[string]string
cpuTimeTotal *prometheus.Desc
@@ -73,11 +64,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
c := &Collector{
processExclude: &config.ProcessExclude,
processInclude: &config.ProcessInclude,
enableWorkerProcess: &config.EnableWorkerProcess,
if config.ProcessExclude == nil {
config.ProcessExclude = ConfigDefaults.ProcessExclude
}
if config.ProcessInclude == nil {
config.ProcessInclude = ConfigDefaults.ProcessInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
@@ -85,26 +83,47 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
processInclude: app.Flag(
"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(),
config: ConfigDefaults,
}
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
}
@@ -125,12 +144,12 @@ func (c *Collector) Close() 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!")
}
commonLabels := make([]string, 0)
if *c.enableReportOwner {
if c.config.EnableReportOwner {
commonLabels = []string{"owner"}
}
@@ -227,18 +246,6 @@ func (c *Collector) Build() error {
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
}
@@ -262,7 +269,7 @@ type perflibProcess struct {
PageFaultsPerSec float64 `perflib:"Page Faults/sec"`
PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"`
PageFileBytes float64 `perflib:"Page File Bytes"`
PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
PoolNonPagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
PoolPagedBytes float64 `perflib:"Pool Paged Bytes"`
PriorityBase float64 `perflib:"Priority Base"`
PrivateBytes float64 `perflib:"Private Bytes"`
@@ -286,10 +293,10 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return err
}
var dst_wp []WorkerProcess
if *c.enableWorkerProcess {
q_wp := wmi.QueryAll(&dst_wp, c.logger)
if err := wmi.QueryNamespace(q_wp, &dst_wp, "root\\WebAdministration"); err != nil {
var workerProcesses []WorkerProcess
if c.config.EnableWorkerProcess {
queryWorkerProcess := wmi.QueryAllForClass(&workerProcesses, "WorkerProcess", c.logger)
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)
}
}
@@ -298,17 +305,18 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
for _, process := range data {
if process.Name == "_Total" ||
c.processExcludePattern.MatchString(process.Name) ||
!c.processIncludePattern.MatchString(process.Name) {
c.config.ProcessExclude.MatchString(process.Name) ||
!c.config.ProcessInclude.MatchString(process.Name) {
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 {
for _, wp := range dst_wp {
// Duplicate processes are suffixed #, and an index number. Remove those.
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) {
processName = strings.Join([]string{processName, wp.AppPoolName}, "_")
break
@@ -318,7 +326,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
labels := make([]string, 0, 4)
if *c.enableReportOwner {
if c.config.EnableReportOwner {
owner, err = c.getProcessOwner(int(process.IDProcess))
if err != nil {
owner = "unknown"
@@ -327,7 +335,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
labels = []string{owner}
}
labels = append(labels, processName, pid, cpid)
labels = append(labels, processName, pid, parentPID)
ch <- prometheus.MustNewConstMetric(
c.startTime,
@@ -416,7 +424,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
ch <- prometheus.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
process.PoolNonpagedBytes,
process.PoolNonPagedBytes,
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_remotefxgraphics/
type Collector struct {
config Config
logger log.Logger
// net
@@ -53,8 +54,15 @@ type Collector struct {
sourceFramesPerSecond *prometheus.Desc
}
func New(logger log.Logger, _ *Config) *Collector {
c := &Collector{}
func New(logger log.Logger, config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c

View File

@@ -18,35 +18,25 @@ import (
"github.com/prometheus/client_golang/prometheus"
)
const (
Name = "scheduled_task"
FlagScheduledTaskExclude = "collector.scheduled_task.exclude"
FlagScheduledTaskInclude = "collector.scheduled_task.include"
)
const Name = "scheduled_task"
type Config struct {
TaskExclude string `yaml:"task_exclude"`
TaskInclude string `yaml:"task_include"`
TaskExclude *regexp.Regexp `yaml:"task_exclude"`
TaskInclude *regexp.Regexp `yaml:"task_include"`
}
var ConfigDefaults = Config{
TaskExclude: "",
TaskInclude: ".+",
TaskExclude: types.RegExpEmpty,
TaskInclude: types.RegExpAny,
}
type Collector struct {
config Config
logger log.Logger
taskExclude *string
taskInclude *string
lastResult *prometheus.Desc
missedRuns *prometheus.Desc
state *prometheus.Desc
taskIncludePattern *regexp.Regexp
taskExcludePattern *regexp.Regexp
}
// TaskState ...
@@ -80,10 +70,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
c := &Collector{
taskExclude: &config.TaskExclude,
taskInclude: &config.TaskInclude,
if config.TaskExclude == nil {
config.TaskExclude = ConfigDefaults.TaskExclude
}
if config.TaskInclude == nil {
config.TaskInclude = ConfigDefaults.TaskInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
@@ -91,17 +89,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
taskInclude: app.Flag(
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(),
config: ConfigDefaults,
}
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
}
@@ -143,18 +161,6 @@ func (c *Collector) Build() error {
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
}
@@ -176,8 +182,8 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
}
for _, task := range scheduledTasks {
if c.taskExcludePattern.MatchString(task.Path) ||
!c.taskIncludePattern.MatchString(task.Path) {
if c.config.TaskExclude.MatchString(task.Path) ||
!c.config.TaskInclude.MatchString(task.Path) {
continue
}

View File

@@ -226,7 +226,7 @@ var (
func (c *Collector) collectWMI(ch chan<- prometheus.Metric) error {
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 {
return err
}

View File

@@ -3,9 +3,6 @@
package smb
import (
"fmt"
"os"
"slices"
"strings"
"github.com/alecthomas/kingpin/v2"
@@ -18,29 +15,16 @@ import (
const Name = "smb"
type Config struct {
CollectorsEnabled string `yaml:"collectors_enabled"`
}
type Config struct{}
var ConfigDefaults = Config{
CollectorsEnabled: "",
}
var ConfigDefaults = Config{}
type Collector struct {
config Config
logger log.Logger
smbListAllCollectors *bool
smbCollectorsEnabled *string
treeConnectCount *prometheus.Desc
currentOpenFileCount *prometheus.Desc
enabledCollectors []string
}
// All available Collector functions.
var smbAllCollectorNames = []string{
"ServerShares",
}
func New(logger log.Logger, config *Config) *Collector {
@@ -48,10 +32,8 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
smbListAllCollectors := false
c := &Collector{
smbCollectorsEnabled: &config.CollectorsEnabled,
smbListAllCollectors: &smbListAllCollectors,
config: *config,
}
c.SetLogger(logger)
@@ -59,18 +41,8 @@ func New(logger log.Logger, config *Config) *Collector {
return c
}
func NewWithFlags(app *kingpin.Application) *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 NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{}
}
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.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
}
// Collect collects smb metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{
"ServerShares": c.collectServerShares,
if err := c.collectServerShares(ctx, ch); err != nil {
_ = 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
}

View File

@@ -3,9 +3,6 @@
package smbclient
import (
"fmt"
"os"
"slices"
"strings"
"github.com/alecthomas/kingpin/v2"
@@ -20,22 +17,14 @@ const (
Name = "smbclient"
)
type Config struct {
CollectorsEnabled string `yaml:"collectors_enabled"`
}
type Config struct{}
var ConfigDefaults = Config{
CollectorsEnabled: "",
}
var ConfigDefaults = Config{}
type Collector struct {
config Config
logger log.Logger
enabledCollectors []string
smbClientListAllCollectors *bool
smbClientCollectorsEnabled *string
readBytesTotal *prometheus.Desc
readBytesTransmittedViaSMBDirectTotal *prometheus.Desc
readRequestQueueSecsTotal *prometheus.Desc
@@ -60,38 +49,22 @@ type Collector struct {
requestSecs *prometheus.Desc
}
// All available collector functions.
var smbclientAllCollectorNames = []string{
"ClientShares",
}
func New(logger log.Logger, config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
smbclientListAllCollectors := false
c := &Collector{
smbClientCollectorsEnabled: &config.CollectorsEnabled,
smbClientListAllCollectors: &smbclientListAllCollectors,
config: *config,
}
c.SetLogger(logger)
return c
}
func NewWithFlags(app *kingpin.Application) *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 NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{}
}
func (c *Collector) GetName() string {
@@ -208,48 +181,16 @@ func (c *Collector) Build() error {
[]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
}
// Collect collects smb client metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{
"ClientShares": c.collectClientShares,
if err := c.collectClientShares(ctx, ch); err != nil {
_ = 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
}

View File

@@ -17,23 +17,19 @@ import (
const Name = "smtp"
type Config struct {
ServerInclude string `yaml:"server_include"`
ServerExclude string `yaml:"server_exclude"`
ServerInclude *regexp.Regexp `yaml:"server_include"`
ServerExclude *regexp.Regexp `yaml:"server_exclude"`
}
var ConfigDefaults = Config{
ServerInclude: ".+",
ServerExclude: "",
ServerInclude: types.RegExpAny,
ServerExclude: types.RegExpEmpty,
}
type Collector struct {
config Config
logger log.Logger
serverInclude *string
serverExclude *string
serverIncludePattern *regexp.Regexp
serverExcludePattern *regexp.Regexp
badMailedMessagesBadPickupFileTotal *prometheus.Desc
badMailedMessagesGeneralFailureTotal *prometheus.Desc
badMailedMessagesHopCountExceededTotal *prometheus.Desc
@@ -83,10 +79,18 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
c := &Collector{
serverExclude: &config.ServerExclude,
serverInclude: &config.ServerInclude,
if config.ServerExclude == nil {
config.ServerExclude = ConfigDefaults.ServerExclude
}
if config.ServerInclude == nil {
config.ServerInclude = ConfigDefaults.ServerInclude
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
@@ -94,17 +98,37 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
serverInclude: 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(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(),
config: ConfigDefaults,
}
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
}
@@ -380,18 +404,6 @@ func (c *Collector) Build() error {
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
}
@@ -461,8 +473,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
for _, server := range dst {
if server.Name == "_Total" ||
c.serverExcludePattern.MatchString(server.Name) ||
!c.serverIncludePattern.MatchString(server.Name) {
c.config.ServerExclude.MatchString(server.Name) ||
!c.config.ServerInclude.MatchString(server.Name) {
continue
}

View File

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

View File

@@ -26,6 +26,7 @@ var ConfigDefaults = Config{}
// win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics.
type Collector struct {
config Config
logger log.Logger
audioBytesReceived *prometheus.Desc
@@ -71,8 +72,15 @@ type Collector struct {
usbTXBWKBitPerSec *prometheus.Desc
}
func New(logger log.Logger, _ *Config) *Collector {
c := &Collector{}
func New(logger log.Logger, config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
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://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/
type Collector struct {
config Config
logger log.Logger
connectionBrokerEnabled bool
@@ -74,8 +75,15 @@ type Collector struct {
workingSetPeak *prometheus.Desc
}
func New(logger log.Logger, _ *Config) *Collector {
c := &Collector{}
func New(logger log.Logger, config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c

View File

@@ -31,7 +31,6 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
@@ -40,19 +39,17 @@ import (
const Name = "textfile"
type Config struct {
TextFileDirectories string `yaml:"text_file_directories"`
TextFileDirectories []string `yaml:"text_file_directories"`
}
var ConfigDefaults = Config{
TextFileDirectories: getDefaultPath(),
TextFileDirectories: []string{getDefaultPath()},
}
type Collector struct {
config Config
logger log.Logger
textFileDirectories *string
directories string
// Only set for testing to get predictable output.
mTime *float64
@@ -64,21 +61,31 @@ func New(logger log.Logger, config *Config) *Collector {
config = &ConfigDefaults
}
c := &Collector{
textFileDirectories: &config.TextFileDirectories,
if config.TextFileDirectories == nil {
config.TextFileDirectories = ConfigDefaults.TextFileDirectories
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
return c
}
func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{
textFileDirectories: app.Flag(
"collector.textfile.directories",
"Directory or Directories to read text files with metrics from.",
).Default(ConfigDefaults.TextFileDirectories).String(),
c := &Collector{
config: ConfigDefaults,
}
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 {
@@ -98,12 +105,8 @@ func (c *Collector) Close() error {
}
func (c *Collector) Build() error {
c.directories = ""
if utils.HasValue(c.textFileDirectories) {
c.directories = strings.Trim(*c.textFileDirectories, ",")
}
_ = level.Info(c.logger).Log("msg", "textfile Collector directories: "+c.directories)
_ = level.Info(c.logger).
Log("msg", "textfile Collector directories: "+strings.Join(c.config.TextFileDirectories, ","))
c.mTimeDesc = prometheus.NewDesc(
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.
if len(mtimes) > 0 {
if len(mTimes) > 0 {
// Sorting is needed for predictable output comparison in tests.
filenames := make([]string, 0, len(mtimes))
for filename := range mtimes {
filenames := make([]string, 0, len(mTimes))
for filename := range mTimes {
filenames = append(filenames, filename)
}
sort.Strings(filenames)
for _, filename := range filenames {
mtime := float64(mtimes[filename].UnixNano() / 1e9)
mtime := float64(mTimes[filename].UnixNano() / 1e9)
if c.mTime != nil {
mtime = *c.mTime
}
@@ -289,14 +292,15 @@ func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) {
// Collect implements the Collector interface.
func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error {
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.
// Once loop is complete, raise error if any duplicates are present.
// 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.
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 {
if err != nil {
_ = 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
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))
errorMetric = 1.0
return nil
}
mtimes[fileInfo.Name()] = fileInfo.ModTime()
mTimes[fileInfo.Name()] = fileInfo.ModTime()
metricFamilies = append(metricFamilies, families_array...)
}
return nil
})
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
}
}
@@ -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.
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(

View File

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

View File

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

View File

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

View File

@@ -32,6 +32,7 @@ var ConfigDefaults = Config{}
// win32_PerfRawData_Counters_VMwareBlastWindowsMediaMMRCounters
type Collector struct {
config Config
logger log.Logger
audioReceivedBytes *prometheus.Desc
@@ -116,8 +117,15 @@ type Collector struct {
windowsMediaMMRTransmittedPackets *prometheus.Desc
}
func New(logger log.Logger, _ *Config) *Collector {
c := &Collector{}
func New(logger log.Logger, config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
c.SetLogger(logger)
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 {
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()
}
// Deprecated: Use QueryAllForClassWhere instead.
func QueryAllWhere(src interface{}, where string, logger log.Logger) string {
var b bytes.Buffer
b.WriteString("SELECT * FROM ")