Compare commits

..

39 Commits

Author SHA1 Message Date
Calle Pettersson
cdbb27d0b4 Fix collector flags not being registered
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-11-07 17:13:00 +10:00
Calle Pettersson
2fbd0464dc Merge pull request #651 from breed808/config_files
Fix exporter failing to start without config flag
2020-11-07 07:25:24 +01:00
Ben Reedy
f616589c5f Fix exporter failing to start without config flag
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-03 19:46:05 +10:00
Ben Reedy
f623c0ed89 Add unit test for config flattening functions
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
ce5c6eed72 Add configuration file documentation
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
d7122930d0 Flatten nested YAML data in specified config file
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
96aa2cf095 Add initial support for YAML configuration files
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
6231eb43e8 Use kingpin application for flags
Will be required to pass application object to config file functions.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Calle Pettersson
0880ec6a1a Add service dependency on wmiApSrv
This appears to fix service startup issues on certain systems, eg #637

Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-11-02 08:38:42 +10:00
Calle Pettersson
8f85475725 Add CODEOWNERS file
Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-11-02 08:33:45 +10:00
Björn Fischer
a4aef9b3c7 adds whitelist for exchange collectors (#642)
adds enable flag for exchange collectors

Signed-off-by: Björn Fischer <bfischer@inovex.de>
2020-11-01 18:26:14 +01:00
Calle Pettersson
637fc246af Merge pull request #640 from fischerman/filter_collectors
Add URL filter for collectors
2020-11-01 13:38:54 +01:00
Björn Fischer
6b141a128c Add docs for filtering enabled collectors
Signed-off-by: Björn Fischer <bfischer@inovex.de>
2020-10-26 14:10:53 +01:00
Björn Fischer
e97a04ed65 Add URL filter for collectors
Signed-off-by: Björn Fischer <bfischer@inovex.de>
2020-10-26 14:10:53 +01:00
Ben Reedy
cdfe3cf258 Add Windows Time Service collector
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-10-26 19:09:25 +10:00
Calle Pettersson
24fe6813b2 Merge pull request #632 from prometheus-community/fix-hyperv-panic
Fix panic in HyperV collector on input format mismatch
2020-10-26 09:01:37 +01:00
Ben Reedy
7eab1fc411 Set mssql transactions_active to Gauge.
Change also renames metric to avoid confusion.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-10-23 06:42:48 +10:00
Calle Pettersson
78918f7034 Merge pull request #633 from prometheus-community/maintainer-breed808
Update MAINTAINERS.md
2020-10-21 10:00:52 +02:00
Calle Pettersson
59e72c7016 Update MAINTAINERS.md
Add Ben Reedy
2020-10-21 08:49:17 +02:00
Calle Pettersson
49c082d594 Fix panic in HyperV collector on input format mismatch
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-10-19 18:02:51 +02:00
Calle Pettersson
b7b19aafa0 Merge pull request #630 from fpco/629-bump-go-version
Bump Go version from 1.13 to 1.15 for CI
2020-10-19 15:42:54 +02:00
Calle Pettersson
3624ea3bba Merge pull request #631 from dcrn/upgrade_wmi_lib
Upgrade WMI library
2020-10-19 15:01:01 +02:00
Michael Snoyman
898c17e657 Bump Go version from 1.13 to 1.15 for CI
Fixes #629, by including bugfix for
https://github.com/golang/go/issues/35447

Signed-off-by: Michael Snoyman <michael@snoyman.com>
2020-10-19 15:59:39 +03:00
Declan Curran
f9790f03fb Merge branch 'master' into upgrade_wmi_lib 2020-10-19 13:54:42 +01:00
Declan Curran
3708c85611 Updated wmi library as described in #446
Signed-off-by: Declan Curran <dcrn@users.noreply.github.com>
2020-10-19 13:53:36 +01:00
Calle Pettersson
7a5dc3c6f5 Merge pull request #615 from mallenLF/tcp-perflib
Convert the tcp collector to use perflib and support TCPv6 counters
2020-10-19 12:18:11 +02:00
Calle Pettersson
8f2f9d83f9 Merge pull request #623 from prometheus-community/remove-cs-metrics-from-memory-docs
Remove cs metrics from memory collector docs
2020-10-10 21:01:59 +02:00
Calle Pettersson
c5ea575fb1 Remove cs metrics from memory collector docs
Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-10-10 21:01:20 +02:00
Michael Allen
be39c1126a Document changes to the tcp collector
Note that TCPv6 metrics are now exported, and there is a new label, `af`.

Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-10-10 11:50:41 -07:00
Calle Pettersson
6765935d17 Merge pull request #563 from prometheus-community/set-versioninfo
Set Windows versioninfo on build
2020-10-10 10:44:06 +02:00
Calle Pettersson
51dd61beeb Set Windows versioninfo on build
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-10-10 10:33:48 +02:00
Calle Pettersson
a30422c31c Merge pull request #597 from prometheus-community/installer-phase
Change upgrade phase
2020-10-10 10:27:47 +02:00
Calle Pettersson
332a903757 Merge pull request #608 from siku4/add-firewall-remoteaddress-option-to-installer
Enable the use of remote ip addresses in Windows Firewall exception
2020-10-10 10:27:23 +02:00
Calle Pettersson
6e518f21bb Merge pull request #618 from ashumkin/readme-fix
Fix metrics description
2020-10-10 09:07:45 +02:00
Alexey Shumkin
3bf94cdaf6 Fix metrics description
`windows_mssql_locks_lock_timeouts` and
`windows_mssql_locks_lock_timeouts_excluding_NOWAIT` metrics have
exchanged descriptions.

According to
https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object
    ---
    Lock Timeouts     | Number of lock requests per second that
    (timeout > 0)/sec | timed out, but excluding requests for NOWAIT locks.
    ---
    Lock Timeouts/sec | Number of lock requests per second that timed
                      | out, including requests for NOWAIT locks.
    ---

Metrics gathered are correct but descriptions are exchanged.

Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
2020-10-09 14:16:06 +03:00
Michael Allen
94bda6aa79 Expose TCPv6 performance counters in the tcp collector
Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-10-08 11:43:39 -07:00
Michael Allen
380eff24c9 Convert the tcp collector to use perflib instead of WMI
Using perflib is substantially faster and more reliable than using WMI to
retrieve Windows performance counter data.

Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-10-07 22:25:58 -07:00
siku4
2ebea42de5 Enable the use of remote ip addresses for fw rule
Signed-off-by: siku4 <sk@sik-net.de>
2020-10-05 11:46:39 +02:00
Calle Pettersson
d39d5230ab Change upgrade phase
With afterInstallExecute, the old installation is only removed after the new one is finished, which has led to some users seeing the new version failing to start, leading to the install rolling back. afterInstallInitialize, in contrast, uninstalls before the new installation.

Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-09-12 16:38:41 +02:00
25 changed files with 618 additions and 84 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @prometheus-community/windows_exporter-reviewers

3
.gitignore vendored
View File

@@ -4,4 +4,5 @@ VERSION
*.un~
output/
.vscode
.idea
.idea
*.syso

View File

@@ -1,5 +1,6 @@
Contributors in alphabetical order
* [Ben Reedy](https://github.com/breed808)
* [Brian Brazil](https://github.com/brian-brazil)
* [Martin Lindhe](https://github.com/martinlindhe)
* [Calle Pettersson](https://github.com/carlpett)

View File

@@ -40,6 +40,7 @@ Name | Description | Enabled by default
[service](docs/collector.service.md) | Service state metrics | &#10003;
[system](docs/collector.system.md) | System calls | &#10003;
[tcp](docs/collector.tcp.md) | TCP connections |
[time](docs/collector.time.md) | Windows Time Service |
[thermalzone](docs/collector.thermalzone.md) | Thermal information
[terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS)
[textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file | &#10003;
@@ -47,6 +48,21 @@ Name | Description | Enabled by default
See the linked documentation on each collector for more information on reported metrics, configuration settings and usage examples.
### Filtering enabled collectors
The `windows_exporter` will expose all metrics from enabled collectors by default. This is the recommended way to collect metrics to avoid errors when comparing metrics of different families.
For advanced use the `windows_exporter` can be passed an optional list of collectors to filter metrics. The `collect[]` parameter may be used multiple times. In Prometheus configuration you can use this syntax under the [scrape config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#<scrape_config>).
```
params:
collect[]:
- foo
- bar
```
This can be useful for having different Prometheus servers collect specific metrics from nodes.
## Flags
windows_exporter accepts flags to configure certain behaviours. The ones configuring the global behaviour of the exporter are listed below, while collector-specific ones are documented in the respective collector documentation above.
@@ -74,6 +90,7 @@ Name | Description
`LISTEN_PORT` | The port to bind to. Defaults to 9182.
`METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics`
`TEXTFILE_DIR` | As the `--collector.textfile.directory` flag, provide a directory to read text files with metrics from
`REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (whitelist). Defaults to an empty string (any remote address).
`EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string.
Parameters are sent to the installer via `msiexec`. Example invocations:
@@ -119,6 +136,34 @@ The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182
When there are multiple processes with the same name, WMI represents those after the first instance as `process-name#index`. So to get them all, rather than just the first one, the [regular expression](https://en.wikipedia.org/wiki/Regular_expression) must use `.+`. See [process](docs/collector.process.md) for more information.
### Using a configuration file
YAML configuration files can be specified with the `--config.file` flag. E.G. `.\windows_exporter.exe --config.file=config.yml`
```yaml
collectors:
enabled: cpu,cs,net,service
collector:
service:
services-where: "Name='windows_exporter'"
log:
level: warn
```
An example configuration file can be found [here](docs/example_config.yml).
#### Configuration file notes
Configuration file values can be mixed with CLI flags. E.G.
`.\windows_exporter.exe --collectors.enabled=cpu,logon`
```yaml
log:
level: debug
```
CLI flags enjoy a higher priority over values specified in the configuration file.
## License

View File

@@ -1,8 +1,7 @@
version: "{build}"
os: Visual Studio 2017
os: Visual Studio 2019
build: off
stack: go 1.13
environment:
GOPATH: c:\gopath
@@ -13,7 +12,7 @@ clone_folder: c:\gopath\src\github.com\prometheus-community\windows_exporter
install:
- mkdir %GOPATH%\bin
- set PATH=%GOPATH%\bin;%PATH%
- set PATH=%PATH%;C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin
- set PATH=%PATH%;C:\msys64\mingw64\bin
- choco install gitversion.portable make -y
- ps: |
appveyor DownloadFile https://github.com/golangci/golangci-lint/releases/download/v1.21.0/golangci-lint-1.21.0-windows-amd64.zip
@@ -22,6 +21,7 @@ install:
- ps: |
$env:GO111MODULE="off"
go get -u github.com/prometheus/promu
go get -u github.com/josephspurrier/goversioninfo/cmd/goversioninfo
$env:GO111MODULE="on"
test_script:
@@ -37,8 +37,13 @@ build_script:
# so we need to run it before setting the preference.
go mod download
$ErrorActionPreference = "Stop"
gitversion /output json /showvariable FullSemVer | Set-Content VERSION -PassThru
$Version = Get-Content VERSION
# Windows versioninfo resources need the file version by parts (but product version is free text)
$VersionParts = ($Version -replace '^v?([0-9\.]+).*$','$1').Split(".")
goversioninfo.exe -ver-major $VersionParts[0] -ver-minor $VersionParts[1] -ver-patch $VersionParts[2] -product-version $Version -platform-specific
make crossbuild
# GH requires all files to have different names, so add version/arch to differentiate
foreach($Arch in "amd64","386") {

View File

@@ -119,3 +119,12 @@ func boolToFloat(b bool) float64 {
}
return 0.0
}
func find(slice []string, val string) bool {
for _, item := range slice {
if item == val {
return true
}
}
return false
}

View File

@@ -65,7 +65,7 @@ type exchangeCollector struct {
RPCOperationsPerSec *prometheus.Desc
UserCount *prometheus.Desc
ActiveCollFuncs []func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error
enabledCollectors []string
}
var (
@@ -86,6 +86,11 @@ var (
"collectors.exchange.list",
"List the collectors along with their perflib object name/ids",
).Bool()
argExchangeCollectorsEnabled = kingpin.Flag(
"collectors.exchange.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default("").String()
)
// newExchangeCollector returns a new Collector
@@ -139,6 +144,8 @@ func newExchangeCollector() (Collector, error) {
MailboxServerProxyFailureRate: desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name"),
PingCommandsPending: desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue"),
SyncCommandsPerSec: desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder"),
enabledCollectors: make([]string, 0, len(exchangeAllCollectorNames)),
}
collectorDesc := map[string]string{
@@ -161,12 +168,27 @@ func newExchangeCollector() (Collector, error) {
os.Exit(0)
}
if *argExchangeCollectorsEnabled == "" {
for _, collectorName := range exchangeAllCollectorNames {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
}
} else {
for _, collectorName := range strings.Split(*argExchangeCollectorsEnabled, ",") {
if find(exchangeAllCollectorNames, collectorName) {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
} else {
return nil, fmt.Errorf("Unknown exchange collector: %s", collectorName)
}
}
}
return &c, nil
}
// Collect collects exchange metrics and sends them to prometheus
func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
for collectorName, collectorFunc := range map[string]func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error{
collectorFuncs := map[string]func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error{
"ADAccessProcesses": c.collectADAccessProcesses,
"TransportQueues": c.collectTransportQueues,
"HttpProxy": c.collectHTTPProxy,
@@ -176,8 +198,10 @@ func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Met
"Autodiscover": c.collectAutoDiscover,
"WorkloadManagement": c.collectWorkloadManagementWorkloads,
"RpcClientAccess": c.collectRPC,
} {
if err := collectorFunc(ctx, ch); err != nil {
}
for _, collectorName := range c.enabledCollectors {
if err := collectorFuncs[collectorName](ctx, ch); err != nil {
log.Errorf("Error in %s: %s", collectorName, err)
return err
}

View File

@@ -1001,8 +1001,17 @@ func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prome
}
// The name format is <VM Name>:Hv VP <vcore id>
parts := strings.Split(obj.Name, ":")
if len(parts) != 2 {
log.Warnf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, "<VM Name>:Hv VP <vcore id>")
continue
}
coreParts := strings.Split(parts[1], " ")
if len(coreParts) != 3 {
log.Warnf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP <vcore id>")
continue
}
vmName := parts[0]
coreId := strings.Split(parts[1], " ")[2]
coreId := coreParts[2]
ch <- prometheus.MustNewConstMetric(
c.VMGuestRunTime,

View File

@@ -387,7 +387,7 @@ type MSSQLCollector struct {
TransactionsLongestTransactionRunningSeconds *prometheus.Desc
TransactionsNonSnapshotVersionActiveTotal *prometheus.Desc
TransactionsSnapshotActiveTotal *prometheus.Desc
TransactionsActiveTotal *prometheus.Desc
TransactionsActive *prometheus.Desc
TransactionsUpdateConflictsTotal *prometheus.Desc
TransactionsUpdateSnapshotActiveTotal *prometheus.Desc
TransactionsVersionCleanupRateBytes *prometheus.Desc
@@ -1749,8 +1749,8 @@ func NewMSSQLCollector() (Collector, error) {
[]string{"instance"},
nil,
),
TransactionsActiveTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transactions_active_total"),
TransactionsActive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transactions_active"),
"(Transactions.Transactions)",
[]string{"instance"},
nil,
@@ -3832,8 +3832,8 @@ func (c *MSSQLCollector) collectTransactions(ctx *ScrapeContext, ch chan<- prome
)
ch <- prometheus.MustNewConstMetric(
c.TransactionsActiveTotal,
prometheus.CounterValue,
c.TransactionsActive,
prometheus.GaugeValue,
v.Transactions,
sqlInstance,
)

View File

@@ -3,17 +3,15 @@
package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
registerCollector("tcp", NewTCPCollector)
registerCollector("tcp", NewTCPCollector, "TCPv4", "TCPv6")
}
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv4 metrics
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics
type TCPCollector struct {
ConnectionFailures *prometheus.Desc
ConnectionsActive *prometheus.Desc
@@ -34,55 +32,55 @@ func NewTCPCollector() (Collector, error) {
ConnectionFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_failures"),
"(TCP.ConnectionFailures)",
nil,
[]string{"af"},
nil,
),
ConnectionsActive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_active"),
"(TCP.ConnectionsActive)",
nil,
[]string{"af"},
nil,
),
ConnectionsEstablished: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_established"),
"(TCP.ConnectionsEstablished)",
nil,
[]string{"af"},
nil,
),
ConnectionsPassive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_passive"),
"(TCP.ConnectionsPassive)",
nil,
[]string{"af"},
nil,
),
ConnectionsReset: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_reset"),
"(TCP.ConnectionsReset)",
nil,
[]string{"af"},
nil,
),
SegmentsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_total"),
"(TCP.SegmentsTotal)",
nil,
[]string{"af"},
nil,
),
SegmentsReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_received_total"),
"(TCP.SegmentsReceivedTotal)",
nil,
[]string{"af"},
nil,
),
SegmentsRetransmittedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_retransmitted_total"),
"(TCP.SegmentsRetransmittedTotal)",
nil,
[]string{"af"},
nil,
),
SegmentsSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_sent_total"),
"(TCP.SegmentsSentTotal)",
nil,
[]string{"af"},
nil,
),
}, nil
@@ -91,7 +89,7 @@ func NewTCPCollector() (Collector, error) {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting tcp metrics:", desc, err)
return err
}
@@ -100,75 +98,94 @@ func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
// Win32_PerfRawData_Tcpip_TCPv4 docs
// - https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx
type Win32_PerfRawData_Tcpip_TCPv4 struct {
ConnectionFailures uint64
ConnectionsActive uint64
ConnectionsEstablished uint64
ConnectionsPassive uint64
ConnectionsReset uint64
SegmentsPersec uint64
SegmentsReceivedPersec uint64
SegmentsRetransmittedPersec uint64
SegmentsSentPersec uint64
// The TCPv6 performance object uses the same fields.
type tcp struct {
ConnectionFailures float64 `perflib:"Connection Failures"`
ConnectionsActive float64 `perflib:"Connections Active"`
ConnectionsEstablished float64 `perflib:"Connections Established"`
ConnectionsPassive float64 `perflib:"Connections Passive"`
ConnectionsReset float64 `perflib:"Connections Reset"`
SegmentsPersec float64 `perflib:"Segments/sec"`
SegmentsReceivedPersec float64 `perflib:"Segments Received/sec"`
SegmentsRetransmittedPersec float64 `perflib:"Segments Retransmitted/sec"`
SegmentsSentPersec float64 `perflib:"Segments Sent/sec"`
}
func (c *TCPCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_Tcpip_TCPv4
q := queryAll(&dst)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
// Counters
func writeTCPCounters(metrics tcp, labels []string, c *TCPCollector, ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(
c.ConnectionFailures,
prometheus.CounterValue,
float64(dst[0].ConnectionFailures),
metrics.ConnectionFailures,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsActive,
prometheus.CounterValue,
float64(dst[0].ConnectionsActive),
metrics.ConnectionsActive,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsEstablished,
prometheus.GaugeValue,
float64(dst[0].ConnectionsEstablished),
metrics.ConnectionsEstablished,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsPassive,
prometheus.CounterValue,
float64(dst[0].ConnectionsPassive),
metrics.ConnectionsPassive,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsReset,
prometheus.CounterValue,
float64(dst[0].ConnectionsReset),
metrics.ConnectionsReset,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsPersec),
metrics.SegmentsPersec,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsReceivedTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsReceivedPersec),
metrics.SegmentsReceivedPersec,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsRetransmittedTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsRetransmittedPersec),
metrics.SegmentsRetransmittedPersec,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsSentTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsSentPersec),
metrics.SegmentsSentPersec,
labels...,
)
}
func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []tcp
// TCPv4 counters
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil {
return nil, err
}
if len(dst) != 0 {
writeTCPCounters(dst[0], []string{"ipv4"}, c, ch)
}
// TCPv6 counters
if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst); err != nil {
return nil, err
}
if len(dst) != 0 {
writeTCPCounters(dst[0], []string{"ipv6"}, c, ch)
}
return nil, nil
}

