chore: enable more linter (#1557)

This commit is contained in:
Jan-Otto Kröpke
2024-08-10 22:05:33 +02:00
committed by GitHub
parent 27a3553dac
commit 9b02e4a0ea
87 changed files with 337 additions and 494 deletions

View File

@@ -4,79 +4,49 @@ linters:
- containedctx - containedctx
- contextcheck - contextcheck
- cyclop - cyclop
- decorder
- depguard - depguard
- dogsled - dogsled
- dupl - dupl
- dupword
- durationcheck
- err113 - err113
- errchkjson
- errname
- errorlint
- exhaustive - exhaustive
- exhaustruct - exhaustruct
- exportloopref
- fatcontext - fatcontext
- funlen - funlen
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoglobals - gochecknoglobals
- gochecknoinits
- gochecksumtype
- gocognit - gocognit
- goconst - goconst
- gocritic
- gocyclo - gocyclo
- godot
- godox - godox
- gofumpt
- goimports
- gomoddirectives
- gomodguard
- gosimple
- gosmopolitan
- grouper
- importas
- inamedparam - inamedparam
- interfacebloat
- intrange
- ireturn - ireturn
- lll - lll
- maintidx
- mirror
- misspell
- mnd - mnd
- musttag
- nakedret
- nestif
- nlreturn - nlreturn
- noctx - noctx
- nonamedreturns
- nosprintfhostport
- paralleltest
- predeclared
- protogetter
- reassign
- rowserrcheck
- sloglint
- spancheck
- sqlclosecheck
- staticcheck
- stylecheck
- tagalign
- tagliatelle
- tenv
- testableexamples
- testifylint
- testpackage - testpackage
- thelper
- tparallel
- varnamelen - varnamelen
- wrapcheck - wrapcheck
- wsl - wsl
- execinquery - execinquery
- gomnd - gomnd
- stylecheck
- maintidx
linters-settings:
gci:
sections:
- prefix(github.com/prometheus-community/windows_exporter/pkg/initiate)
- standard # Standard section: captures all standard packages.
- default # Default section: contains all imports that could not be matched to another section type.
custom-order: true
tagliatelle:
case:
use-field-name: true
rules:
# Any struct tag type can be used.
# Support string case: `camel`, `pascal`, `kebab`, `snake`, `upperSnake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header`
json: camel
yaml: snake
issues: issues:
exclude: exclude:

View File

@@ -4,7 +4,12 @@
package main package main
//goland:noinspection GoUnsortedImport
//nolint:gofumpt
import ( import (
// Its important that we do these first so that we can register with the Windows service control ASAP to avoid timeouts.
"github.com/prometheus-community/windows_exporter/pkg/initiate"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
@@ -22,8 +27,6 @@ import (
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/collector" "github.com/prometheus-community/windows_exporter/pkg/collector"
"github.com/prometheus-community/windows_exporter/pkg/config" "github.com/prometheus-community/windows_exporter/pkg/config"
// Its important that we do these first so that we can register with the Windows service control ASAP to avoid timeouts
"github.com/prometheus-community/windows_exporter/pkg/initiate"
winlog "github.com/prometheus-community/windows_exporter/pkg/log" winlog "github.com/prometheus-community/windows_exporter/pkg/log"
"github.com/prometheus-community/windows_exporter/pkg/log/flag" "github.com/prometheus-community/windows_exporter/pkg/log/flag"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
@@ -39,7 +42,7 @@ import (
const PROCESS_ALL_ACCESS = windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | windows.SPECIFIC_RIGHTS_ALL const PROCESS_ALL_ACCESS = windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | windows.SPECIFIC_RIGHTS_ALL
// Same struct prometheus uses for their /version endpoint. // Same struct prometheus uses for their /version endpoint.
// Separate copy to avoid pulling all of prometheus as a dependency // Separate copy to avoid pulling all of prometheus as a dependency.
type prometheusVersion struct { type prometheusVersion struct {
Version string `json:"version"` Version string `json:"version"`
Revision string `json:"revision"` Revision string `json:"revision"`
@@ -49,7 +52,7 @@ type prometheusVersion struct {
GoVersion string `json:"goVersion"` GoVersion string `json:"goVersion"`
} }
// Mapping of priority names to uin32 values required by windows.SetPriorityClass // Mapping of priority names to uin32 values required by windows.SetPriorityClass.
var priorityStringToInt = map[string]uint32{ var priorityStringToInt = map[string]uint32{
"realtime": windows.REALTIME_PRIORITY_CLASS, "realtime": windows.REALTIME_PRIORITY_CLASS,
"high": windows.HIGH_PRIORITY_CLASS, "high": windows.HIGH_PRIORITY_CLASS,

View File

@@ -19,7 +19,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -18,7 +18,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for Perflib Cache metrics // A Collector is a Prometheus Collector for Perflib Cache metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -258,7 +258,7 @@ func (c *Collector) Build() error {
return nil return nil
} }
// Collect implements the Collector interface // Collect implements the Collector interface.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
if err := c.collect(ctx, ch); err != nil { if err := c.collect(ctx, ch); err != nil {
_ = level.Error(c.logger).Log("msg", "failed collecting cache metrics", "err", err) _ = level.Error(c.logger).Log("msg", "failed collecting cache metrics", "err", err)

View File

@@ -69,7 +69,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
) )
// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse // NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse.
func NewWithFlags(app *kingpin.Application) Collectors { func NewWithFlags(app *kingpin.Application) Collectors {
collectors := map[string]Collector{} collectors := map[string]Collector{}
@@ -195,7 +195,7 @@ func (c *Collectors) SetPerfCounterQuery() error {
return nil return nil
} }
// Enable removes all collectors that not enabledCollectors // Enable removes all collectors that not enabledCollectors.
func (c *Collectors) Enable(enabledCollectors []string) { func (c *Collectors) Enable(enabledCollectors []string) {
for name := range c.collectors { for name := range c.collectors {
if !slices.Contains(enabledCollectors, name) { if !slices.Contains(enabledCollectors, name) {
@@ -204,7 +204,7 @@ func (c *Collectors) Enable(enabledCollectors []string) {
} }
} }
// Build To be called by the exporter for collector initialization // Build To be called by the exporter for collector initialization.
func (c *Collectors) Build() error { func (c *Collectors) Build() error {
var err error var err error
@@ -217,7 +217,7 @@ func (c *Collectors) Build() error {
return nil return nil
} }
// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape // PrepareScrapeContext creates a ScrapeContext to be used during a single scrape.
func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) { func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) {
objs, err := perflib.GetPerflibSnapshot(c.perfCounterQuery) objs, err := perflib.GetPerflibSnapshot(c.perfCounterQuery)
if err != nil { if err != nil {
@@ -227,7 +227,7 @@ func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) {
return &types.ScrapeContext{PerfObjects: objs}, nil return &types.ScrapeContext{PerfObjects: objs}, nil
} }
// Close To be called by the exporter for collector cleanup // Close To be called by the exporter for collector cleanup.
func (c *Collectors) Close() error { func (c *Collectors) Close() error {
errs := make([]error, 0, len(c.collectors)) errs := make([]error, 0, len(c.collectors))

View File

@@ -70,7 +70,7 @@ type Config struct {
Cs cs.Config `yaml:"cs"` Cs cs.Config `yaml:"cs"`
DFSR dfsr.Config `yaml:"dfsr"` DFSR dfsr.Config `yaml:"dfsr"`
Dhcp dhcp.Config `yaml:"dhcp"` Dhcp dhcp.Config `yaml:"dhcp"`
DiskDrive diskdrive.Config `yaml:"diskdrive"` DiskDrive diskdrive.Config `yaml:"diskdrive"` //nolint:tagliatelle
DNS dns.Config `yaml:"dns"` DNS dns.Config `yaml:"dns"`
Exchange exchange.Config `yaml:"exchange"` Exchange exchange.Config `yaml:"exchange"`
Fsrmquota fsrmquota.Config `yaml:"fsrmquota"` Fsrmquota fsrmquota.Config `yaml:"fsrmquota"`
@@ -84,7 +84,7 @@ type Config struct {
MsclusterNetwork mscluster_network.Config `yaml:"mscluster_network"` MsclusterNetwork mscluster_network.Config `yaml:"mscluster_network"`
MsclusterNode mscluster_node.Config `yaml:"mscluster_node"` MsclusterNode mscluster_node.Config `yaml:"mscluster_node"`
MsclusterResource mscluster_resource.Config `yaml:"mscluster_resource"` MsclusterResource mscluster_resource.Config `yaml:"mscluster_resource"`
MsclusterResourceGroup mscluster_resourcegroup.Config `yaml:"mscluster_resourcegroup"` MsclusterResourceGroup mscluster_resourcegroup.Config `yaml:"mscluster_resourcegroup"` //nolint:tagliatelle
Msmq msmq.Config `yaml:"msmq"` Msmq msmq.Config `yaml:"msmq"`
Mssql mssql.Config `yaml:"mssql"` Mssql mssql.Config `yaml:"mssql"`
Net net.Config `yaml:"net"` Net net.Config `yaml:"net"`
@@ -105,7 +105,7 @@ type Config struct {
ScheduledTask scheduled_task.Config `yaml:"scheduled_task"` ScheduledTask scheduled_task.Config `yaml:"scheduled_task"`
Service service.Config `yaml:"service"` Service service.Config `yaml:"service"`
SMB smb.Config `yaml:"smb"` SMB smb.Config `yaml:"smb"`
SMBClient smbclient.Config `yaml:"smbclient"` SMBClient smbclient.Config `yaml:"smbclient"` //nolint:tagliatelle
SMTP smtp.Config `yaml:"smtp"` SMTP smtp.Config `yaml:"smtp"`
System system.Config `yaml:"system"` System system.Config `yaml:"system"`
TeradiciPcoip teradici_pcoip.Config `yaml:"teradici_pcoip"` TeradiciPcoip teradici_pcoip.Config `yaml:"teradici_pcoip"`

View File

@@ -20,7 +20,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for containers metrics // A Collector is a Prometheus Collector for containers metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -55,7 +55,7 @@ type Collector struct {
writeSizeBytes *prometheus.Desc writeSizeBytes *prometheus.Desc
} }
// New constructs a new Collector // New constructs a new Collector.
func New(logger log.Logger, _ *Config) *Collector { func New(logger log.Logger, _ *Config) *Collector {
c := &Collector{} c := &Collector{}
c.SetLogger(logger) c.SetLogger(logger)
@@ -205,7 +205,7 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
return nil return nil
} }
// containerClose closes the container resource // containerClose closes the container resource.
func (c *Collector) containerClose(container hcsshim.Container) { func (c *Collector) containerClose(container hcsshim.Container) {
err := container.Close() err := container.Close()
if err != nil { if err != nil {

View File

@@ -25,7 +25,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor // A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -62,7 +62,7 @@ func (c *Collector) Close() error {
func (c *Collector) Build() error { func (c *Collector) Build() error {
c.cpuInfo = prometheus.NewDesc( c.cpuInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, "", Name), prometheus.BuildFQName(types.Namespace, "", Name),
"Labelled CPU information as provided provided by Win32_Processor", "Labelled CPU information as provided by Win32_Processor",
[]string{ []string{
"architecture", "architecture",
"device_id", "device_id",

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -82,7 +82,7 @@ type Collector struct {
type dfsrCollectorFunc func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error type dfsrCollectorFunc func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error
// Map Perflib sources to DFSR Collector names // Map Perflib sources to DFSR Collector names
// e.g, volume -> DFS Replication Service Volumes // e.g, volume -> DFS Replication Service Volumes.
func dfsrGetPerfObjectName(collector string) string { func dfsrGetPerfObjectName(collector string) string {
prefix := "DFS " prefix := "DFS "
suffix := "" suffix := ""
@@ -113,7 +113,7 @@ func New(logger log.Logger, config *Config) *Collector {
func NewWithFlags(app *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{ return &Collector{
dfsrEnabledCollectors: app. dfsrEnabledCollectors: app.
Flag("collectors.dfsr.sources-enabled", "Comma-seperated list of DFSR Perflib sources to use."). Flag("collectors.dfsr.sources-enabled", "Comma-separated list of DFSR Perflib sources to use.").
Default(ConfigDefaults.EnabledCollectors). Default(ConfigDefaults.EnabledCollectors).
String(), String(),
} }
@@ -441,7 +441,7 @@ func (c *Collector) Build() error {
} }
// Maps enabled child collectors names to their relevant collection function, // Maps enabled child collectors names to their relevant collection function,
// for use in Collector.Collect() // for use in Collector.Collect().
func (c *Collector) getDFSRChildCollectors(enabledCollectors []string) []dfsrCollectorFunc { func (c *Collector) getDFSRChildCollectors(enabledCollectors []string) []dfsrCollectorFunc {
var dfsrCollectors []dfsrCollectorFunc var dfsrCollectors []dfsrCollectorFunc
for _, collector := range enabledCollectors { for _, collector := range enabledCollectors {
@@ -470,7 +470,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return nil return nil
} }
// PerflibDFSRConnection Perflib: "DFS Replication Service Connections" // PerflibDFSRConnection Perflib: "DFS Replication Service Connections".
type PerflibDFSRConnection struct { type PerflibDFSRConnection struct {
Name string Name string
@@ -558,7 +558,7 @@ func (c *Collector) collectConnection(ctx *types.ScrapeContext, ch chan<- promet
return nil return nil
} }
// perflibDFSRFolder Perflib: "DFS Replicated Folder" // perflibDFSRFolder Perflib: "DFS Replicated Folder".
type perflibDFSRFolder struct { type perflibDFSRFolder struct {
Name string Name string
@@ -790,7 +790,7 @@ func (c *Collector) collectFolder(ctx *types.ScrapeContext, ch chan<- prometheus
return nil return nil
} }
// perflibDFSRVolume Perflib: "DFS Replication Service Volumes" // perflibDFSRVolume Perflib: "DFS Replication Service Volumes".
type perflibDFSRVolume struct { type perflibDFSRVolume struct {
Name string Name string

View File

@@ -16,7 +16,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector perflib DHCP metrics // A Collector is a Prometheus Collector perflib DHCP metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -23,7 +23,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive // A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -177,10 +177,10 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.diskInfo, c.diskInfo,
prometheus.GaugeValue, prometheus.GaugeValue,
1.0, 1.0,
strings.Trim(disk.DeviceID, "\\.\\"), strings.Trim(disk.DeviceID, "\\.\\"), //nolint:staticcheck
strings.TrimRight(disk.Model, " "), strings.TrimRight(disk.Model, " "),
strings.TrimRight(disk.Caption, " "), strings.TrimRight(disk.Caption, " "),
strings.TrimRight(disk.Name, "\\.\\"), strings.TrimRight(disk.Name, "\\.\\"), //nolint:staticcheck
) )
for _, status := range allDiskStatus { for _, status := range allDiskStatus {
@@ -193,7 +193,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.status, c.status,
prometheus.GaugeValue, prometheus.GaugeValue,
isCurrentState, isCurrentState,
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
status, status,
) )
} }
@@ -202,14 +202,14 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.size, c.size,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(disk.Size), float64(disk.Size),
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.partitions, c.partitions,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(disk.Partitions), float64(disk.Partitions),
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
) )
for availNum, val := range availMap { for availNum, val := range availMap {
@@ -221,7 +221,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.availability, c.availability,
prometheus.GaugeValue, prometheus.GaugeValue,
isCurrentState, isCurrentState,
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
val, val,
) )
} }

View File

@@ -19,7 +19,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -75,7 +75,7 @@ type Collector struct {
enabledCollectors []string enabledCollectors []string
} }
// All available Collector functions // All available Collector functions.
var exchangeAllCollectorNames = []string{ var exchangeAllCollectorNames = []string{
"ADAccessProcesses", "ADAccessProcesses",
"TransportQueues", "TransportQueues",
@@ -189,7 +189,7 @@ func (c *Collector) Build() error {
c.yieldedTasks = desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name") c.yieldedTasks = desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name")
c.isActive = desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name") c.isActive = desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name")
c.activeSyncRequestsPerSec = desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load") c.activeSyncRequestsPerSec = desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load")
c.averageCASProcessingLatency = desc("http_proxy_avg_cas_proccessing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name") c.averageCASProcessingLatency = desc("http_proxy_avg_cas_processing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name")
c.mailboxServerProxyFailureRate = desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name") c.mailboxServerProxyFailureRate = desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name")
c.pingCommandsPending = desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue") c.pingCommandsPending = desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue")
c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder") c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder")
@@ -220,9 +220,7 @@ func (c *Collector) Build() error {
} }
if utils.IsEmpty(c.exchangeCollectorsEnabled) { if utils.IsEmpty(c.exchangeCollectorsEnabled) {
for _, collectorName := range exchangeAllCollectorNames { c.enabledCollectors = append(c.enabledCollectors, exchangeAllCollectorNames...)
c.enabledCollectors = append(c.enabledCollectors, collectorName)
}
} else { } else {
for _, collectorName := range strings.Split(*c.exchangeCollectorsEnabled, ",") { for _, collectorName := range strings.Split(*c.exchangeCollectorsEnabled, ",") {
if slices.Contains(exchangeAllCollectorNames, collectorName) { if slices.Contains(exchangeAllCollectorNames, collectorName) {
@@ -236,7 +234,7 @@ func (c *Collector) Build() error {
return nil return nil
} }
// Collect collects exchange metrics and sends them to prometheus // Collect collects exchange metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{
"ADAccessProcesses": c.collectADAccessProcesses, "ADAccessProcesses": c.collectADAccessProcesses,
@@ -260,7 +258,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return nil return nil
} }
// Perflib: [19108] MSExchange ADAccess Processes // Perflib: [19108] MSExchange ADAccess Processes.
type perflibADAccessProcesses struct { type perflibADAccessProcesses struct {
Name string Name string
@@ -324,7 +322,7 @@ func (c *Collector) collectADAccessProcesses(ctx *types.ScrapeContext, ch chan<-
return nil return nil
} }
// Perflib: [24914] MSExchange Availability Service // Perflib: [24914] MSExchange Availability Service.
type perflibAvailabilityService struct { type perflibAvailabilityService struct {
RequestsSec float64 `perflib:"Availability Requests (sec)"` RequestsSec float64 `perflib:"Availability Requests (sec)"`
} }
@@ -345,7 +343,7 @@ func (c *Collector) collectAvailabilityService(ctx *types.ScrapeContext, ch chan
return nil return nil
} }
// Perflib: [36934] MSExchange HttpProxy // Perflib: [36934] MSExchange HttpProxy.
type perflibHTTPProxy struct { type perflibHTTPProxy struct {
Name string Name string
@@ -405,7 +403,7 @@ func (c *Collector) collectHTTPProxy(ctx *types.ScrapeContext, ch chan<- prometh
return nil return nil
} }
// Perflib: [24618] MSExchange OWA // Perflib: [24618] MSExchange OWA.
type perflibOWA struct { type perflibOWA struct {
CurrentUniqueUsers float64 `perflib:"Current Unique Users"` CurrentUniqueUsers float64 `perflib:"Current Unique Users"`
RequestsPerSec float64 `perflib:"Requests/sec"` RequestsPerSec float64 `perflib:"Requests/sec"`
@@ -432,7 +430,7 @@ func (c *Collector) collectOWA(ctx *types.ScrapeContext, ch chan<- prometheus.Me
return nil return nil
} }
// Perflib: [25138] MSExchange ActiveSync // Perflib: [25138] MSExchange ActiveSync.
type perflibActiveSync struct { type perflibActiveSync struct {
RequestsPerSec float64 `perflib:"Requests/sec"` RequestsPerSec float64 `perflib:"Requests/sec"`
PingCommandsPending float64 `perflib:"Ping Commands Pending"` PingCommandsPending float64 `perflib:"Ping Commands Pending"`
@@ -465,7 +463,7 @@ func (c *Collector) collectActiveSync(ctx *types.ScrapeContext, ch chan<- promet
return nil return nil
} }
// Perflib: [29366] MSExchange RpcClientAccess // Perflib: [29366] MSExchange RpcClientAccess.
type perflibRPCClientAccess struct { type perflibRPCClientAccess struct {
RPCAveragedLatency float64 `perflib:"RPC Averaged Latency"` RPCAveragedLatency float64 `perflib:"RPC Averaged Latency"`
RPCRequests float64 `perflib:"RPC Requests"` RPCRequests float64 `perflib:"RPC Requests"`
@@ -517,7 +515,7 @@ func (c *Collector) collectRPC(ctx *types.ScrapeContext, ch chan<- prometheus.Me
return nil return nil
} }
// Perflib: [20524] MSExchangeTransport Queues // Perflib: [20524] MSExchangeTransport Queues.
type perflibTransportQueues struct { type perflibTransportQueues struct {
Name string Name string
@@ -594,7 +592,7 @@ func (c *Collector) collectTransportQueues(ctx *types.ScrapeContext, ch chan<- p
return nil return nil
} }
// Perflib: [19430] MSExchange WorkloadManagement Workloads // Perflib: [19430] MSExchange WorkloadManagement Workloads.
type perflibWorkloadManagementWorkloads struct { type perflibWorkloadManagementWorkloads struct {
Name string Name string
@@ -651,7 +649,7 @@ func (c *Collector) collectWorkloadManagementWorkloads(ctx *types.ScrapeContext,
return nil return nil
} }
// [29240] MSExchangeAutodiscover // [29240] MSExchangeAutodiscover.
type perflibAutodiscover struct { type perflibAutodiscover struct {
RequestsPerSec float64 `perflib:"Requests/sec"` RequestsPerSec float64 `perflib:"Requests/sec"`
} }
@@ -671,7 +669,7 @@ func (c *Collector) collectAutoDiscover(ctx *types.ScrapeContext, ch chan<- prom
return nil return nil
} }
// perflib [26463] MSExchange MapiHttp Emsmdb // perflib [26463] MSExchange MapiHttp Emsmdb.
type perflibMapiHttpEmsmdb struct { type perflibMapiHttpEmsmdb struct {
ActiveUserCount float64 `perflib:"Active User Count"` ActiveUserCount float64 `perflib:"Active User Count"`
} }
@@ -693,14 +691,14 @@ func (c *Collector) collectMapiHttpEmsmdb(ctx *types.ScrapeContext, ch chan<- pr
return nil return nil
} }
// toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores // toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores.
func (c *Collector) toLabelName(name string) string { func (c *Collector) toLabelName(name string) string {
s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_") s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_")
s = strings.ReplaceAll(s, "__", "_") s = strings.ReplaceAll(s, "__", "_")
return s return s
} }
// msToSec converts from ms to seconds // msToSec converts from ms to seconds.
func (c *Collector) msToSec(t float64) float64 { func (c *Collector) msToSec(t float64) float64 {
return t / 1000 return t / 1000
} }

View File

@@ -55,7 +55,7 @@ func (c *Collectors) BuildServeHTTP(disableExporterMetrics bool, timeoutMargin f
if timeoutSeconds == 0 { if timeoutSeconds == 0 {
timeoutSeconds = defaultTimeout timeoutSeconds = defaultTimeout
} }
timeoutSeconds = timeoutSeconds - timeoutMargin timeoutSeconds -= timeoutMargin
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
err, wc := collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"]) err, wc := collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"])

View File

@@ -20,7 +20,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// Collector is a Prometheus Collector for hyper-v // Collector is a Prometheus Collector for hyper-v.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -810,7 +810,7 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
return nil return nil
} }
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary vm health status // Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary vm health status.
type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary struct { type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary struct {
HealthCritical uint32 HealthCritical uint32
HealthOk uint32 HealthOk uint32
@@ -840,7 +840,7 @@ func (c *Collector) collectVmHealth(ch chan<- prometheus.Metric) error {
return nil return nil
} }
// Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition .., // Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition ..,.
type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct { type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct {
Name string Name string
PhysicalPagesAllocated uint64 PhysicalPagesAllocated uint64

View File

@@ -987,22 +987,22 @@ type perflibWebService struct {
TotalUnlockRequests float64 `perflib:"Total Unlock Requests"` TotalUnlockRequests float64 `perflib:"Total Unlock Requests"`
} }
// Fulfill the hasGetIISName interface // Fulfill the hasGetIISName interface.
func (p perflibWebService) getIISName() string { func (p perflibWebService) getIISName() string {
return p.Name return p.Name
} }
// Fulfill the hasGetIISName interface // Fulfill the hasGetIISName interface.
func (p perflibAPP_POOL_WAS) getIISName() string { func (p perflibAPP_POOL_WAS) getIISName() string {
return p.Name return p.Name
} }
// Fulfill the hasGetIISName interface // Fulfill the hasGetIISName interface.
func (p perflibW3SVC_W3WP) getIISName() string { func (p perflibW3SVC_W3WP) getIISName() string {
return p.Name return p.Name
} }
// Fulfill the hasGetIISName interface // Fulfill the hasGetIISName interface.
func (p perflibW3SVC_W3WP_IIS8) getIISName() string { func (p perflibW3SVC_W3WP_IIS8) getIISName() string {
return p.Name return p.Name
} }
@@ -1017,7 +1017,7 @@ type hasGetIISName interface {
// E.G. Given the following list of site names, "Site_B" would be // E.G. Given the following list of site names, "Site_B" would be
// discarded, and "Site_B#2" would be kept and presented as "Site_B" in the // discarded, and "Site_B#2" would be kept and presented as "Site_B" in the
// Collector metrics. // Collector metrics.
// [ "Site_A", "Site_B", "Site_C", "Site_B#2" ] // [ "Site_A", "Site_B", "Site_C", "Site_B#2" ].
func dedupIISNames[V hasGetIISName](services []V) map[string]V { func dedupIISNames[V hasGetIISName](services []V) map[string]V {
// Ensure IIS entry with the highest suffix occurs last // Ensure IIS entry with the highest suffix occurs last
sort.SliceStable(services, func(i, j int) bool { sort.SliceStable(services, func(i, j int) bool {
@@ -1457,13 +1457,13 @@ type perflibW3SVC_W3WP struct {
URICacheFlushesTotal float64 `perflib:"Total Flushed URIs"` URICacheFlushesTotal float64 `perflib:"Total Flushed URIs"`
URICacheFlushesTotalKernel float64 `perflib:"Total Flushed URIs"` URICacheFlushesTotalKernel float64 `perflib:"Total Flushed URIs"`
URIsFlushedTotalKernel float64 `perflib:"Kernel\: Total Flushed URIs"` //nolint:govet URIsFlushedTotalKernel float64 `perflib:"Kernel\: Total Flushed URIs"` //nolint:govet,tagalign,staticcheck
URICacheHitsTotal float64 `perflib:"URI Cache Hits"` URICacheHitsTotal float64 `perflib:"URI Cache Hits"`
URICacheHitsTotalKernel float64 `perflib:"Kernel\: URI Cache Hits"` //nolint:govet URICacheHitsTotalKernel float64 `perflib:"Kernel\: URI Cache Hits"` //nolint:govet,tagalign,staticcheck
URICacheMissesTotal float64 `perflib:"URI Cache Misses"` URICacheMissesTotal float64 `perflib:"URI Cache Misses"`
URICacheMissesTotalKernel float64 `perflib:"Kernel\: URI Cache Misses"` //nolint:govet URICacheMissesTotalKernel float64 `perflib:"Kernel\: URI Cache Misses"` //nolint:govet,tagalign,staticcheck
URIsCached float64 `perflib:"Current URIs Cached"` URIsCached float64 `perflib:"Current URIs Cached"`
URIsCachedKernel float64 `perflib:"Kernel\: Current URIs Cached"` //nolint:govet URIsCachedKernel float64 `perflib:"Kernel\: Current URIs Cached"` //nolint:govet,tagalign,staticcheck
URIsCachedTotal float64 `perflib:"Total URIs Cached"` URIsCachedTotal float64 `perflib:"Total URIs Cached"`
URIsCachedTotalKernel float64 `perflib:"Total URIs Cached"` URIsCachedTotalKernel float64 `perflib:"Total URIs Cached"`
URIsFlushedTotal float64 `perflib:"Total Flushed URIs"` URIsFlushedTotal float64 `perflib:"Total Flushed URIs"`

View File

@@ -6,6 +6,8 @@ import (
) )
func TestIISDeduplication(t *testing.T) { func TestIISDeduplication(t *testing.T) {
t.Parallel()
start := []perflibAPP_POOL_WAS{ start := []perflibAPP_POOL_WAS{
{ {
Name: "foo", Name: "foo",

View File

@@ -25,7 +25,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -31,7 +31,7 @@ var ConfigDefaults = Config{
VolumeExclude: "", VolumeExclude: "",
} }
// A Collector is a Prometheus Collector for perflib logicalDisk metrics // A Collector is a Prometheus Collector for perflib logicalDisk metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -264,7 +264,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
// Win32_PerfRawData_PerfDisk_LogicalDisk docs: // Win32_PerfRawData_PerfDisk_LogicalDisk docs:
// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class // - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class
// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference // - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference.
type logicalDisk struct { type logicalDisk struct {
Name string Name string
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`
@@ -478,7 +478,6 @@ func getDiskIDByVolume(rootDrive string) (string, error) {
f, err = windows.CreateFile( f, err = windows.CreateFile(
windows.StringToUTF16Ptr(`\\.\`+rootDrive), windows.StringToUTF16Ptr(`\\.\`+rootDrive),
0, mode, nil, windows.OPEN_EXISTING, uint32(windows.FILE_ATTRIBUTE_READONLY), 0) 0, mode, nil, windows.OPEN_EXISTING, uint32(windows.FILE_ATTRIBUTE_READONLY), 0)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -527,7 +526,6 @@ func getVolumeInfo(rootDrive string) (volumeInfo, error) {
err := windows.GetVolumeInformation(volPath, &volBufLabel[0], uint32(len(volBufLabel)), err := windows.GetVolumeInformation(volPath, &volBufLabel[0], uint32(len(volBufLabel)),
&volSerialNum, nil, &fsFlags, &volBufType[0], uint32(len(volBufType))) &volSerialNum, nil, &fsFlags, &volBufType[0], uint32(len(volBufType)))
if err != nil { if err != nil {
if driveType != windows.DRIVE_CDROM && driveType != windows.DRIVE_REMOVABLE { if driveType != windows.DRIVE_CDROM && driveType != windows.DRIVE_REMOVABLE {
return volumeInfo{}, err return volumeInfo{}, err

View File

@@ -19,7 +19,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -20,7 +20,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for perflib Memory metrics // A Collector is a Prometheus Collector for perflib Memory metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -14,7 +14,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics // A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -14,7 +14,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_Network metrics // A Collector is a Prometheus Collector for WMI MSCluster_Network metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -14,10 +14,10 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// Variable used by mscluster_resource and mscluster_resourcegroup // Variable used by mscluster_resource and mscluster_resourcegroup.
var NodeName []string var NodeName []string
// A Collector is a Prometheus Collector for WMI MSCluster_Node metrics // A Collector is a Prometheus Collector for WMI MSCluster_Node metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -15,7 +15,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_Resource metrics // A Collector is a Prometheus Collector for WMI MSCluster_Resource metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -15,7 +15,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI MSCluster_ResourceGroup metrics // A Collector is a Prometheus Collector for WMI MSCluster_ResourceGroup metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -24,7 +24,7 @@ var ConfigDefaults = Config{
QueryWhereClause: "", QueryWhereClause: "",
} }
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -23,7 +23,7 @@ import (
const Name = "mssql" const Name = "mssql"
type Config struct { type Config struct {
EnabledCollectors string `yaml:"collectors_enabled"` EnabledCollectors string `yaml:"collectors_enabled"` //nolint:tagliatelle
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
@@ -126,7 +126,7 @@ func mssqlGetPerfObjectName(sqlInstance string, collector string) string {
return prefix + suffix return prefix + suffix
} }
// A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics // A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -28,7 +28,7 @@ var ConfigDefaults = Config{
var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
// A Collector is a Prometheus Collector for Perflib Network Interface metrics // A Collector is a Prometheus Collector for Perflib Network Interface metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -7,6 +7,8 @@ import (
) )
func TestNetworkToInstanceName(t *testing.T) { func TestNetworkToInstanceName(t *testing.T) {
t.Parallel()
data := map[string]string{ data := map[string]string{
"Intel[R] Dual Band Wireless-AC 8260": "Intel_R__Dual_Band_Wireless_AC_8260", "Intel[R] Dual Band Wireless-AC 8260": "Intel_R__Dual_Band_Wireless_AC_8260",
} }

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics // Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -246,7 +246,7 @@ func (c *Collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric)
} }
// Win32_PerfRawData_IAS_NPSAuthenticationServer docs: // Win32_PerfRawData_IAS_NPSAuthenticationServer docs:
// at the moment there is no Microsoft documentation // at the moment there is no Microsoft documentation.
type Win32_PerfRawData_IAS_NPSAuthenticationServer struct { type Win32_PerfRawData_IAS_NPSAuthenticationServer struct {
Name string Name string

View File

@@ -30,7 +30,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -175,7 +175,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
} }
// Win32_OperatingSystem docs: // Win32_OperatingSystem docs:
// - https://msdn.microsoft.com/en-us/library/aa394239 - Win32_OperatingSystem class // - https://msdn.microsoft.com/en-us/library/aa394239 - Win32_OperatingSystem class.
type Win32_OperatingSystem struct { type Win32_OperatingSystem struct {
Caption string Caption string
FreePhysicalMemory uint64 FreePhysicalMemory uint64
@@ -215,11 +215,12 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
// Get total allocation of paging files across all disks. // Get total allocation of paging files across all disks.
memManKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management`, registry.QUERY_VALUE) memManKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management`, registry.QUERY_VALUE)
defer memManKey.Close()
if err != nil { if err != nil {
return err return err
} }
defer memManKey.Close()
pagingFiles, _, pagingErr := memManKey.GetStringsValue("ExistingPageFiles") pagingFiles, _, pagingErr := memManKey.GetStringsValue("ExistingPageFiles")
var fsipf float64 var fsipf float64
@@ -236,12 +237,12 @@ func (c *Collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
// Get build number and product name from registry // Get build number and product name from registry
ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
defer ntKey.Close()
if err != nil { if err != nil {
return err return err
} }
defer ntKey.Close()
pn, _, err := ntKey.GetStringValue("ProductName") pn, _, err := ntKey.GetStringValue("ProductName")
if err != nil { if err != nil {
return err return err

View File

@@ -27,7 +27,7 @@ var ConfigDefaults = Config{
DiskExclude: "", DiskExclude: "",
} }
// A Collector is a Prometheus Collector for perflib PhysicalDisk metrics // A Collector is a Prometheus Collector for perflib PhysicalDisk metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -217,7 +217,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
// PhysicalDisk // PhysicalDisk
// Win32_PerfRawData_PerfDisk_PhysicalDisk docs: // Win32_PerfRawData_PerfDisk_PhysicalDisk docs:
// - https://docs.microsoft.com/en-us/previous-versions/aa394308(v=vs.85) - Win32_PerfRawData_PerfDisk_PhysicalDisk class // - https://docs.microsoft.com/en-us/previous-versions/aa394308(v=vs.85) - Win32_PerfRawData_PerfDisk_PhysicalDisk class.
type PhysicalDisk struct { type PhysicalDisk struct {
Name string Name string
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`

View File

@@ -26,7 +26,7 @@ const Name = "process"
type Config struct { type Config struct {
ProcessInclude string `yaml:"process_include"` ProcessInclude string `yaml:"process_include"`
ProcessExclude string `yaml:"process_exclude"` ProcessExclude string `yaml:"process_exclude"`
EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle
EnableReportOwner bool `yaml:"enable_report_owner"` EnableReportOwner bool `yaml:"enable_report_owner"`
} }
@@ -488,7 +488,7 @@ func (c *Collector) getProcessOwner(pid int) (string, error) {
} }
if err != nil { if err != nil {
return "", fmt.Errorf("OpenProcess: %T %w", err, err) return "", fmt.Errorf("OpenProcess: %w", err)
} }
defer windows.Close(p) defer windows.Close(p)

View File

@@ -87,7 +87,7 @@ func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) {
time.Since(t).Seconds(), time.Since(t).Seconds(),
) )
if err != nil { if err != nil {
ch <- prometheus.NewInvalidMetric(coll.scrapeSuccessDesc, fmt.Errorf("failed to prepare scrape: %v", err)) ch <- prometheus.NewInvalidMetric(coll.scrapeSuccessDesc, fmt.Errorf("failed to prepare scrape: %w", err))
return return
} }

View File

@@ -423,7 +423,7 @@ func (c *Collector) collectRemoteFXGraphicsCounters(ctx *types.ScrapeContext, ch
return nil return nil
} }
// normalizeSessionName ensure that the session is the same between WTS API and performance counters // normalizeSessionName ensure that the session is the same between WTS API and performance counters.
func normalizeSessionName(sessionName string) string { func normalizeSessionName(sessionName string) string {
return strings.Replace(sessionName, "RDP-tcp", "RDP-Tcp", 1) return strings.Replace(sessionName, "RDP-tcp", "RDP-Tcp", 1)
} }

View File

@@ -225,7 +225,9 @@ const SCHEDULED_TASK_PROGRAM_ID = "Schedule.Service.1"
// S_FALSE is returned by CoInitialize if it was already called on this thread. // S_FALSE is returned by CoInitialize if it was already called on this thread.
const S_FALSE = 0x00000001 const S_FALSE = 0x00000001
func getScheduledTasks() (scheduledTasks ScheduledTasks, err error) { func getScheduledTasks() (ScheduledTasks, error) {
var scheduledTasks ScheduledTasks
// The only way to run WMI queries in parallel while being thread-safe is to // The only way to run WMI queries in parallel while being thread-safe is to
// ensure the CoInitialize[Ex]() call is bound to its current OS thread. // ensure the CoInitialize[Ex]() call is bound to its current OS thread.
// Otherwise, attempting to initialize and run parallel queries across // Otherwise, attempting to initialize and run parallel queries across
@@ -320,7 +322,9 @@ func fetchTasksRecursively(folder *ole.IDispatch, scheduledTasks *ScheduledTasks
return err return err
} }
func parseTask(task *ole.IDispatch) (scheduledTask ScheduledTask, err error) { func parseTask(task *ole.IDispatch) (ScheduledTask, error) {
var scheduledTask ScheduledTask
taskNameVar, err := oleutil.GetProperty(task, "Name") taskNameVar, err := oleutil.GetProperty(task, "Name")
if err != nil { if err != nil {
return scheduledTask, err return scheduledTask, err

View File

@@ -35,7 +35,7 @@ var ConfigDefaults = Config{
V2: false, V2: false,
} }
// A Collector is a Prometheus Collector for WMI Win32_Service metrics // A Collector is a Prometheus Collector for WMI Win32_Service metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -38,7 +38,7 @@ type Collector struct {
enabledCollectors []string enabledCollectors []string
} }
// All available Collector functions // All available Collector functions.
var smbAllCollectorNames = []string{ var smbAllCollectorNames = []string{
"ServerShares", "ServerShares",
} }
@@ -121,9 +121,7 @@ func (c *Collector) Build() error {
} }
if *c.smbCollectorsEnabled == "" { if *c.smbCollectorsEnabled == "" {
for _, collectorName := range smbAllCollectorNames { c.enabledCollectors = append(c.enabledCollectors, smbAllCollectorNames...)
c.enabledCollectors = append(c.enabledCollectors, collectorName)
}
} else { } else {
for _, collectorName := range strings.Split(*c.smbCollectorsEnabled, ",") { for _, collectorName := range strings.Split(*c.smbCollectorsEnabled, ",") {
if slices.Contains(smbAllCollectorNames, collectorName) { if slices.Contains(smbAllCollectorNames, collectorName) {
@@ -137,7 +135,7 @@ func (c *Collector) Build() error {
return nil return nil
} }
// Collect collects smb metrics and sends them to prometheus // Collect collects smb metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{
"ServerShares": c.collectServerShares, "ServerShares": c.collectServerShares,
@@ -152,7 +150,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return nil return nil
} }
// Perflib: SMB Server Shares // Perflib: SMB Server Shares.
type perflibServerShares struct { type perflibServerShares struct {
Name string Name string
@@ -186,7 +184,7 @@ func (c *Collector) collectServerShares(ctx *types.ScrapeContext, ch chan<- prom
return nil return nil
} }
// toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores // toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores.
func (c *Collector) toLabelName(name string) string { func (c *Collector) toLabelName(name string) string {
s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_") s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_")
s = strings.ReplaceAll(s, "__", "_") s = strings.ReplaceAll(s, "__", "_")

View File

@@ -60,7 +60,7 @@ type Collector struct {
requestSecs *prometheus.Desc requestSecs *prometheus.Desc
} }
// All available collector functions // All available collector functions.
var smbclientAllCollectorNames = []string{ var smbclientAllCollectorNames = []string{
"ClientShares", "ClientShares",
} }
@@ -224,9 +224,7 @@ func (c *Collector) Build() error {
} }
if *c.smbClientCollectorsEnabled == "" { if *c.smbClientCollectorsEnabled == "" {
for _, collectorName := range smbclientAllCollectorNames { c.enabledCollectors = append(c.enabledCollectors, smbclientAllCollectorNames...)
c.enabledCollectors = append(c.enabledCollectors, collectorName)
}
} else { } else {
for _, collectorName := range strings.Split(*c.smbClientCollectorsEnabled, ",") { for _, collectorName := range strings.Split(*c.smbClientCollectorsEnabled, ",") {
if slices.Contains(smbclientAllCollectorNames, collectorName) { if slices.Contains(smbclientAllCollectorNames, collectorName) {
@@ -240,7 +238,7 @@ func (c *Collector) Build() error {
return nil return nil
} }
// Collect collects smb client metrics and sends them to prometheus // Collect collects smb client metrics and sends them to prometheus.
func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{
"ClientShares": c.collectClientShares, "ClientShares": c.collectClientShares,
@@ -255,7 +253,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return nil return nil
} }
// Perflib: SMB Client Shares // Perflib: SMB Client Shares.
type perflibClientShares struct { type perflibClientShares struct {
Name string Name string

View File

@@ -405,7 +405,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return nil return nil
} }
// PerflibSMTPServer Perflib: "SMTP Server" // PerflibSMTPServer Perflib: "SMTP Server".
type PerflibSMTPServer struct { type PerflibSMTPServer struct {
Name string Name string

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics // A Collector is a Prometheus Collector for WMI metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -17,7 +17,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -24,7 +24,7 @@ var ConfigDefaults = Config{}
// win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -102,7 +102,6 @@ func (c *Collector) GetPerfCounter() ([]string, error) {
func (c *Collector) Close() error { func (c *Collector) Close() error {
err := wtsapi32.WTSCloseServer(c.hServer) err := wtsapi32.WTSCloseServer(c.hServer)
if err != nil { if err != nil {
return fmt.Errorf("failed to close WTS server: %w", err) return fmt.Errorf("failed to close WTS server: %w", err)
} }
@@ -434,7 +433,7 @@ func (c *Collector) collectWTSSessions(ch chan<- prometheus.Metric) error {
c.sessionInfo, c.sessionInfo,
prometheus.GaugeValue, prometheus.GaugeValue,
isState, isState,
strings.Replace(session.SessionName, "#", " ", -1), strings.ReplaceAll(session.SessionName, "#", " "),
userName, userName,
session.HostName, session.HostName,
stateName, stateName,

View File

@@ -120,21 +120,21 @@ func (c *Collector) Build() error {
func duplicateMetricEntry(metricFamilies []*dto.MetricFamily) bool { func duplicateMetricEntry(metricFamilies []*dto.MetricFamily) bool {
uniqueMetrics := make(map[string]map[string]string) uniqueMetrics := make(map[string]map[string]string)
for _, metricFamily := range metricFamilies { for _, metricFamily := range metricFamilies {
metric_name := *metricFamily.Name metricName := metricFamily.GetName()
for _, metric := range metricFamily.Metric { for _, metric := range metricFamily.GetMetric() {
metric_labels := metric.GetLabel() metricLabels := metric.GetLabel()
labels := make(map[string]string) labels := make(map[string]string)
for _, label := range metric_labels { for _, label := range metricLabels {
labels[label.GetName()] = label.GetValue() labels[label.GetName()] = label.GetValue()
} }
// Check if key is present before appending // Check if key is present before appending
_, mapContainsKey := uniqueMetrics[metric_name] _, mapContainsKey := uniqueMetrics[metricName]
// Duplicate metric found with identical labels & label values // Duplicate metric found with identical labels & label values
if mapContainsKey == true && reflect.DeepEqual(uniqueMetrics[metric_name], labels) { if mapContainsKey && reflect.DeepEqual(uniqueMetrics[metricName], labels) {
return true return true
} }
uniqueMetrics[metric_name] = labels uniqueMetrics[metricName] = labels
} }
} }
return false return false
@@ -145,7 +145,7 @@ func (c *Collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<
var val float64 var val float64
allLabelNames := map[string]struct{}{} allLabelNames := map[string]struct{}{}
for _, metric := range metricFamily.Metric { for _, metric := range metricFamily.GetMetric() {
labels := metric.GetLabel() labels := metric.GetLabel()
for _, label := range labels { for _, label := range labels {
if _, ok := allLabelNames[label.GetName()]; !ok { if _, ok := allLabelNames[label.GetName()]; !ok {
@@ -154,7 +154,7 @@ func (c *Collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<
} }
} }
for _, metric := range metricFamily.Metric { for _, metric := range metricFamily.GetMetric() {
if metric.TimestampMs != nil { if metric.TimestampMs != nil {
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Ignoring unsupported custom timestamp on textfile Collector metric %v", metric)) _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Ignoring unsupported custom timestamp on textfile Collector metric %v", metric))
} }
@@ -175,7 +175,7 @@ func (c *Collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<
break break
} }
} }
if present == false { if !present {
names = append(names, k) names = append(names, k)
values = append(values, "") values = append(values, "")
} }
@@ -185,44 +185,44 @@ func (c *Collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<
switch metricType { switch metricType {
case dto.MetricType_COUNTER: case dto.MetricType_COUNTER:
valType = prometheus.CounterValue valType = prometheus.CounterValue
val = metric.Counter.GetValue() val = metric.GetCounter().GetValue()
case dto.MetricType_GAUGE: case dto.MetricType_GAUGE:
valType = prometheus.GaugeValue valType = prometheus.GaugeValue
val = metric.Gauge.GetValue() val = metric.GetGauge().GetValue()
case dto.MetricType_UNTYPED: case dto.MetricType_UNTYPED:
valType = prometheus.UntypedValue valType = prometheus.UntypedValue
val = metric.Untyped.GetValue() val = metric.GetUntyped().GetValue()
case dto.MetricType_SUMMARY: case dto.MetricType_SUMMARY:
quantiles := map[float64]float64{} quantiles := map[float64]float64{}
for _, q := range metric.Summary.Quantile { for _, q := range metric.GetSummary().GetQuantile() {
quantiles[q.GetQuantile()] = q.GetValue() quantiles[q.GetQuantile()] = q.GetValue()
} }
ch <- prometheus.MustNewConstSummary( ch <- prometheus.MustNewConstSummary(
prometheus.NewDesc( prometheus.NewDesc(
*metricFamily.Name, metricFamily.GetName(),
metricFamily.GetHelp(), metricFamily.GetHelp(),
names, nil, names, nil,
), ),
metric.Summary.GetSampleCount(), metric.GetSummary().GetSampleCount(),
metric.Summary.GetSampleSum(), metric.GetSummary().GetSampleSum(),
quantiles, values..., quantiles, values...,
) )
case dto.MetricType_HISTOGRAM: case dto.MetricType_HISTOGRAM:
buckets := map[float64]uint64{} buckets := map[float64]uint64{}
for _, b := range metric.Histogram.Bucket { for _, b := range metric.GetHistogram().GetBucket() {
buckets[b.GetUpperBound()] = b.GetCumulativeCount() buckets[b.GetUpperBound()] = b.GetCumulativeCount()
} }
ch <- prometheus.MustNewConstHistogram( ch <- prometheus.MustNewConstHistogram(
prometheus.NewDesc( prometheus.NewDesc(
*metricFamily.Name, metricFamily.GetName(),
metricFamily.GetHelp(), metricFamily.GetHelp(),
names, nil, names, nil,
), ),
metric.Histogram.GetSampleCount(), metric.GetHistogram().GetSampleCount(),
metric.Histogram.GetSampleSum(), metric.GetHistogram().GetSampleSum(),
buckets, values..., buckets, values...,
) )
default: default:
@@ -232,7 +232,7 @@ func (c *Collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<
if metricType == dto.MetricType_GAUGE || metricType == dto.MetricType_COUNTER || metricType == dto.MetricType_UNTYPED { if metricType == dto.MetricType_GAUGE || metricType == dto.MetricType_COUNTER || metricType == dto.MetricType_UNTYPED {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc( prometheus.NewDesc(
*metricFamily.Name, metricFamily.GetName(),
metricFamily.GetHelp(), metricFamily.GetHelp(),
names, nil, names, nil,
), ),
@@ -266,7 +266,7 @@ type carriageReturnFilteringReader struct {
r io.Reader r io.Reader
} }
// Read returns data from the underlying io.Reader, but with \r filtered out // Read returns data from the underlying io.Reader, but with \r filtered out.
func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) { func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) {
buf := make([]byte, len(p)) buf := make([]byte, len(p))
n, err := cr.r.Read(buf) n, err := cr.r.Read(buf)
@@ -276,7 +276,7 @@ func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) {
} }
pi := 0 pi := 0
for i := 0; i < n; i++ { for i := range n {
if buf[i] != '\r' { if buf[i] != '\r' {
p[pi] = buf[i] p[pi] = buf[i]
pi++ pi++
@@ -380,7 +380,7 @@ func scrapeFile(path string, log log.Logger) ([]*dto.MetricFamily, error) {
for _, mf := range parsedFamilies { for _, mf := range parsedFamilies {
families_array = append(families_array, mf) families_array = append(families_array, mf)
for _, m := range mf.Metric { for _, m := range mf.GetMetric() {
if m.TimestampMs != nil { if m.TimestampMs != nil {
return nil, errors.New("textfile contains unsupported client-side timestamps") return nil, errors.New("textfile contains unsupported client-side timestamps")
} }

View File

@@ -10,6 +10,8 @@ import (
) )
func TestCRFilter(t *testing.T) { func TestCRFilter(t *testing.T) {
t.Parallel()
sr := strings.NewReader("line 1\r\nline 2") sr := strings.NewReader("line 1\r\nline 2")
cr := carriageReturnFilteringReader{r: sr} cr := carriageReturnFilteringReader{r: sr}
b, err := io.ReadAll(cr) b, err := io.ReadAll(cr)
@@ -23,6 +25,8 @@ func TestCRFilter(t *testing.T) {
} }
func TestCheckBOM(t *testing.T) { func TestCheckBOM(t *testing.T) {
t.Parallel()
testdata := []struct { testdata := []struct {
encoding utfbom.Encoding encoding utfbom.Encoding
err string err string
@@ -49,6 +53,8 @@ func TestCheckBOM(t *testing.T) {
} }
func TestDuplicateMetricEntry(t *testing.T) { func TestDuplicateMetricEntry(t *testing.T) {
t.Parallel()
metric_name := "windows_sometest" metric_name := "windows_sometest"
metric_help := "This is a Test." metric_help := "This is a Test."
metric_type := dto.MetricType_GAUGE metric_type := dto.MetricType_GAUGE

View File

@@ -17,6 +17,8 @@ import (
var baseDir = "../../../tools/textfile-test" var baseDir = "../../../tools/textfile-test"
func TestMultipleDirectories(t *testing.T) { func TestMultipleDirectories(t *testing.T) {
t.Parallel()
testDir := baseDir + "/multiple-dirs" testDir := baseDir + "/multiple-dirs"
testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir) testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir)
@@ -58,6 +60,8 @@ func TestMultipleDirectories(t *testing.T) {
} }
func TestDuplicateFileName(t *testing.T) { func TestDuplicateFileName(t *testing.T) {
t.Parallel()
testDir := baseDir + "/duplicate-filename" testDir := baseDir + "/duplicate-filename"
textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{
TextFileDirectories: testDir, TextFileDirectories: testDir,

View File

@@ -19,7 +19,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -20,7 +20,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// Collector is a Prometheus Collector for Perflib counter metrics // Collector is a Prometheus Collector for Perflib counter metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger
@@ -113,7 +113,7 @@ func (c *Collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
return nil return nil
} }
// Perflib "Windows Time Service" // Perflib "Windows Time Service".
type windowsTime struct { type windowsTime struct {
ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"` ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"`
ComputedTimeOffset float64 `perflib:"Computed Time Offset"` ComputedTimeOffset float64 `perflib:"Computed Time Offset"`

View File

@@ -16,8 +16,10 @@ type Collectors struct {
type Map map[string]Collector type Map map[string]Collector
type Builder func(logger log.Logger) Collector type (
type BuilderWithFlags[C Collector] func(*kingpin.Application) C Builder func(logger log.Logger) Collector
BuilderWithFlags[C Collector] func(*kingpin.Application) C
)
// Collector interface that a collector has to implement. // Collector interface that a collector has to implement.
type Collector interface { type Collector interface {

View File

@@ -20,7 +20,7 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics.
type Collector struct { type Collector struct {
logger log.Logger logger log.Logger

View File

@@ -42,39 +42,24 @@ func NewResolver(file string, logger log.Logger, insecureSkipVerify bool) (*Reso
var fileBytes []byte var fileBytes []byte
var err error var err error
if strings.HasPrefix(file, "http://") || strings.HasPrefix(file, "https://") { if strings.HasPrefix(file, "http://") || strings.HasPrefix(file, "https://") {
_ = level.Info(logger).Log("msg", fmt.Sprintf("Loading configuration file from URL: %v", file)) fileBytes, err = readFromURL(file, logger, insecureSkipVerify)
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify}, //nolint:gosec
}
if insecureSkipVerify {
_ = level.Warn(logger).Log("msg", "Loading configuration file with TLS verification disabled")
}
client := &http.Client{Transport: tr}
resp, err := client.Get(file)
if err != nil {
return nil, err
}
defer resp.Body.Close()
fileBytes, err = io.ReadAll(resp.Body)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
_ = level.Info(logger).Log("msg", fmt.Sprintf("Loading configuration file: %v", file)) fileBytes, err = readFromFile(file, logger)
if _, err := os.Stat(file); err != nil {
return nil, err
}
fileBytes, err = os.ReadFile(file)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
var rawValues map[string]interface{} var rawValues map[string]interface{}
err = yaml.Unmarshal(fileBytes, &rawValues) err = yaml.Unmarshal(fileBytes, &rawValues)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Flatten nested YAML values // Flatten nested YAML values
flattenedValues := flatten(rawValues) flattenedValues := flatten(rawValues)
for k, v := range flattenedValues { for k, v := range flattenedValues {
@@ -82,9 +67,51 @@ func NewResolver(file string, logger log.Logger, insecureSkipVerify bool) (*Reso
flags[k] = v flags[k] = v
} }
} }
return &Resolver{flags: flags}, nil return &Resolver{flags: flags}, nil
} }
func readFromFile(file string, logger log.Logger) ([]byte, error) {
_ = level.Info(logger).Log("msg", fmt.Sprintf("Loading configuration file: %v", file))
if _, err := os.Stat(file); err != nil {
return nil, err
}
fileBytes, err := os.ReadFile(file)
if err != nil {
return nil, err
}
return fileBytes, err
}
func readFromURL(file string, logger log.Logger, insecureSkipVerify bool) ([]byte, error) {
_ = level.Info(logger).Log("msg", fmt.Sprintf("Loading configuration file from URL: %v", file))
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify}, //nolint:gosec
}
if insecureSkipVerify {
_ = level.Warn(logger).Log("msg", "Loading configuration file with TLS verification disabled")
}
client := &http.Client{Transport: tr}
resp, err := client.Get(file)
if err != nil {
return nil, err
}
defer resp.Body.Close()
fileBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return fileBytes, nil
}
func (c *Resolver) setDefault(v getFlagger) { func (c *Resolver) setDefault(v getFlagger) {
for name, value := range c.flags { for name, value := range c.flags {
f := v.GetFlag(name) f := v.GetFlag(name)

View File

@@ -9,7 +9,7 @@ import (
// //
// All keys will be joined by dot // All keys will be joined by dot
// e.g. {"a": {"b":"c"}} => {"a.b":"c"} // e.g. {"a": {"b":"c"}} => {"a.b":"c"}
// or {"a": {"b":[1,2]}} => {"a.b.0":1, "a.b.1": 2} // or {"a": {"b":[1,2]}} => {"a.b.0":1, "a.b.1": 2}.
func flatten(data map[string]interface{}) map[string]string { func flatten(data map[string]interface{}) map[string]string {
ret := make(map[string]string) ret := make(map[string]string)
for k, v := range data { for k, v := range data {
@@ -32,6 +32,7 @@ func flatten(data map[string]interface{}) map[string]string {
} }
return ret return ret
} }
func flattenSlice(data []interface{}) map[string]string { func flattenSlice(data []interface{}) map[string]string {
ret := make(map[string]string) ret := make(map[string]string)
for idx, v := range data { for idx, v := range data {

View File

@@ -7,8 +7,10 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
// Unmarshal good configuration file and confirm data is flattened correctly // Unmarshal good configuration file and confirm data is flattened correctly.
func TestConfigFlattening(t *testing.T) { func TestConfigFlattening(t *testing.T) {
t.Parallel()
goodYamlConfig := []byte(`--- goodYamlConfig := []byte(`---
collectors: collectors:

View File

@@ -19,7 +19,7 @@ type wKSTAInfo102 struct {
wki102_logged_on_users uint32 wki102_logged_on_users uint32
} }
// WorkstationInfo is an idiomatic wrapper of WKSTAInfo102 // WorkstationInfo is an idiomatic wrapper of WKSTAInfo102.
type WorkstationInfo struct { type WorkstationInfo struct {
PlatformId uint32 PlatformId uint32
ComputerName string ComputerName string
@@ -89,7 +89,7 @@ func netWkstaGetInfo() (wKSTAInfo102, uint32, error) {
return deref, 0, nil return deref, 0, nil
} }
// GetWorkstationInfo is an idiomatic wrapper for netWkstaGetInfo // GetWorkstationInfo is an idiomatic wrapper for netWkstaGetInfo.
func GetWorkstationInfo() (WorkstationInfo, error) { func GetWorkstationInfo() (WorkstationInfo, error) {
info, _, err := netWkstaGetInfo() info, _, err := netWkstaGetInfo()
if err != nil { if err != nil {

View File

@@ -24,7 +24,7 @@ const (
SL_GEN_STATE_LAST SL_GEN_STATE_LAST
) )
// SLIsWindowsGenuineLocal function wrapper // SLIsWindowsGenuineLocal function wrapper.
func SLIsWindowsGenuineLocal() (SL_GENUINE_STATE, error) { func SLIsWindowsGenuineLocal() (SL_GENUINE_STATE, error) {
var genuineState SL_GENUINE_STATE var genuineState SL_GENUINE_STATE

View File

@@ -21,7 +21,7 @@ type memoryStatusEx struct {
UllAvailExtendedVirtual uint64 UllAvailExtendedVirtual uint64
} }
// MemoryStatus is an idiomatic wrapper for MemoryStatusEx // MemoryStatus is an idiomatic wrapper for MemoryStatusEx.
type MemoryStatus struct { type MemoryStatus struct {
MemoryLoad uint32 MemoryLoad uint32
TotalPhys uint64 TotalPhys uint64
@@ -40,17 +40,17 @@ type wProcessorArchitecture struct {
WReserved uint16 WReserved uint16
} }
// ProcessorArchitecture is an idiomatic wrapper for wProcessorArchitecture // ProcessorArchitecture is an idiomatic wrapper for wProcessorArchitecture.
type ProcessorArchitecture uint16 type ProcessorArchitecture uint16
// Idiomatic values for wProcessorArchitecture // Idiomatic values for wProcessorArchitecture.
const ( const (
AMD64 ProcessorArchitecture = 9 AMD64 ProcessorArchitecture = 9
ARM = 5 ARM ProcessorArchitecture = 5
ARM64 = 12 ARM64 ProcessorArchitecture = 12
IA64 = 6 IA64 ProcessorArchitecture = 6
INTEL = 0 INTEL ProcessorArchitecture = 0
UNKNOWN = 0xffff UNKNOWN ProcessorArchitecture = 0xffff
) )
// LpSystemInfo is a wrapper for LPSYSTEM_INFO // LpSystemInfo is a wrapper for LPSYSTEM_INFO
@@ -68,7 +68,7 @@ type lpSystemInfo struct {
WProcessorRevision uint16 WProcessorRevision uint16
} }
// SystemInfo is an idiomatic wrapper for LpSystemInfo // SystemInfo is an idiomatic wrapper for LpSystemInfo.
type SystemInfo struct { type SystemInfo struct {
Arch ProcessorArchitecture Arch ProcessorArchitecture
PageSize uint32 PageSize uint32
@@ -82,10 +82,10 @@ type SystemInfo struct {
ProcessorRevision uint16 ProcessorRevision uint16
} }
// WinComputerNameFormat is a wrapper for COMPUTER_NAME_FORMAT // WinComputerNameFormat is a wrapper for COMPUTER_NAME_FORMAT.
type WinComputerNameFormat int type WinComputerNameFormat int
// Definitions for WinComputerNameFormat constants // Definitions for WinComputerNameFormat constants.
const ( const (
ComputerNameNetBIOS WinComputerNameFormat = iota ComputerNameNetBIOS WinComputerNameFormat = iota
ComputerNameDNSHostname ComputerNameDNSHostname
@@ -112,7 +112,7 @@ func GlobalMemoryStatusEx() (MemoryStatus, error) {
mse.dwLength = (uint32)(unsafe.Sizeof(mse)) mse.dwLength = (uint32)(unsafe.Sizeof(mse))
r1, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&mse))) r1, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&mse)))
if ret := *(*bool)(unsafe.Pointer(&r1)); ret == false { if ret := *(*bool)(unsafe.Pointer(&r1)); !ret {
return MemoryStatus{}, err return MemoryStatus{}, err
} }

View File

@@ -12,7 +12,7 @@ import (
type WTSTypeClass int type WTSTypeClass int
// The valid values for the WTSTypeClass enumeration // The valid values for the WTSTypeClass enumeration.
const ( const (
WTSTypeProcessInfoLevel0 WTSTypeClass = iota WTSTypeProcessInfoLevel0 WTSTypeClass = iota
WTSTypeProcessInfoLevel1 WTSTypeProcessInfoLevel1
@@ -138,11 +138,11 @@ func WTSCloseServer(server syscall.Handle) error {
return nil return nil
} }
func WTSFreeMemoryEx(class WTSTypeClass, pMemory uintptr, NumberOfEntries uint32) error { func WTSFreeMemoryEx(class WTSTypeClass, pMemory uintptr, numberOfEntries uint32) error {
r1, _, err := procWTSFreeMemoryEx.Call( r1, _, err := procWTSFreeMemoryEx.Call(
uintptr(class), uintptr(class),
pMemory, pMemory,
uintptr(NumberOfEntries), uintptr(numberOfEntries),
) )
if r1 != 1 { if r1 != 1 {
@@ -182,7 +182,7 @@ func WTSEnumerateSessionsEx(server syscall.Handle, logger log.Logger) ([]WTSSess
sessionSize := unsafe.Sizeof(sizeTest) sessionSize := unsafe.Sizeof(sizeTest)
sessions := make([]WTSSession, 0, count) sessions := make([]WTSSession, 0, count)
for i := uint32(0); i < count; i++ { for i := range count {
curPtr := unsafe.Pointer(sessionInfoPointer + (uintptr(i) * sessionSize)) curPtr := unsafe.Pointer(sessionInfoPointer + (uintptr(i) * sessionSize))
data := (*wtsSessionInfo1)(curPtr) data := (*wtsSessionInfo1)(curPtr)

View File

@@ -17,31 +17,32 @@ type windowsExporterService struct{}
var logger *eventlog.Log var logger *eventlog.Log
//nolint:nonamedreturns
func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) { func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
changes <- svc.Status{State: svc.StartPending} changes <- svc.Status{State: svc.StartPending}
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
loop:
for { for c := range r {
select { switch c.Cmd {
case c := <-r: case svc.Interrogate:
switch c.Cmd { changes <- c.CurrentStatus
case svc.Interrogate: case svc.Stop, svc.Shutdown:
changes <- c.CurrentStatus _ = logger.Info(100, "Service Stop Received")
case svc.Stop, svc.Shutdown: changes <- svc.Status{State: svc.StopPending}
_ = logger.Info(100, "Service Stop Received")
changes <- svc.Status{State: svc.StopPending} return
break loop default:
default: _ = logger.Error(102, fmt.Sprintf("unexpected control request #%d", c))
_ = logger.Error(102, fmt.Sprintf("unexpected control request #%d", c))
}
} }
} }
return return
} }
var StopCh = make(chan bool) var StopCh = make(chan bool)
//nolint:gochecknoinits
func init() { func init() {
isService, err := svc.IsWindowsService() isService, err := svc.IsWindowsService()
if err != nil { if err != nil {

View File

@@ -70,7 +70,7 @@ func (l *eventlogLogger) Log(keyvals ...interface{}) error {
msg, err := syscall.UTF16PtrFromString(lb.buf.String()) msg, err := syscall.UTF16PtrFromString(lb.buf.String())
if err != nil { if err != nil {
return fmt.Errorf("error convert string to UTF-16: %v", err) return fmt.Errorf("error convert string to UTF-16: %w", err)
} }
ss := []*uint16{msg, nil, nil, nil, nil, nil, nil, nil, nil} ss := []*uint16{msg, nil, nil, nil, nil, nil, nil, nil, nil}
@@ -104,7 +104,7 @@ func (l *eventlogLogger) putLoggerBuf(lb *loggerBuf) {
// PrioritySelector inspects the list of keyvals and selects an eventlog priority. // PrioritySelector inspects the list of keyvals and selects an eventlog priority.
type PrioritySelector func(keyvals ...interface{}) Priority type PrioritySelector func(keyvals ...interface{}) Priority
// defaultPrioritySelector convert a kit/log level into a Windows Eventlog level // defaultPrioritySelector convert a kit/log level into a Windows Eventlog level.
func defaultPrioritySelector(keyvals ...interface{}) Priority { func defaultPrioritySelector(keyvals ...interface{}) Priority {
l := len(keyvals) l := len(keyvals)

View File

@@ -20,14 +20,14 @@ import (
promlogflag "github.com/prometheus/common/promlog/flag" promlogflag "github.com/prometheus/common/promlog/flag"
) )
// FileFlagName is the canonical flag name to configure the log file // FileFlagName is the canonical flag name to configure the log file.
const FileFlagName = "log.file" const FileFlagName = "log.file"
// FileFlagHelp is the help description for the log.file flag. // FileFlagHelp is the help description for the log.file flag.
const FileFlagHelp = "Output file of log messages. One of [stdout, stderr, eventlog, <path to log file>]" const FileFlagHelp = "Output file of log messages. One of [stdout, stderr, eventlog, <path to log file>]"
// AddFlags adds the flags used by this package to the Kingpin application. // AddFlags adds the flags used by this package to the Kingpin application.
// To use the default Kingpin application, call AddFlags(kingpin.CommandLine) // To use the default Kingpin application, call AddFlags(kingpin.CommandLine).
func AddFlags(a *kingpin.Application, config *log.Config) { func AddFlags(a *kingpin.Application, config *log.Config) {
config.Level = &promlog.AllowedLevel{} config.Level = &promlog.AllowedLevel{}
a.Flag(promlogflag.LevelFlagName, promlogflag.LevelFlagHelp). a.Flag(promlogflag.LevelFlagName, promlogflag.LevelFlagHelp).

View File

@@ -33,7 +33,7 @@ func (f *AllowedFile) Set(s string) error {
case "eventlog": case "eventlog":
f.w = nil f.w = nil
default: default:
file, err := os.OpenFile(s, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0200) file, err := os.OpenFile(s, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o200)
if err != nil { if err != nil {
return err return err
} }
@@ -42,7 +42,7 @@ func (f *AllowedFile) Set(s string) error {
return nil return nil
} }
// Config is a struct containing configurable settings for the logger // Config is a struct containing configurable settings for the logger.
type Config struct { type Config struct {
promlog.Config promlog.Config
@@ -72,15 +72,17 @@ func New(config *Config) (log.Logger, error) {
return nil, fmt.Errorf("unsupported log.format %q", config.Format.String()) return nil, fmt.Errorf("unsupported log.format %q", config.Format.String())
} }
if config.File.s == "eventlog" { switch {
case config.File.s == "eventlog":
w, err := goeventlog.Open("windows_exporter") w, err := goeventlog.Open("windows_exporter")
if err != nil { if err != nil {
return nil, err return nil, err
} }
l = eventlog.NewEventLogLogger(w, loggerFunc) l = eventlog.NewEventLogLogger(w, loggerFunc)
} else if config.File.w == nil { case config.File.w == nil:
panic("logger: file writer is nil") panic("logger: file writer is nil")
} else { default:
l = loggerFunc(log.NewSyncWriter(config.File.w)) l = loggerFunc(log.NewSyncWriter(config.File.w))
} }

View File

@@ -113,6 +113,7 @@ Data for some of the objects is also available through WMI:
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io" "io"
"strings" "strings"
@@ -120,7 +121,7 @@ import (
"unsafe" "unsafe"
) )
// TODO: There's a LittleEndian field in the PERF header - we ought to check it // TODO: There's a LittleEndian field in the PERF header - we ought to check it.
var bo = binary.LittleEndian var bo = binary.LittleEndian
const averageCount64Type = 1073874176 const averageCount64Type = 1073874176
@@ -204,9 +205,8 @@ func queryRawData(query string) ([]byte, error) {
buffer = make([]byte, bufLen) buffer = make([]byte, bufLen)
name, err := syscall.UTF16PtrFromString(query) name, err := syscall.UTF16PtrFromString(query)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode query string: %v", err) return nil, fmt.Errorf("failed to encode query string: %w", err)
} }
for { for {
@@ -220,14 +220,15 @@ func queryRawData(query string) ([]byte, error) {
(*byte)(unsafe.Pointer(&buffer[0])), (*byte)(unsafe.Pointer(&buffer[0])),
&bufLen) &bufLen)
if err == error(syscall.ERROR_MORE_DATA) { if errors.Is(err, error(syscall.ERROR_MORE_DATA)) {
newBuffer := make([]byte, len(buffer)+16384) newBuffer := make([]byte, len(buffer)+16384)
copy(newBuffer, buffer) copy(newBuffer, buffer)
buffer = newBuffer buffer = newBuffer
continue continue
} else if err != nil { } else if err != nil {
if errno, ok := err.(syscall.Errno); ok { var errNo syscall.Errno
return nil, fmt.Errorf("ReqQueryValueEx failed: %v errno %d", err, uint(errno)) if errors.As(err, &errNo) {
return nil, fmt.Errorf("ReqQueryValueEx failed: %w errno %d", err, uint(errNo))
} }
return nil, err return nil, err
@@ -266,7 +267,6 @@ more than you asked for.
*/ */
func QueryPerformanceData(query string) ([]*PerfObject, error) { func QueryPerformanceData(query string) ([]*PerfObject, error) {
buffer, err := queryRawData(query) buffer, err := queryRawData(query)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -277,7 +277,6 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
header := new(perfDataBlock) header := new(perfDataBlock)
err = header.BinaryReadFrom(r) err = header.BinaryReadFrom(r)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read performance data block for %q with: %w", query, err) return nil, fmt.Errorf("failed to read performance data block for %q with: %w", query, err)
} }
@@ -294,7 +293,7 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
objOffset := int64(header.HeaderLength) objOffset := int64(header.HeaderLength)
for i := 0; i < numObjects; i++ { for i := range numObjects {
_, err := r.Seek(objOffset, io.SeekStart) _, err := r.Seek(objOffset, io.SeekStart)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -328,7 +327,7 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
rawData: obj, rawData: obj,
} }
for i := 0; i < numCounterDefs; i++ { for i := range numCounterDefs {
def := new(perfCounterDefinition) def := new(perfCounterDefinition)
err := def.BinaryReadFrom(r) err := def.BinaryReadFrom(r)
if err != nil { if err != nil {
@@ -349,10 +348,10 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
} }
} }
if obj.NumInstances <= 0 { if obj.NumInstances <= 0 { //nolint:nestif
blockOffset := objOffset + int64(obj.DefinitionLength) blockOffset := objOffset + int64(obj.DefinitionLength)
_, err := r.Seek(blockOffset, io.SeekStart)
if err != nil { if _, err := r.Seek(blockOffset, io.SeekStart); err != nil {
return nil, err return nil, err
} }
@@ -370,20 +369,20 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
} else { } else {
instOffset := objOffset + int64(obj.DefinitionLength) instOffset := objOffset + int64(obj.DefinitionLength)
for i := 0; i < numInstances; i++ { for i := range numInstances {
_, err := r.Seek(instOffset, io.SeekStart) if _, err := r.Seek(instOffset, io.SeekStart); err != nil {
if err != nil {
return nil, err return nil, err
} }
inst := new(perfInstanceDefinition) inst := new(perfInstanceDefinition)
err = inst.BinaryReadFrom(r)
if err != nil { if err = inst.BinaryReadFrom(r); err != nil {
return nil, err return nil, err
} }
name, _ := readUTF16StringAtPos(r, instOffset+int64(inst.NameOffset), inst.NameLength) name, _ := readUTF16StringAtPos(r, instOffset+int64(inst.NameOffset), inst.NameLength)
pos := instOffset + int64(inst.ByteLength) pos := instOffset + int64(inst.ByteLength)
offset, counters, err := parseCounterBlock(buffer, r, pos, counterDefs) offset, counters, err := parseCounterBlock(buffer, r, pos, counterDefs)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -438,6 +437,7 @@ func parseCounterBlock(b []byte, r io.ReadSeeker, pos int64, defs []*PerfCounter
return int64(block.ByteLength), counters, nil return int64(block.ByteLength), counters, nil
} }
//nolint:nonamedreturns
func convertCounterValue(counterDef *perfCounterDefinition, buffer []byte, valueOffset int64) (value int64) { func convertCounterValue(counterDef *perfCounterDefinition, buffer []byte, valueOffset int64) (value int64) {
/* /*
We can safely ignore the type since we're not interested in anything except the raw value. We can safely ignore the type since we're not interested in anything except the raw value.

View File

@@ -1,39 +1,9 @@
package perflib package perflib
import ( import (
"fmt"
"testing" "testing"
) )
func ExampleQueryPerformanceData() {
objects, err := QueryPerformanceData("2")
if err != nil {
panic(err)
}
for _, object := range objects {
fmt.Printf("%d %s [%d counters, %d instances]\n",
object.NameIndex, object.Name, len(object.CounterDefs), len(object.Instances))
for _, instance := range object.Instances {
if !((instance.Name == "_Total") || (instance.Name == "")) {
continue
}
if instance.Name == "" {
fmt.Println("No instance.", instance.Name)
} else {
fmt.Println("Instance:", instance.Name)
}
for _, counter := range instance.Counters {
fmt.Printf(" -> %s %d\n", counter.Def.Name, counter.Def.NameIndex)
}
}
}
}
func BenchmarkQueryPerformanceData(b *testing.B) { func BenchmarkQueryPerformanceData(b *testing.B) {
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
_, _ = QueryPerformanceData("Global") _, _ = QueryPerformanceData("Global")

View File

@@ -10,7 +10,7 @@ import (
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
) )
// Conversion factors // Conversion factors.
const ( const (
TicksToSecondScaleFactor = 1 / 1e7 TicksToSecondScaleFactor = 1 / 1e7
WindowsEpoch = 116444736000000000 WindowsEpoch = 116444736000000000
@@ -48,7 +48,7 @@ func UnmarshalObject(obj *PerfObject, vs interface{}, logger log.Logger) error {
} }
} }
for i := 0; i < target.NumField(); i++ { for i := range target.NumField() {
f := rt.Field(i) f := rt.Field(i)
tag := f.Tag.Get("perflib") tag := f.Tag.Get("perflib")
if tag == "" { if tag == "" {

View File

@@ -6,17 +6,15 @@ import (
"syscall" "syscall"
) )
// readUTF16StringAtPos Read an unterminated UTF16 string at a given position, specifying its length // readUTF16StringAtPos Read an unterminated UTF16 string at a given position, specifying its length.
func readUTF16StringAtPos(r io.ReadSeeker, absPos int64, length uint32) (string, error) { func readUTF16StringAtPos(r io.ReadSeeker, absPos int64, length uint32) (string, error) {
value := make([]uint16, length/2) value := make([]uint16, length/2)
_, err := r.Seek(absPos, io.SeekStart) _, err := r.Seek(absPos, io.SeekStart)
if err != nil { if err != nil {
return "", err return "", err
} }
err = binary.Read(r, bo, value) err = binary.Read(r, bo, value)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -24,7 +22,7 @@ func readUTF16StringAtPos(r io.ReadSeeker, absPos int64, length uint32) (string,
return syscall.UTF16ToString(value), nil return syscall.UTF16ToString(value), nil
} }
// readUTF16String Reads a null-terminated UTF16 string at the current offset // readUTF16String Reads a null-terminated UTF16 string at the current offset.
func readUTF16String(r io.Reader) (string, error) { func readUTF16String(r io.Reader) (string, error) {
var err error var err error

View File

@@ -14,6 +14,8 @@ type simple struct {
} }
func TestUnmarshalPerflib(t *testing.T) { func TestUnmarshalPerflib(t *testing.T) {
t.Parallel()
cases := []struct { cases := []struct {
name string name string
obj *PerfObject obj *PerfObject
@@ -110,6 +112,8 @@ func TestUnmarshalPerflib(t *testing.T) {
} }
for _, c := range cases { for _, c := range cases {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
t.Parallel()
output := make([]simple, 0) output := make([]simple, 0)
err := UnmarshalObject(c.obj, &output, log.NewNopLogger()) err := UnmarshalObject(c.obj, &output, log.NewNopLogger())
if err != nil && !c.expectError { if err != nil && !c.expectError {

View File

@@ -13,6 +13,8 @@ import (
) )
func FuncBenchmarkCollector[C collector.Collector](b *testing.B, name string, collectFunc collector.BuilderWithFlags[C]) { func FuncBenchmarkCollector[C collector.Collector](b *testing.B, name string, collectFunc collector.BuilderWithFlags[C]) {
b.Helper()
c := collectFunc(kingpin.CommandLine) c := collectFunc(kingpin.CommandLine)
collectors := collector.New(map[string]collector.Collector{name: c}) collectors := collector.New(map[string]collector.Collector{name: c})
require.NoError(b, collectors.Build()) require.NoError(b, collectors.Build())

View File

@@ -14,13 +14,15 @@ import (
// Splits provided child Collectors and deduplicate. // Splits provided child Collectors and deduplicate.
func ExpandEnabledChildCollectors(enabled string) []string { func ExpandEnabledChildCollectors(enabled string) []string {
result := slices.Compact(strings.Split(enabled, ",")) result := slices.Compact(strings.Split(enabled, ","))
// Ensure result is ordered, to prevent test failure
// Result must order, to prevent test failures.
sort.Strings(result) sort.Strings(result)
return result return result
} }
func ExpandEnabledCollectors(enabled string) []string { func ExpandEnabledCollectors(enabled string) []string {
expanded := strings.Replace(enabled, types.DefaultCollectorsPlaceholder, types.DefaultCollectors, -1) expanded := strings.ReplaceAll(enabled, types.DefaultCollectorsPlaceholder, types.DefaultCollectors)
separated := strings.Split(expanded, ",") separated := strings.Split(expanded, ",")
unique := map[string]bool{} unique := map[string]bool{}
for _, s := range separated { for _, s := range separated {

View File

@@ -11,6 +11,8 @@ import (
) )
func TestExpandChildCollectors(t *testing.T) { func TestExpandChildCollectors(t *testing.T) {
t.Parallel()
cases := []struct { cases := []struct {
name string name string
input string input string
@@ -30,6 +32,8 @@ func TestExpandChildCollectors(t *testing.T) {
for _, c := range cases { for _, c := range cases {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
t.Parallel()
output := utils.ExpandEnabledChildCollectors(c.input) output := utils.ExpandEnabledChildCollectors(c.input)
if !reflect.DeepEqual(output, c.expectedOutput) { if !reflect.DeepEqual(output, c.expectedOutput) {
t.Errorf("Output mismatch, expected %+v, got %+v", c.expectedOutput, output) t.Errorf("Output mismatch, expected %+v, got %+v", c.expectedOutput, output)
@@ -39,6 +43,8 @@ func TestExpandChildCollectors(t *testing.T) {
} }
func TestExpandEnabled(t *testing.T) { func TestExpandEnabled(t *testing.T) {
t.Parallel()
expansionTests := []struct { expansionTests := []struct {
input string input string
expectedOutput []string expectedOutput []string

View File

@@ -9,9 +9,12 @@ import (
"golang.org/x/sys/windows/registry" "golang.org/x/sys/windows/registry"
) )
var WindowsVersion string var (
var WindowsVersionFloat float64 WindowsVersion string
WindowsVersionFloat float64
)
//nolint:gochecknoinits
func init() { func init() {
var err error var err error
WindowsVersion, WindowsVersionFloat, err = GetWindowsVersion() WindowsVersion, WindowsVersionFloat, err = GetWindowsVersion()

View File

@@ -41,6 +41,9 @@ func QueryNamespace(query string, dst interface{}, namespace string) error {
return wmi.QueryNamespace(query, dst, namespace) return wmi.QueryNamespace(query, dst, namespace)
} }
// QueryAll returns a query string that selects all fields from the given
// struct type.
// Deprecated: Use QueryAllForClass instead.
func QueryAll(src interface{}, logger log.Logger) string { func QueryAll(src interface{}, logger log.Logger) string {
var b bytes.Buffer var b bytes.Buffer
b.WriteString("SELECT * FROM ") b.WriteString("SELECT * FROM ")

View File

@@ -29,6 +29,8 @@ var (
type queryFunc func(src interface{}, class string, where string) string type queryFunc func(src interface{}, class string, where string) string
func TestCreateQuery(t *testing.T) { func TestCreateQuery(t *testing.T) {
t.Parallel()
cases := []struct { cases := []struct {
desc string desc string
dst interface{} dst interface{}
@@ -109,6 +111,8 @@ func TestCreateQuery(t *testing.T) {
} }
for _, c := range cases { for _, c := range cases {
t.Run(c.desc, func(t *testing.T) { t.Run(c.desc, func(t *testing.T) {
t.Parallel()
if q := c.queryFunc(c.dst, c.class, c.where); q != c.expected { if q := c.queryFunc(c.dst, c.class, c.where); q != c.expected {
t.Errorf("Case %q failed: Expected %q, got %q", c.desc, c.expected, q) t.Errorf("Case %q failed: Expected %q, got %q", c.desc, c.expected, q)
} }

View File

@@ -1,34 +0,0 @@
Param(
[Parameter(Mandatory=$true)]
$Class,
[Parameter(Mandatory=$false)]
$Namespace = "root/cimv2",
[Parameter(Mandatory=$false)]
$CollectorName = ($Class -replace 'Win32_PerfRawData_Perf',''),
[Parameter(Mandatory=$false)]
$ComputerName = "localhost",
[Parameter(Mandatory=$false)]
[CimSession] $Session
)
$ErrorActionPreference = "Stop"
if($null -ne $Session) {
$wmiObject = Get-CimInstance -CimSession $Session -Namespace $Namespace -Class $Class
}
else {
$wmiObject = Get-CimInstance -ComputerName $ComputerName -Namespace $Namespace -Class $Class
}
$members = $wmiObject `
| Get-Member -MemberType Properties `
| Where-Object { $_.Definition -Match '^u?int' -and $_.Name -NotMatch '_' } `
| Select-Object Name, @{Name="Type";Expression={$_.Definition.Split(" ")[0]}}
$input = @{
"Namespace"=$Namespace;
"Class"=$Class;
"CollectorName"=$CollectorName;
"Members"=$members
} | ConvertTo-Json
$outFileName = "..\..\collector\$CollectorName.go".ToLower()
$input | .\collector-generator.exe | Out-File -NoClobber -Encoding UTF8 $outFileName
go fmt $outFileName

View File

@@ -1,17 +0,0 @@
# Collector generator
Generates a collector skeleton implementation from a WMI class.
## Usage
Build the generator:
```bash
go build .
```
Run the script to query the WMI service and send the output to the generator:
```powershell
.\New-Collector.ps1 -Class Win32_PerfRawData_PerfOS_Processor
```
This will generate a collector. The collector name is generated by first removing `Win32_PerfRawData_Perf` and lower-casing, so `Win32_PerfRawData_PerfOS_Processor` will generate `os_processor.go`. This can be overridden by passing `-CollectorName` to the script.

View File

@@ -1,56 +0,0 @@
package collector
import (
"github.com/yusufpapurcu/wmi"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus-community/windows_exporter/log"
)
func init() {
registerCollector("{{ .CollectorName | toLower }}", new{{ .CollectorName }}Collector) // TODO: Add any perflib dependencies here
}
// A {{ .CollectorName }}Collector is a Prometheus collector for WMI {{ .Class }} metrics
type {{ .CollectorName }}Collector struct {
{{- range $m := .Members }}
{{ $m.Name }} *prometheus.Desc
{{- end }}
}
func new{{ .CollectorName }}Collector() (Collector, error) {
const subsystem = "{{ .CollectorName | toLower }}"
return &{{ .CollectorName }}Collector{
{{- range $m := .Members }}
{{ $m.Name }}: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "{{ $m.Name | toSnakeCase }}"),
"({{ $m.Name }})",
nil,
nil,
),
{{- end }}
}, nil
}
// {{ .Class }} docs:
// - <add link to documentation here>
type {{ .Class }} struct {
Name string
{{ range $m := .Members }}
{{ $m.Name }} {{ $m.Type }}
{{- end }}
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *{{ .CollectorName }}Collector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []{{ .Class }}
q := queryAll(&dst)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
{{ range $m := .Members }}
ch <- prometheus.MustNewConstMetric(
c.{{ $m.Name }},
prometheus.GaugeValue,
float64(dst[0].{{ $m.Name }}),
)
{{ end }}
return nil, nil
}

View File

@@ -1,60 +0,0 @@
package main
import (
"encoding/json"
"io/ioutil"
"os"
"strings"
"text/template"
"unicode"
)
type TemplateData struct {
CollectorName string
Class string
Members []Member
}
type Member struct {
Name string
Type string
}
func main() {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
var data TemplateData
if err = json.Unmarshal(bytes, &data); err != nil {
panic(err)
}
funcs := template.FuncMap{
"toLower": strings.ToLower,
"toSnakeCase": toSnakeCase,
}
tmpl, err := template.New("template").Funcs(funcs).ParseFiles("collector.template")
if err != nil {
panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "collector.template", data)
if err != nil {
panic(err)
}
}
// https://gist.github.com/elwinar/14e1e897fdbe4d3432e1
func toSnakeCase(in string) string {
runes := []rune(in)
length := len(runes)
var out []rune
for i := 0; i < length; i++ {
if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
out = append(out, '_')
}
out = append(out, unicode.ToLower(runes[i]))
}
return string(out)
}