mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-09 22:46:36 +00:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdbb27d0b4 | ||
|
|
2fbd0464dc | ||
|
|
f616589c5f | ||
|
|
f623c0ed89 | ||
|
|
ce5c6eed72 | ||
|
|
d7122930d0 | ||
|
|
96aa2cf095 | ||
|
|
6231eb43e8 | ||
|
|
0880ec6a1a | ||
|
|
8f85475725 | ||
|
|
a4aef9b3c7 | ||
|
|
637fc246af | ||
|
|
6b141a128c | ||
|
|
e97a04ed65 | ||
|
|
cdfe3cf258 | ||
|
|
24fe6813b2 | ||
|
|
7eab1fc411 | ||
|
|
78918f7034 | ||
|
|
59e72c7016 | ||
|
|
49c082d594 | ||
|
|
b7b19aafa0 | ||
|
|
3624ea3bba | ||
|
|
898c17e657 | ||
|
|
f9790f03fb | ||
|
|
3708c85611 | ||
|
|
7a5dc3c6f5 | ||
|
|
8f2f9d83f9 | ||
|
|
c5ea575fb1 | ||
|
|
be39c1126a | ||
|
|
6765935d17 | ||
|
|
51dd61beeb | ||
|
|
a30422c31c | ||
|
|
332a903757 | ||
|
|
6e518f21bb | ||
|
|
3bf94cdaf6 | ||
|
|
94bda6aa79 | ||
|
|
380eff24c9 | ||
|
|
2ebea42de5 | ||
|
|
d39d5230ab | ||
|
|
922c08b85b | ||
|
|
a3867b8dbf | ||
|
|
3b2ef6287c | ||
|
|
8d0d7b31b1 | ||
|
|
24470eb17e | ||
|
|
6bcaee5885 | ||
|
|
ea557547dd | ||
|
|
3c90b96cc6 | ||
|
|
a03f9ef01b | ||
|
|
391335a91f | ||
|
|
6367863c43 | ||
|
|
5c7c0aaa69 | ||
|
|
51f1f884e7 | ||
|
|
7d2511b7ab | ||
|
|
f1384759cb | ||
|
|
3316dc502d | ||
|
|
c9f1e5068a | ||
|
|
86dc495aeb | ||
|
|
418b5b3ca9 | ||
|
|
f2d8418e9f | ||
|
|
0fbdfae85c | ||
|
|
501ac3da4c | ||
|
|
dd6bfbe963 | ||
|
|
a4f815b5fd | ||
|
|
44d419e8fa | ||
|
|
cd8d676443 |
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* @prometheus-community/windows_exporter-reviewers
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,4 +4,5 @@ VERSION
|
||||
*.un~
|
||||
output/
|
||||
.vscode
|
||||
.idea
|
||||
.idea
|
||||
*.syso
|
||||
|
||||
3
CODE_OF_CONDUCT.md
Normal file
3
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## Prometheus Community Code of Conduct
|
||||
|
||||
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
@@ -1,4 +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)
|
||||
62
README.md
62
README.md
@@ -14,8 +14,10 @@ Name | Description | Enabled by default
|
||||
[cpu](docs/collector.cpu.md) | CPU usage | ✓
|
||||
[cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) | ✓
|
||||
[container](docs/collector.container.md) | Container metrics |
|
||||
[dhcp](docs/collector.dhcp.md) | DHCP Server |
|
||||
[dns](docs/collector.dns.md) | DNS Server |
|
||||
[exchange](docs/collector.exchange.md) | Exchange metrics |
|
||||
[fsrmquota](docs/collector.fsrmquota.md) | Microsoft File Server Resource Manager (FSRM) Quotas collector |
|
||||
[hyperv](docs/collector.hyperv.md) | Hyper-V hosts |
|
||||
[iis](docs/collector.iis.md) | IIS sites and applications |
|
||||
[logical_disk](docs/collector.logical_disk.md) | Logical disks, disk I/O | ✓
|
||||
@@ -38,6 +40,7 @@ Name | Description | Enabled by default
|
||||
[service](docs/collector.service.md) | Service state metrics | ✓
|
||||
[system](docs/collector.system.md) | System calls | ✓
|
||||
[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 | ✓
|
||||
@@ -45,6 +48,34 @@ 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.
|
||||
|
||||
Flag | Description | Default value
|
||||
---------|-------------|--------------------
|
||||
`--telemetry.addr` | host:port for exporter. | `:9182`
|
||||
`--telemetry.path` | URL path for surfacing collected metrics. | `/metrics`
|
||||
`--telemetry.max-requests` | Maximum number of concurrent requests. 0 to disable. | `5`
|
||||
`--collectors.enabled` | Comma-separated list of collectors to use. Use `[defaults]` as a placeholder for all the collectors enabled by default." | `[defaults]`
|
||||
`--collectors.print` | If true, print available collectors and exit. |
|
||||
`--scrape.timeout-margin` | Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads. | `0.5`
|
||||
|
||||
## Installation
|
||||
The latest release can be downloaded from the [releases page](https://github.com/prometheus-community/windows_exporter/releases).
|
||||
|
||||
@@ -59,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:
|
||||
@@ -87,7 +119,7 @@ See [open issues](https://github.com/prometheus-community/windows_exporter/issue
|
||||
go get -u github.com/prometheus/promu
|
||||
go get -u github.com/prometheus-community/windows_exporter
|
||||
cd $env:GOPATH/src/github.com/prometheus-community/windows_exporter
|
||||
promu build -v .
|
||||
promu build -v
|
||||
.\windows_exporter.exe
|
||||
|
||||
The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182)
|
||||
@@ -104,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
|
||||
|
||||
|
||||
11
appveyor.yml
11
appveyor.yml
@@ -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") {
|
||||
|
||||
@@ -58,6 +58,10 @@ var (
|
||||
|
||||
func registerCollector(name string, builder collectorBuilder, perfCounterNames ...string) {
|
||||
builders[name] = builder
|
||||
addPerfCounterDependencies(name, perfCounterNames)
|
||||
}
|
||||
|
||||
func addPerfCounterDependencies(name string, perfCounterNames []string) {
|
||||
perfIndicies := make([]string, 0, len(perfCounterNames))
|
||||
for _, cn := range perfCounterNames {
|
||||
perfIndicies = append(perfIndicies, MapCounterToIndex(cn))
|
||||
@@ -109,3 +113,18 @@ func PrepareScrapeContext(collectors []string) (*ScrapeContext, error) {
|
||||
|
||||
return &ScrapeContext{objs}, nil
|
||||
}
|
||||
func boolToFloat(b bool) float64 {
|
||||
if b {
|
||||
return 1.0
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func find(slice []string, val string) bool {
|
||||
for _, item := range slice {
|
||||
if item == val {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ func NewDhcpCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
DeniedDueToNonMatch: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_match_total"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_nonmatch_total"),
|
||||
"Total number of DHCP requests denied, based on non-matches from the Allow list (DeniedDueToNonMatch)",
|
||||
nil,
|
||||
nil,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
187
collector/fsrmquota.go
Normal file
187
collector/fsrmquota.go
Normal file
@@ -0,0 +1,187 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("fsrmquota", newFSRMQuotaCollector)
|
||||
}
|
||||
|
||||
type FSRMQuotaCollector struct {
|
||||
QuotasCount *prometheus.Desc
|
||||
Path *prometheus.Desc
|
||||
PeakUsage *prometheus.Desc
|
||||
Size *prometheus.Desc
|
||||
Usage *prometheus.Desc
|
||||
|
||||
Description *prometheus.Desc
|
||||
Disabled *prometheus.Desc
|
||||
MatchesTemplate *prometheus.Desc
|
||||
SoftLimit *prometheus.Desc
|
||||
Template *prometheus.Desc
|
||||
}
|
||||
|
||||
func newFSRMQuotaCollector() (Collector, error) {
|
||||
const subsystem = "fsrmquota"
|
||||
return &FSRMQuotaCollector{
|
||||
QuotasCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "count"),
|
||||
"Number of Quotas",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PeakUsage: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "peak_usage_bytes"),
|
||||
"The highest amount of disk space usage charged to this quota. (PeakUsage)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Size: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "size_bytes"),
|
||||
"The size of the quota. (Size)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Usage: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "usage_bytes"),
|
||||
"The current amount of disk space usage charged to this quota. (Usage)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Description: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "description"),
|
||||
"Description of the quota (Description)",
|
||||
[]string{"path", "template", "description"},
|
||||
nil,
|
||||
),
|
||||
Disabled: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "disabled"),
|
||||
"If 1, the quota is disabled. The default value is 0. (Disabled)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
SoftLimit: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "softlimit"),
|
||||
"If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Template: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "template"),
|
||||
"Quota template name. (Template)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
MatchesTemplate: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "matchestemplate"),
|
||||
"If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *FSRMQuotaCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting fsrmquota metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MSFT_FSRMQuota docs:
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
|
||||
type MSFT_FSRMQuota struct {
|
||||
Name string
|
||||
|
||||
Path string
|
||||
PeakUsage uint64
|
||||
Size uint64
|
||||
Usage uint64
|
||||
Description string
|
||||
Template string
|
||||
//Threshold string
|
||||
Disabled bool
|
||||
MatchesTemplate bool
|
||||
SoftLimit bool
|
||||
}
|
||||
|
||||
func (c *FSRMQuotaCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []MSFT_FSRMQuota
|
||||
q := queryAll(&dst)
|
||||
|
||||
var count int
|
||||
|
||||
if err := wmi.QueryNamespace(q, &dst, "root/microsoft/windows/fsrm"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, quota := range dst {
|
||||
|
||||
count++
|
||||
path := quota.Path
|
||||
template := quota.Template
|
||||
Description := quota.Description
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PeakUsage,
|
||||
prometheus.GaugeValue,
|
||||
float64(quota.PeakUsage),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Size,
|
||||
prometheus.GaugeValue,
|
||||
float64(quota.Size),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Usage,
|
||||
prometheus.GaugeValue,
|
||||
float64(quota.Usage),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Description,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
path, template, Description,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Disabled,
|
||||
prometheus.GaugeValue,
|
||||
boolToFloat(quota.Disabled),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MatchesTemplate,
|
||||
prometheus.GaugeValue,
|
||||
boolToFloat(quota.MatchesTemplate),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SoftLimit,
|
||||
prometheus.GaugeValue,
|
||||
boolToFloat(quota.SoftLimit),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.QuotasCount,
|
||||
prometheus.GaugeValue,
|
||||
float64(count),
|
||||
)
|
||||
return nil, nil
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
2828
collector/mssql.go
2828
collector/mssql.go
File diff suppressed because it is too large
Load Diff
@@ -45,7 +45,7 @@ func NewserviceCollector() (Collector, error) {
|
||||
Information: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "info"),
|
||||
"A metric with a constant '1' value labeled with service information",
|
||||
[]string{"name", "display_name", "process_id"},
|
||||
[]string{"name", "display_name", "process_id", "run_as"},
|
||||
nil,
|
||||
),
|
||||
State: prometheus.NewDesc(
|
||||
@@ -89,6 +89,7 @@ type Win32_Service struct {
|
||||
State string
|
||||
Status string
|
||||
StartMode string
|
||||
StartName *string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -131,9 +132,13 @@ func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Des
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, service := range dst {
|
||||
pid := strconv.FormatUint(uint64(service.ProcessId), 10)
|
||||
|
||||
runAs := ""
|
||||
if service.StartName != nil {
|
||||
runAs = *service.StartName
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Information,
|
||||
prometheus.GaugeValue,
|
||||
@@ -141,6 +146,7 @@ func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Des
|
||||
strings.ToLower(service.Name),
|
||||
service.DisplayName,
|
||||
pid,
|
||||
runAs,
|
||||
)
|
||||
|
||||
for _, state := range allStates {
|
||||
|
||||
107
collector/tcp.go
107
collector/tcp.go
@@ -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
124
collector/time.go
Normal 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
84
config/config.go
Normal 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
61
config/flatten.go
Normal 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
33
config/flatten_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
--------------|---------------
|
||||
|
||||
52
docs/collector.fsrmquota.md
Normal file
52
docs/collector.fsrmquota.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Microsoft File Server Resource Manager (FSRM) Quotas collector
|
||||
|
||||
The fsrmquota collector exposes metrics about File Server Ressource Manager Quotas. Note that this collector has only been tested against Windows server 2012R2.
|
||||
Other FSRM versions may work but are not tested.
|
||||
|
||||
|||
|
||||
-|-
|
||||
Metric name prefix | `fsrmquota`
|
||||
Data source | wmi
|
||||
Counters | `FSRMQUOTA`
|
||||
Enabled by default? | No
|
||||
|
||||
## Flags
|
||||
|
||||
None
|
||||
|
||||
## Metrics
|
||||
|
||||
Name | Description | Type | Labels
|
||||
-----|-------------|------|-------
|
||||
|
||||
`windows_fsrmquota_count` | Number of Quotas | counter |None
|
||||
`windows_fsrmquota_description` | A string up to 1KB in size. Optional. The default value is an empty string. (Description) | counter |`path`, `template`,`description`
|
||||
`windows_fsrmquota_disabled` | If 1, the quota is disabled. The default value is 0. (Disabled) | counter |`path`, `template`
|
||||
`windows_fsrmquota_matchestemplate` | If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate) | counter |`path`, `template`
|
||||
`windows_fsrmquota_peak_usage_bytes ` | The highest amount of disk space usage charged to this quota. (PeakUsage) | counter |`path`, `template`
|
||||
`windows_fsrmquota_size_bytes` | The size of the quota. If the Template property is not provided then the Size property must be provided (Size) | counter |`path`, `template`
|
||||
`windows_fsrmquota_softlimit` | If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit) | counter |`path`, `template`
|
||||
`windows_fsrmquota_template` | A valid quota template name. Up to 1KB in size. Optional (Template) | counter |`path`, `template`
|
||||
`windows_fsrmquota_usage_bytes` | The current amount of disk space usage charged to this quota. (Usage) | counter |`path`, `template`
|
||||
|
||||
|
||||
### Example metric
|
||||
Show rate of Quotas usage:
|
||||
```
|
||||
rate(windows_fsrmquota_usage_bytes)[1d]
|
||||
```
|
||||
|
||||
## Useful queries
|
||||
|
||||
## Alerting examples
|
||||
**prometheus.rules**
|
||||
```yaml
|
||||
- alert: "HighQuotasUsage"
|
||||
expr: "windows_fsrmquota_usage_bytes{instance="SERVER1.COM:9182"} / windows_fsrmquota_size{instance="SERVER1.COM:9182"} >0.85"
|
||||
for: "10m"
|
||||
labels:
|
||||
severity: "high"
|
||||
annotations:
|
||||
summary: "High Quotas Usage"
|
||||
description: "High use of File Ressource.\n Quotas: {{ $labels.path }}\n Current use : {{ $value }}"
|
||||
```
|
||||
@@ -96,7 +96,18 @@ Name | Description | Type | Labels
|
||||
_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!_
|
||||
Percent of physical CPU resources used per VM (on instance "localhost")
|
||||
```
|
||||
(sum (rate(windows_hyperv_vm_cpu_hypervisor_run_time{instance="localhost"}[1m]))) / ignoring(vm) group_left max (windows_cs_logical_processors{instance="localhost"}) / 100000
|
||||
```
|
||||
Percent of physical CPU resources used by all VMs (on all monitored hosts)
|
||||
```
|
||||
(sum by (instance)(rate(windows_hyperv_vm_cpu_total_run_time{}[1m]))) / max by (instance)(windows_cs_logical_processors{}) / 100000
|
||||
```
|
||||
Percent of physical CPU resources by the hosts themselves (on all monitored hosts)
|
||||
```
|
||||
(sum by (instance)(rate(windows_hyperv_host_cpu_total_run_time{}[1m]))) / sum by (instance)(windows_cs_logical_processors{}) / 100000
|
||||
```
|
||||
|
||||
## Alerting examples
|
||||
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -20,12 +20,12 @@ Example: `--collector.service.services-where="Name='windows_exporter'"`
|
||||
|
||||
Name | Description | Type | Labels
|
||||
-----|-------------|------|-------
|
||||
`windows_service_info` | Contains service information in labels, constant 1 | gauge | name, display_name, process_id
|
||||
`windows_service_info` | Contains service information in labels, constant 1 | gauge | name, display_name, process_id, run_as
|
||||
`windows_service_state` | The state of the service, 1 if the current state, 0 otherwise | gauge | name, state
|
||||
`windows_service_start_mode` | The start mode of the service, 1 if the current start mode, 0 otherwise | gauge | name, start_mode
|
||||
`windows_service_status` | The status of the service, 1 if the current status, 0 otherwise | gauge | name, status
|
||||
|
||||
For the values of the `state`, `start_mode` and `status` labels, see below.
|
||||
For the values of the `state`, `start_mode`, `status` and `run_as` labels, see below.
|
||||
|
||||
### States
|
||||
|
||||
@@ -66,6 +66,13 @@ A service can have any of the following statuses:
|
||||
|
||||
Note that there is some overlap with service state.
|
||||
|
||||
### Run As
|
||||
|
||||
Account name under which a service runs. Depending on the service type, the account name may be in the form of "DomainName\Username" or UPN format ("Username@DomainName").
|
||||
|
||||
It corresponds to the `StartName` attribute of the `Win32_Service` class.
|
||||
`StartName` attribute can be NULL and in such case the label is reported as an empty string. Notice that if the attribute is NULL the service is logged on as the `LocalSystem` account or, for kernel or system-level drive, it runs with a default object name created by the I/O system based on the service name, for example, DWDOM\Admin.
|
||||
|
||||
### Example metric
|
||||
Lists the services that have a 'disabled' start mode.
|
||||
```
|
||||
|
||||
@@ -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
45
docs/collector.time.md
Normal 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
15
docs/example_config.yml
Normal 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
|
||||
78
exporter.go
78
exporter.go
@@ -3,9 +3,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -16,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"
|
||||
@@ -28,6 +31,17 @@ type windowsCollector struct {
|
||||
collectors map[string]collector.Collector
|
||||
}
|
||||
|
||||
// Same struct prometheus uses for their /version endpoint.
|
||||
// Separate copy to avoid pulling all of prometheus as a dependency
|
||||
type prometheusVersion struct {
|
||||
Version string `json:"version"`
|
||||
Revision string `json:"revision"`
|
||||
Branch string `json:"branch"`
|
||||
BuildUser string `json:"buildUser"`
|
||||
BuildDate string `json:"buildDate"`
|
||||
GoVersion string `json:"goVersion"`
|
||||
}
|
||||
|
||||
const (
|
||||
defaultCollectors = "cpu,cs,logical_disk,net,os,service,system,textfile"
|
||||
defaultCollectorsPlaceholder = "[defaults]"
|
||||
@@ -256,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.",
|
||||
@@ -285,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))
|
||||
@@ -327,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,
|
||||
}
|
||||
},
|
||||
@@ -337,6 +383,21 @@ func main() {
|
||||
|
||||
http.HandleFunc(*metricsPath, withConcurrencyLimit(*maxRequests, h.ServeHTTP))
|
||||
http.HandleFunc("/health", healthCheck)
|
||||
http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
|
||||
// we can't use "version" directly as it is a package, and not an object that
|
||||
// can be serialized.
|
||||
err := json.NewEncoder(w).Encode(prometheusVersion{
|
||||
Version: version.Version,
|
||||
Revision: version.Revision,
|
||||
Branch: version.Branch,
|
||||
BuildUser: version.BuildUser,
|
||||
BuildDate: version.BuildDate,
|
||||
GoVersion: version.GoVersion,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("error encoding JSON: %s", err), http.StatusInternalServerError)
|
||||
}
|
||||
})
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte(`<html>
|
||||
<head><title>windows_exporter</title></head>
|
||||
@@ -428,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) {
|
||||
@@ -448,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
3
go.mod
@@ -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
3
go.sum
@@ -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=
|
||||
|
||||
@@ -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
7
versioninfo.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"StringFileInfo": {
|
||||
"CompanyName": "prometheus-community",
|
||||
"LegalCopyright": "Copyright 2020 The Prometheus Authors",
|
||||
"ProductName": "windows_exporter"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user