124
collector/time.go Normal file
View File

@@ -0,0 +1,124 @@
// +build windows
package collector
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
registerCollector("time", newTimeCollector, "Windows Time Service")
}
// TimeCollector is a Prometheus collector for Perflib counter metrics
type TimeCollector struct {
ClockFrequencyAdjustmentPPBTotal *prometheus.Desc
ComputedTimeOffset *prometheus.Desc
NTPClientTimeSourceCount *prometheus.Desc
NTPRoundtripDelay *prometheus.Desc
NTPServerIncomingRequestsTotal *prometheus.Desc
NTPServerOutgoingResponsesTotal *prometheus.Desc
}
func newTimeCollector() (Collector, error) {
const subsystem = "time"
return &TimeCollector{
ClockFrequencyAdjustmentPPBTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "clock_frequency_adjustment_ppb_total"),
"Total adjustment made to the local system clock frequency by W32Time in Parts Per Billion (PPB) units.",
nil,
nil,
),
ComputedTimeOffset: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "computed_time_offset_seconds"),
"Absolute time offset between the system clock and the chosen time source, in seconds",
nil,
nil,
),
NTPClientTimeSourceCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_client_time_source_count"),
"Active number of NTP Time sources being used by the client",
nil,
nil,
),
NTPRoundtripDelay: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_round_trip_delay_seconds"),
"Roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds",
nil,
nil,
),
NTPServerOutgoingResponsesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_server_outgoing_responses_total"),
"Total number of requests responded to by NTP server",
nil,
nil,
),
NTPServerIncomingRequestsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_server_incoming_requests_total"),
"Total number of requests received by NTP server",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *TimeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting time metrics:", desc, err)
return err
}
return nil
}
// Perflib "Windows Time Service"
type windowsTime struct {
ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"`
ComputedTimeOffset float64 `perflib:"Computed Time Offset"`
NTPClientTimeSourceCount float64 `perflib:"NTP Client Time Source Count"`
NTPRoundtripDelay float64 `perflib:"NTP Roundtrip Delay"`
NTPServerIncomingRequestsTotal float64 `perflib:"NTP Server Incoming Requests"`
NTPServerOutgoingResponsesTotal float64 `perflib:"NTP Server Outgoing Responses"`
}
func (c *TimeCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []windowsTime // Single-instance class, array is required but will have single entry.
if err := unmarshalObject(ctx.perfObjects["Windows Time Service"], &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.ClockFrequencyAdjustmentPPBTotal,
prometheus.CounterValue,
dst[0].ClockFrequencyAdjustmentPPBTotal,
)
ch <- prometheus.MustNewConstMetric(
c.ComputedTimeOffset,
prometheus.GaugeValue,
dst[0].ComputedTimeOffset/1000000, // microseconds -> seconds
)
ch <- prometheus.MustNewConstMetric(
c.NTPClientTimeSourceCount,
prometheus.GaugeValue,
dst[0].NTPClientTimeSourceCount,
)
ch <- prometheus.MustNewConstMetric(
c.NTPRoundtripDelay,
prometheus.GaugeValue,
dst[0].NTPRoundtripDelay/1000000, // microseconds -> seconds
)
ch <- prometheus.MustNewConstMetric(
c.NTPServerIncomingRequestsTotal,
prometheus.CounterValue,
dst[0].NTPServerIncomingRequestsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.NTPServerOutgoingResponsesTotal,
prometheus.CounterValue,
dst[0].NTPServerOutgoingResponsesTotal,
)
return nil, nil
}

84
config/config.go Normal file
View File

@@ -0,0 +1,84 @@
// Copyright 2018 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"io/ioutil"
"os"
"github.com/prometheus/common/log"
"gopkg.in/alecthomas/kingpin.v2"
"gopkg.in/yaml.v2"
)
type getFlagger interface {
GetFlag(name string) *kingpin.FlagClause
}
// Resolver represents a configuration file resolver for kingpin.
type Resolver struct {
flags map[string]string
}
// NewResolver returns a Resolver structure.
func NewResolver(file string) (*Resolver, error) {
flags := map[string]string{}
log.Infof("Loading configuration file: %v", file)
if _, err := os.Stat(file); err != nil {
return nil, err
}
b, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
var rawValues map[string]interface{}
err = yaml.Unmarshal(b, &rawValues)
if err != nil {
return nil, err
}
// Flatten nested YAML values
flattenedValues := flatten(rawValues)
for k, v := range flattenedValues {
if _, ok := flags[k]; !ok {
flags[k] = v
}
}
return &Resolver{flags: flags}, nil
}
func (c *Resolver) setDefault(v getFlagger) {
for name, value := range c.flags {
f := v.GetFlag(name)
if f != nil {
f.Default(value)
}
}
}
// Bind sets active flags with their default values from the configuration file(s).
func (c *Resolver) Bind(app *kingpin.Application, args []string) error {
// Parse the command line arguments to get the selected command.
pc, err := app.ParseContext(args)
if err != nil {
return err
}
c.setDefault(app)
if pc.SelectedCommand != nil {
c.setDefault(pc.SelectedCommand)
}
return nil
}

61
config/flatten.go Normal file
View File

@@ -0,0 +1,61 @@
package config
import "fmt"
// flatten flattens the nested struct.
//
// All keys will be joined by dot
// e.g. {"a": {"b":"c"}} => {"a.b":"c"}
// or {"a": {"b":[1,2]}} => {"a.b.0":1, "a.b.1": 2}
func flatten(data map[string]interface{}) map[string]string {
ret := make(map[string]string)
for k, v := range data {
switch typed := v.(type) {
case map[interface{}]interface{}:
for fk, fv := range flatten(convertMap(typed)) {
ret[fmt.Sprintf("%s.%s", k, fk)] = fv
}
case map[string]interface{}:
for fk, fv := range flatten(typed) {
ret[fmt.Sprintf("%s.%s", k, fk)] = fv
}
case []interface{}:
for fk, fv := range flattenSlice(typed) {
ret[fmt.Sprintf("%s.%s", k, fk)] = fv
}
default:
ret[k] = fmt.Sprint(typed)
}
}
return ret
}
func flattenSlice(data []interface{}) map[string]string {
ret := make(map[string]string)
for idx, v := range data {
switch typed := v.(type) {
case map[interface{}]interface{}:
for fk, fv := range flatten(convertMap(typed)) {
ret[fmt.Sprintf("%d,%s", idx, fk)] = fv
}
case map[string]interface{}:
for fk, fv := range flatten(typed) {
ret[fmt.Sprintf("%d,%s", idx, fk)] = fv
}
case []interface{}:
for fk, fv := range flattenSlice(typed) {
ret[fmt.Sprintf("%d,%s", idx, fk)] = fv
}
default:
ret[fmt.Sprint(idx)] = fmt.Sprint(typed)
}
}
return ret
}
func convertMap(originalMap map[interface{}]interface{}) map[string]interface{} {
convertedMap := map[string]interface{}{}
for key, value := range originalMap {
convertedMap[key.(string)] = value
}
return convertedMap
}

33
config/flatten_test.go Normal file
View File

@@ -0,0 +1,33 @@
package config
import (
"gopkg.in/yaml.v2"
"reflect"
"testing"
)
// Unmarshal good configuration file and confirm data is flattened correctly
func TestConfigFlattening(t *testing.T) {
goodYamlConfig := []byte(`---
collectors:
enabled: cpu,net,service
log:
level: debug`)
var data map[string]interface{}
err := yaml.Unmarshal(goodYamlConfig, &data)
if err != nil {
t.Error(err)
}
expectedResult := map[string]string{
"collectors.enabled": "cpu,net,service",
"log.level": "debug",
}
flattenedValues := flatten(data)
if !reflect.DeepEqual(expectedResult, flattenedValues) {
t.Errorf("Flattened values do not match!\nExpected result: %s\nActual result: %s", expectedResult, flattenedValues)
}
}

View File

@@ -15,6 +15,9 @@ Enabled by default? | No
### `--collectors.exchange.list`
Lists the Perflib Objects that are queried for data along with the perlfib object id
### `--collectors.exchange.enabled`
Comma-separated list of collectors to use, for example: `--collectors.exchange.enabled=AvailabilityService,OutlookWebAccess`. Matching is case-sensetive. Depending on the exchange installation not all performance counters are available. Use `--collectors.exchange.list` to obtain a list of supported collectors.
## Metrics
Name | Description
--------------|---------------

View File

@@ -17,8 +17,6 @@ None
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_cs_logical_processors` | Number of installed logical processors | gauge | None
`windows_cs_physical_memory_bytes` | Total installed physical memory | gauge | None
`windows_memory_available_bytes` | The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to the standby (cached), free and zero page lists | gauge | None
`windows_memory_cache_bytes` | Number of bytes currently being used by the file system cache | gauge | None
`windows_memory_cache_bytes_peak` | Maximum number of CacheBytes after the system was last restarted | gauge | None

View File

@@ -194,8 +194,8 @@ Name | Description | Type | Labels
`windows_mssql_genstats_user_connections` | Counts the number of users currently connected to SQL Server | counter | `instance`
`windows_mssql_locks_average_wait_seconds` | Average amount of wait time (in milliseconds) for each lock request that resulted in a wait | counter | `instance`, `resource`
`windows_mssql_locks_lock_requests` | Number of new locks and lock conversions per second requested from the lock manager | counter | `instance`, `resource`
`windows_mssql_locks_lock_timeouts` | Number of lock requests per second that timed out, but excluding requests for NOWAIT locks | counter | `instance`, `resource`
`windows_mssql_locks_lock_timeouts_excluding_NOWAIT` | Number of lock requests per second that timed out, including requests for NOWAIT locks | counter | `instance`, `resource`
`windows_mssql_locks_lock_timeouts` | Number of lock requests per second that timed out, including requests for NOWAIT locks | counter | `instance`, `resource`
`windows_mssql_locks_lock_timeouts_excluding_NOWAIT` | Number of lock requests per second that timed out, but excluding requests for NOWAIT locks | counter | `instance`, `resource`
`windows_mssql_locks_lock_waits` | Total wait time (in milliseconds) for locks in the last second | counter | `instance`, `resource`
`windows_mssql_locks_lock_wait_seconds` | Number of lock requests per second that required the caller to wait | counter | `instance`, `resource`
`windows_mssql_locks_deadlocks` | Number of lock requests per second that resulted in a deadlock | counter | `instance`, `resource`
@@ -235,7 +235,7 @@ Name | Description | Type | Labels
`windows_mssql_transactions_longest_transaction_running_seconds` | The length of time (in seconds) since the start of the transaction that has been active longer than any other current transaction | gauge | `instance`
`windows_mssql_transactions_nonsnapshot_version_active_total` | The number of currently active transactions that are not using snapshot isolation level and have made data modifications that have generated row versions in the tempdb version store | counter | `instance`
`windows_mssql_transactions_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level | counter | `instance`
`windows_mssql_transactions_active_total` | The number of currently active transactions of all types | counter | `instance`
`windows_mssql_transactions_active` | The number of currently active transactions of all types | gauge | `instance`
`windows_mssql_transactions_update_conflicts_total` | The percentage of those transactions using the snapshot isolation level that have encountered update conflicts within the last second | counter | `instance`
`windows_mssql_transactions_update_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level and have modified data | counter | `instance`
`windows_mssql_transactions_version_cleanup_rate_bytes` | The rate (in kilobytes per second) at which row versions are removed from the snapshot isolation version store in tempdb | gauge | `instance`

View File

@@ -5,7 +5,8 @@ The tcp collector exposes metrics about the TCP/IPv4 network stack.
|||
-|-
Metric name prefix | `tcp`
Classes | [`Win32_PerfRawData_Tcpip_TCPv4`](https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx)
Data source | Perflib
Classes | [`Win32_PerfRawData_Tcpip_TCPv4`](https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx), Win32_PerfRawData_Tcpip_TCPv6
Enabled by default? | No
## Flags
@@ -16,15 +17,15 @@ None
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_tcp_connection_failures` | Number of times TCP connections have made a direct transition to the CLOSED state from the SYN-SENT state or the SYN-RCVD state, plus the number of times TCP connections have made a direct transition from the SYN-RCVD state to the LISTEN state | counter | None
`windows_tcp_connections_active` | Number of times TCP connections have made a direct transition from the CLOSED state to the SYN-SENT state.| counter | None
`windows_tcp_connections_established` | Number of TCP connections for which the current state is either ESTABLISHED or CLOSE-WAIT. | counter | None
`windows_tcp_connections_passive` | Number of times TCP connections have made a direct transition from the LISTEN state to the SYN-RCVD state. | counter | None
`windows_tcp_connections_reset` | Number of times TCP connections have made a direct transition from the LISTEN state to the SYN-RCVD state. | counter | None
`windows_tcp_segments_total` | Total segments sent or received using the TCP protocol | counter | None
`windows_tcp_segments_received_total` | Total segments received, including those received in error. This count includes segments received on currently established connections | counter | None
`windows_tcp_segments_retransmitted_total` | Total segments retransmitted. That is, segments transmitted that contain one or more previously transmitted bytes | counter | None
`windows_tcp_segments_sent_total` | Total segments sent, including those on current connections, but excluding those containing *only* retransmitted bytes | counter | None
`windows_tcp_connection_failures` | Number of times TCP connections have made a direct transition to the CLOSED state from the SYN-SENT state or the SYN-RCVD state, plus the number of times TCP connections have made a direct transition from the SYN-RCVD state to the LISTEN state | counter | af
`windows_tcp_connections_active` | Number of times TCP connections have made a direct transition from the CLOSED state to the SYN-SENT state.| counter | af
`windows_tcp_connections_established` | Number of TCP connections for which the current state is either ESTABLISHED or CLOSE-WAIT. | counter | af
`windows_tcp_connections_passive` | Number of times TCP connections have made a direct transition from the LISTEN state to the SYN-RCVD state. | counter | af
`windows_tcp_connections_reset` | Number of times TCP connections have made a direct transition from the LISTEN state to the SYN-RCVD state. | counter | af
`windows_tcp_segments_total` | Total segments sent or received using the TCP protocol | counter | af
`windows_tcp_segments_received_total` | Total segments received, including those received in error. This count includes segments received on currently established connections | counter | af
`windows_tcp_segments_retransmitted_total` | Total segments retransmitted. That is, segments transmitted that contain one or more previously transmitted bytes | counter | af
`windows_tcp_segments_sent_total` | Total segments sent, including those on current connections, but excluding those containing *only* retransmitted bytes | counter | af
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_

45
docs/collector.time.md Normal file
View File

@@ -0,0 +1,45 @@
# time collector
The time collector exposes the Windows Time Service metrics. Note that the Windows Time Service must be running, else metric collection will fail.
If the Windows Time Service is stopped after collection has started, collector metric values will reset to 0.
|||
-|-
Metric name prefix | `time`
Data source | Perflib
Enabled by default? | No
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_time_clock_frequency_Adjustment_ppb_total` | Total adjustment made to the local system clock frequency by W32Time in parts per billion (PPB) units. 1 PPB adjustment implies the system clock was adjusted at a rate of 1 nanosecond per second (1 ns/s). The smallest possible adjustment can vary and is expected to be in the order of 100's of PPB. | counter | None
`windows_time_computed_time_offset_seconds` | Absolute time offset between the system clock and the chosen time source, in seconds. | counter | None
`windows_time_ntp_client_time_source_count` | Active number of NTP Time sources being used by the client. This is a count of active, distinct IP addresses of time servers that are responding to this client's requests. | gauge | None
`windows_time_ntp_round_trip_delay_seconds` | Total roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds. This is the time elapsed on the NTP client between transmitting a request to the NTP server and receiving a valid response from the server. | gauge | None
`windows_time_ntp_server_outgoing_responses_total` | Total number of requests responded to by the NTP server. | counter | None
`windows_time_ntp_server_incoming_requests_total` | Total number of requests received by the NTP server. | counter | None
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
**prometheus.rules**
```yaml
# Alert on hosts with an NTP client delay of more than 1 second, for a 5 minute period or longer.
- alert: NTPClientDelay
expr: windows_time_ntp_round_trip_delay_seconds > 1
for: 5m
labels:
severity: warning
annotations:
summary: "NTP client delay: (instance {{ $labels.instance }})"
description: "RTT for NTP client is greater than 1 second!\nVALUE = {{ $value }}sec\n LABELS: {{ $labels }}"
```

15
docs/example_config.yml Normal file
View File

@@ -0,0 +1,15 @@
---
# Note this is not an exhaustive list of all configuration values
collectors:
enabled: cpu,cs,logical_disk,net,os,service,system,textfile
collector:
service:
services-where: Name='windows_exporter'
log:
level: debug
scrape:
timeout-margin: 0.5
telemetry:
addr: ":9182"
path: /metrics
max-requests: 5

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
_ "net/http/pprof"
"os"
"sort"
"strconv"
"strings"
@@ -17,6 +18,7 @@ import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/collector"
"github.com/prometheus-community/windows_exporter/config"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/log"
@@ -268,6 +270,10 @@ func initWbem() {
func main() {
var (
configFile = kingpin.Flag(
"config.file",
"YAML configuration file to use. Values set in this file will be overriden by CLI flags.",
).String()
listenAddress = kingpin.Flag(
"telemetry.addr",
"host:port for exporter.",
@@ -297,8 +303,24 @@ func main() {
log.AddFlags(kingpin.CommandLine)
kingpin.Version(version.Print("windows_exporter"))
kingpin.HelpFlag.Short('h')
// Load values from configuration file(s). Executable flags must first be parsed, in order
// to load the specified file(s).
kingpin.Parse()
if *configFile != "" {
resolver, err := config.NewResolver(*configFile)
if err != nil {
log.Fatalf("could not load config file: %v\n", err)
}
err = resolver.Bind(kingpin.CommandLine, os.Args[1:])
if err != nil {
log.Fatalf("%v\n", err)
}
// Parse flags once more to include those discovered in configuration file(s).
kingpin.Parse()
}
if *printCollectors {
collectors := collector.Available()
collectorNames := make(sort.StringSlice, 0, len(collectors))
@@ -339,9 +361,21 @@ func main() {
h := &metricsHandler{
timeoutMargin: *timeoutMargin,
collectorFactory: func(timeout time.Duration) *windowsCollector {
return &windowsCollector{
collectors: collectors,
collectorFactory: func(timeout time.Duration, requestedCollectors []string) (error, *windowsCollector) {
filteredCollectors := make(map[string]collector.Collector)
// scrape all enabled collectors if no collector is requested
if len(requestedCollectors) == 0 {
filteredCollectors = collectors
}
for _, name := range requestedCollectors {
col, exists := collectors[name]
if !exists {
return fmt.Errorf("unavailable collector: %s", name), nil
}
filteredCollectors[name] = col
}
return nil, &windowsCollector{
collectors: filteredCollectors,
maxScrapeDuration: timeout,
}
},
@@ -455,7 +489,7 @@ loop:
type metricsHandler struct {
timeoutMargin float64
collectorFactory func(timeout time.Duration) *windowsCollector
collectorFactory func(timeout time.Duration, requestedCollectors []string) (error, *windowsCollector)
}
func (mh *metricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -475,7 +509,14 @@ func (mh *metricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
timeoutSeconds = timeoutSeconds - mh.timeoutMargin
reg := prometheus.NewRegistry()
reg.MustRegister(mh.collectorFactory(time.Duration(timeoutSeconds * float64(time.Second))))
err, wc := mh.collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"])
if err != nil {
log.Warnln("Couldn't create filtered metrics handler: ", err)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err)))
return
}
reg.MustRegister(wc)
reg.MustRegister(
prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}),
prometheus.NewGoCollector(),

3
go.mod
View File

@@ -5,7 +5,7 @@ go 1.13
require (
github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/Microsoft/hcsshim v0.8.6
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6
github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f
github.com/dimchansky/utfbom v1.1.0
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/leoluk/perflib_exporter v0.1.0
@@ -14,4 +14,5 @@ require (
github.com/prometheus/common v0.2.0
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v2 v2.2.1
)

3
go.sum
View File

@@ -4,6 +4,8 @@ github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f h1:5ZfJxyXo8KyX8DgGXC5B7ILL8y51fci/qYz2B4j8iLY=
github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
@@ -67,4 +69,5 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -14,7 +14,7 @@
<Package Id="*" Manufacturer="prometheus-community" InstallScope="perMachine"
Description="windows_exporter $(var.Version) installer" Compressed="yes" />
<Media Id="1" Cabinet="windows_exporter.cab" EmbedCab="yes"/>
<MajorUpgrade Schedule="afterInstallExecute" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
<Property Id="ENABLED_COLLECTORS" Secure="yes"/>
<SetProperty Id="CollectorsFlag" After="InstallFiles" Sequence="execute" Value="--collectors.enabled [ENABLED_COLLECTORS]">ENABLED_COLLECTORS</SetProperty>
@@ -28,6 +28,9 @@
<Property Id="METRICS_PATH" Secure="yes"/>
<SetProperty Id="MetricsPathFlag" After="InstallFiles" Sequence="execute" Value="--telemetry.path [METRICS_PATH]">METRICS_PATH</SetProperty>
<Property Id="REMOTE_ADDR" Secure="yes" />
<SetProperty Id="RemoteAddressFlag" After="InstallFiles" Sequence="execute" Value="[REMOTE_ADDR]">REMOTE_ADDR</SetProperty>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PlatformProgramFiles)">
@@ -43,10 +46,13 @@
<ComponentGroup Id="Files">
<Component Directory="APPLICATIONROOTDIRECTORY">
<File Id="windows_exporter.exe" Name="windows_exporter.exe" Source="Work\windows_exporter.exe" KeyPath="yes">
<fw:FirewallException Id="MetricsEndpoint" Name="windows_exporter (HTTP [LISTEN_PORT])" Description="windows_exporter HTTP endpoint" Port="[LISTEN_PORT]" Protocol="tcp" Scope="any" IgnoreFailure="yes" />
<fw:FirewallException Id="MetricsEndpoint" Name="windows_exporter (HTTP [LISTEN_PORT])" Description="windows_exporter HTTP endpoint" Port="[LISTEN_PORT]" Protocol="tcp" IgnoreFailure="yes">
<fw:RemoteAddress>[REMOTE_ADDR]</fw:RemoteAddress>
</fw:FirewallException>
</File>
<ServiceInstall Id="InstallExporterService" Name="windows_exporter" DisplayName="windows_exporter" Description="Exports Prometheus metrics from WMI queries" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="--log.format logger:eventlog?name=windows_exporter [CollectorsFlag] [ListenFlag] [MetricsPathFlag] [TextfileDirFlag] [ExtraFlags]">
<util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" RestartServiceDelayInSeconds="5" />
<ServiceInstall Id="InstallExporterService" Name="windows_exporter" DisplayName="windows_exporter" Description="Exports Prometheus metrics about the system" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="--log.format logger:eventlog?name=windows_exporter [CollectorsFlag] [ListenFlag] [MetricsPathFlag] [TextfileDirFlag] [ExtraFlags]">
<util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" RestartServiceDelayInSeconds="60" />
<ServiceDependency Id="wmiApSrv" />
</ServiceInstall>
<ServiceControl Id="ServiceStateControl" Name="windows_exporter" Remove="uninstall" Start="install" Stop="both" />
<util:EventSource Log="Application" Name="windows_exporter" EventMessageFile="%SystemRoot%\System32\EventCreate.exe" />

7
versioninfo.json Normal file
View File

@@ -0,0 +1,7 @@
{
"StringFileInfo": {
"CompanyName": "prometheus-community",
"LegalCopyright": "Copyright 2020 The Prometheus Authors",
"ProductName": "windows_exporter"
}
}