mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-24 05:36:36 +00:00
Compare commits
13 Commits
v0.30.0-be
...
v0.30.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5ff75ebc2 | ||
|
|
71e5e5ec5f | ||
|
|
40ff2f2e57 | ||
|
|
9db94aa66a | ||
|
|
a359acb3d1 | ||
|
|
487de0c20b | ||
|
|
aaa4ce07f6 | ||
|
|
a2db81494e | ||
|
|
64bf0a6551 | ||
|
|
40b6f53479 | ||
|
|
ca04ad8fd2 | ||
|
|
fd55ac4894 | ||
|
|
c8eeb595c0 |
@@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="all" type="GoApplicationRunConfiguration" factoryName="Go Application" folderName="run">
|
<configuration default="false" name="all" type="GoApplicationRunConfiguration" factoryName="Go Application" folderName="run">
|
||||||
<module name="windows_exporter" />
|
<module name="windows_exporter" />
|
||||||
<working_directory value="$PROJECT_DIR$" />
|
<working_directory value="$PROJECT_DIR$" />
|
||||||
<parameters value="--web.listen-address=127.0.0.1:9182 --log.level=debug --collectors.enabled=ad,adcs,adfs,cache,container,cpu,cpu_info,cs,dfsr,dhcp,diskdrive,dns,exchange,filetime,fsrmquota,hyperv,iis,license,logical_disk,logon,memory,mscluster,msmq,mssql,net,netframework,nps,os,pagefile,perfdata,physical_disk,printer,process,remote_fx,scheduled_task,service,smb,smbclient,smtp,system,tcp,terminal_services,textfile,thermalzone,time,udp,update,vmware" />
|
<parameters value="--web.listen-address=127.0.0.1:9182 --log.level=info --collectors.enabled=ad,adcs,adfs,cache,container,cpu,cpu_info,cs,dfsr,dhcp,diskdrive,dns,exchange,filetime,fsrmquota,hyperv,iis,license,logical_disk,logon,memory,mscluster,msmq,mssql,net,netframework,nps,os,pagefile,performancecounter,physical_disk,printer,process,remote_fx,scheduled_task,service,smb,smbclient,smtp,system,tcp,terminal_services,thermalzone,time,udp,update,vmware --debug.enabled" />
|
||||||
<sudo value="true" />
|
<sudo value="true" />
|
||||||
<kind value="PACKAGE" />
|
<kind value="PACKAGE" />
|
||||||
<package value="github.com/prometheus-community/windows_exporter/cmd/windows_exporter" />
|
<package value="github.com/prometheus-community/windows_exporter/cmd/windows_exporter" />
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -42,7 +42,7 @@ Name | Description | Enabled by default
|
|||||||
[net](docs/collector.net.md) | Network interface I/O | ✓
|
[net](docs/collector.net.md) | Network interface I/O | ✓
|
||||||
[os](docs/collector.os.md) | OS metrics (memory, processes, users) | ✓
|
[os](docs/collector.os.md) | OS metrics (memory, processes, users) | ✓
|
||||||
[pagefile](docs/collector.pagefile.md) | pagefile metrics |
|
[pagefile](docs/collector.pagefile.md) | pagefile metrics |
|
||||||
[perfdata](docs/collector.perfdata.md) | Custom perfdata metrics |
|
[performancecounter](docs/collector.performancecounter.md) | Custom performance counter metrics |
|
||||||
[physical_disk](docs/collector.physical_disk.md) | physical disk metrics | ✓
|
[physical_disk](docs/collector.physical_disk.md) | physical disk metrics | ✓
|
||||||
[printer](docs/collector.printer.md) | Printer metrics |
|
[printer](docs/collector.printer.md) | Printer metrics |
|
||||||
[process](docs/collector.process.md) | Per-process metrics |
|
[process](docs/collector.process.md) | Per-process metrics |
|
||||||
@@ -199,6 +199,14 @@ Windows Server 2012 and 2012R2 are supported as best-effort only, but not guaran
|
|||||||
|
|
||||||
The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182)
|
The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182)
|
||||||
|
|
||||||
|
### HTTP Endpoints
|
||||||
|
|
||||||
|
windows_exporter provides the following HTTP endpoints:
|
||||||
|
|
||||||
|
* `/metrics`: Exposes metrics in the [Prometheus text format](https://prometheus.io/docs/instrumenting/exposition_formats/).
|
||||||
|
* `/health`: Returns 200 OK when the exporter is running.
|
||||||
|
* `/debug/pprof/`: Exposes the [pprof](https://golang.org/pkg/net/http/pprof/) endpoints. Only, if `--debug.enabled` is set.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Enable only service collector and specify a custom query
|
### Enable only service collector and specify a custom query
|
||||||
|
|||||||
@@ -87,10 +87,6 @@ func run() int {
|
|||||||
"web.disable-exporter-metrics",
|
"web.disable-exporter-metrics",
|
||||||
"Exclude metrics about the exporter itself (promhttp_*, process_*, go_*).",
|
"Exclude metrics about the exporter itself (promhttp_*, process_*, go_*).",
|
||||||
).Bool()
|
).Bool()
|
||||||
maxRequests = app.Flag(
|
|
||||||
"telemetry.max-requests",
|
|
||||||
"Maximum number of concurrent requests. 0 to disable.",
|
|
||||||
).Default("5").Int()
|
|
||||||
enabledCollectors = app.Flag(
|
enabledCollectors = app.Flag(
|
||||||
"collectors.enabled",
|
"collectors.enabled",
|
||||||
"Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default.").
|
"Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default.").
|
||||||
@@ -109,7 +105,14 @@ func run() int {
|
|||||||
).Default("normal").String()
|
).Default("normal").String()
|
||||||
)
|
)
|
||||||
|
|
||||||
logConfig := &log.Config{}
|
logFile := &log.AllowedFile{}
|
||||||
|
|
||||||
|
_ = logFile.Set("stdout")
|
||||||
|
if windowsservice.IsService {
|
||||||
|
_ = logFile.Set("eventlog")
|
||||||
|
}
|
||||||
|
|
||||||
|
logConfig := &log.Config{File: logFile}
|
||||||
flag.AddFlags(app, logConfig)
|
flag.AddFlags(app, logConfig)
|
||||||
|
|
||||||
app.Version(version.Print("windows_exporter"))
|
app.Version(version.Print("windows_exporter"))
|
||||||
@@ -220,7 +223,6 @@ func run() int {
|
|||||||
mux.Handle("GET "+*metricsPath, httphandler.New(logger, collectors, &httphandler.Options{
|
mux.Handle("GET "+*metricsPath, httphandler.New(logger, collectors, &httphandler.Options{
|
||||||
DisableExporterMetrics: *disableExporterMetrics,
|
DisableExporterMetrics: *disableExporterMetrics,
|
||||||
TimeoutMargin: *timeoutMargin,
|
TimeoutMargin: *timeoutMargin,
|
||||||
MaxRequests: *maxRequests,
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if *debugEnabled {
|
if *debugEnabled {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ This directory contains documentation of the collectors in the windows_exporter,
|
|||||||
- [`fsrmquota`](collector.fsrmquota.md)
|
- [`fsrmquota`](collector.fsrmquota.md)
|
||||||
- [`hyperv`](collector.hyperv.md)
|
- [`hyperv`](collector.hyperv.md)
|
||||||
- [`iis`](collector.iis.md)
|
- [`iis`](collector.iis.md)
|
||||||
|
- [`license`](collector.license.md)
|
||||||
- [`logical_disk`](collector.logical_disk.md)
|
- [`logical_disk`](collector.logical_disk.md)
|
||||||
- [`logon`](collector.logon.md)
|
- [`logon`](collector.logon.md)
|
||||||
- [`memory`](collector.memory.md)
|
- [`memory`](collector.memory.md)
|
||||||
@@ -28,12 +29,16 @@ This directory contains documentation of the collectors in the windows_exporter,
|
|||||||
- [`netframework`](collector.netframework.md)
|
- [`netframework`](collector.netframework.md)
|
||||||
- [`nps`](collector.nps.md)
|
- [`nps`](collector.nps.md)
|
||||||
- [`os`](collector.os.md)
|
- [`os`](collector.os.md)
|
||||||
|
- [`pagefile`](collector.pagefile.md)
|
||||||
|
- [`performancecounter`](collector.performancecounter.md)
|
||||||
- [`physical_disk`](collector.physical_disk.md)
|
- [`physical_disk`](collector.physical_disk.md)
|
||||||
|
- [`printer`](collector.printer.md)
|
||||||
- [`process`](collector.process.md)
|
- [`process`](collector.process.md)
|
||||||
- [`remote_fx`](collector.remote_fx.md)
|
- [`remote_fx`](collector.remote_fx.md)
|
||||||
- [`scheduled_task`](collector.scheduled_task.md)
|
- [`scheduled_task`](collector.scheduled_task.md)
|
||||||
- [`service`](collector.service.md)
|
- [`service`](collector.service.md)
|
||||||
- [`smb`](collector.smb.md)
|
- [`smb`](collector.smb.md)
|
||||||
|
- [`smbclient`](collector.smbclient.md)
|
||||||
- [`smtp`](collector.smtp.md)
|
- [`smtp`](collector.smtp.md)
|
||||||
- [`system`](collector.system.md)
|
- [`system`](collector.system.md)
|
||||||
- [`tcp`](collector.tcp.md)
|
- [`tcp`](collector.tcp.md)
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
# Perfdata collector
|
|
||||||
|
|
||||||
The perfdata collector exposes any configured metric.
|
|
||||||
|
|
||||||
| | |
|
|
||||||
|---------------------|-------------------------|
|
|
||||||
| Metric name prefix | `perfdata` |
|
|
||||||
| Data source | Performance Data Helper |
|
|
||||||
| Enabled by default? | No |
|
|
||||||
|
|
||||||
## Flags
|
|
||||||
|
|
||||||
|
|
||||||
### `--collector.perfdata.objects`
|
|
||||||
|
|
||||||
Objects is a list of objects to collect metrics from. The value takes the form of a JSON array of strings. YAML is also supported.
|
|
||||||
|
|
||||||
The collector supports only english named counter. Localized counter-names are not supported.
|
|
||||||
|
|
||||||
#### Schema
|
|
||||||
|
|
||||||
YAML:
|
|
||||||
```yaml
|
|
||||||
- object: "Processor Information"
|
|
||||||
instances: ["*"]
|
|
||||||
instance_label: "core"
|
|
||||||
counters:
|
|
||||||
"% Processor Time": {}
|
|
||||||
- object: "Memory"
|
|
||||||
counters:
|
|
||||||
"Cache Faults/sec":
|
|
||||||
type: "counter"
|
|
||||||
```
|
|
||||||
|
|
||||||
JSON:
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{"object":"Processor Information","instance_label": "core","instances":["*"],"counters": {"% Processor Time": {}}},
|
|
||||||
{"object":"Memory","counters": {"Cache Faults/sec": {"type": "counter"}}}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### name
|
|
||||||
|
|
||||||
ObjectName is the Object to query for, like Processor, DirectoryServices, LogicalDisk or similar.
|
|
||||||
|
|
||||||
The collector supports only english named counter. Localized counter-names are not supported.
|
|
||||||
|
|
||||||
#### instances
|
|
||||||
|
|
||||||
The instances key (this is an array) declares the instances of a counter you would like returned, it can be one or more values.
|
|
||||||
|
|
||||||
Example: Instances = `["C:","D:","E:"]`
|
|
||||||
|
|
||||||
This will return only for the instances C:, D: and E: where relevant. To get all instances of a Counter, use `["*"]` only.
|
|
||||||
|
|
||||||
Some Objects like `Memory` do not have instances to select from at all. In this case, the `instances` key can be omitted.
|
|
||||||
|
|
||||||
#### counters
|
|
||||||
|
|
||||||
The Counters key (this is an object) declares the counters of the ObjectName you would like returned, it can also be one or more values.
|
|
||||||
|
|
||||||
Example: Counters = `{"% Idle Time": {}, "% Disk Read Time": {}, "% Disk Write Time": {}}`
|
|
||||||
|
|
||||||
This must be specified for every counter you want the results. Wildcards are not supported.
|
|
||||||
|
|
||||||
#### counters Sub-Schema
|
|
||||||
|
|
||||||
##### type
|
|
||||||
|
|
||||||
This key is optional. It indicates the type of the counter. The value can be `counter` or `gauge`.
|
|
||||||
If not specified, the windows_exporter will try to determine the type based on the counter type.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```
|
|
||||||
# HELP windows_perfdata_memory_cache_faults_sec
|
|
||||||
# TYPE windows_perfdata_memory_cache_faults_sec counter
|
|
||||||
windows_perfdata_memory_cache_faults_sec 2.369977e+07
|
|
||||||
# HELP windows_perfdata_processor_information__processor_time
|
|
||||||
# TYPE windows_perfdata_processor_information__processor_time gauge
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,0"} 1.7259640625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,1"} 1.7576796875e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,10"} 2.2704234375e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,11"} 2.3069296875e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,12"} 2.3302265625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,13"} 2.32851875e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,14"} 2.3282421875e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,15"} 2.3271234375e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,16"} 2.329590625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,17"} 2.32800625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,18"} 2.3194359375e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,19"} 2.32380625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,2"} 1.954765625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,20"} 2.3259765625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,21"} 2.3268515625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,22"} 2.3301765625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,23"} 2.3264328125e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,3"} 1.94745625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,4"} 2.2011453125e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,5"} 2.27244375e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,6"} 2.25501875e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,7"} 2.2995265625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,8"} 2.2929890625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,9"} 2.313540625e+11
|
|
||||||
windows_perfdata_processor_information__processor_time{instance="0,_Total"} 2.23009459635e+11
|
|
||||||
```
|
|
||||||
|
|
||||||
## Metrics
|
|
||||||
|
|
||||||
The perfdata collector returns metrics based on the user configuration.
|
|
||||||
The metrics are named based on the object name and the counter name.
|
|
||||||
The instance name is added as a label to the metric.
|
|
||||||
193
docs/collector.performancecounter.md
Normal file
193
docs/collector.performancecounter.md
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
# performancecounter collector
|
||||||
|
|
||||||
|
The performancecounter collector exposes any configured metric.
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---------------------|-------------------------|
|
||||||
|
| Metric name prefix | `performancecounter` |
|
||||||
|
| Data source | Performance Data Helper |
|
||||||
|
| Enabled by default? | No |
|
||||||
|
|
||||||
|
## Flags
|
||||||
|
|
||||||
|
|
||||||
|
### `--collector.performancecounter.objects`
|
||||||
|
|
||||||
|
Objects is a list of objects to collect metrics from. The value takes the form of a JSON array of strings. YAML is also supported.
|
||||||
|
|
||||||
|
The collector supports only english named counter. Localized counter-names are not supported.
|
||||||
|
|
||||||
|
#### Schema
|
||||||
|
|
||||||
|
YAML:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to expand YAML schema</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- object: "Processor Information"
|
||||||
|
instances: ["*"]
|
||||||
|
instance_label: "core"
|
||||||
|
counters:
|
||||||
|
- name: "% Processor Time"
|
||||||
|
metric: windows_performancecounter_processor_information_processor_time # optional
|
||||||
|
labels:
|
||||||
|
state: active
|
||||||
|
- name: "% Idle Time"
|
||||||
|
metric: windows_performancecounter_processor_information_processor_time # optional
|
||||||
|
labels:
|
||||||
|
state: idle
|
||||||
|
- object: "Memory"
|
||||||
|
counters:
|
||||||
|
- name: "Cache Faults/sec"
|
||||||
|
type: "counter" # optional
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to expand JSON schema</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"object": "Processor Information",
|
||||||
|
"instances": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"instance_label": "core",
|
||||||
|
"counters": [
|
||||||
|
{
|
||||||
|
"name": "% Processor Time",
|
||||||
|
"metric": "windows_performancecounter_processor_information_processor_time",
|
||||||
|
"labels": {
|
||||||
|
"state": "active"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "% Idle Time",
|
||||||
|
"metric": "windows_performancecounter_processor_information_processor_time",
|
||||||
|
"labels": {
|
||||||
|
"state": "idle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "Memory",
|
||||||
|
"counters": [
|
||||||
|
{
|
||||||
|
"name": "Cache Faults/sec",
|
||||||
|
"type": "counter"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### name
|
||||||
|
|
||||||
|
ObjectName is the Object to query for, like Processor, DirectoryServices, LogicalDisk or similar.
|
||||||
|
|
||||||
|
The collector supports only english named counter. Localized counter-names are not supported.
|
||||||
|
|
||||||
|
#### instances
|
||||||
|
|
||||||
|
The instances key (this is an array) declares the instances of a counter you would like returned, it can be one or more values.
|
||||||
|
|
||||||
|
Example: Instances = `["C:","D:","E:"]`
|
||||||
|
|
||||||
|
This will return only for the instances C:, D: and E: where relevant. To get all instances of a Counter, use `["*"]` only.
|
||||||
|
|
||||||
|
Some Objects like `Memory` do not have instances to select from at all. In this case, the `instances` key can be omitted.
|
||||||
|
|
||||||
|
#### counters
|
||||||
|
|
||||||
|
List of counters to collect from the object. See the counters sub-schema for more information.
|
||||||
|
|
||||||
|
#### counters Sub-Schema
|
||||||
|
|
||||||
|
##### name
|
||||||
|
|
||||||
|
The name of the counter to collect.
|
||||||
|
|
||||||
|
##### metric
|
||||||
|
|
||||||
|
It indicates the name of the metric to be exposed. If not specified, the metric name will be generated based on the object name and the counter name.
|
||||||
|
|
||||||
|
This key is optional.
|
||||||
|
|
||||||
|
##### type
|
||||||
|
|
||||||
|
It indicates the type of the counter. The value can be `counter` or `gauge`.
|
||||||
|
If not specified, the windows_exporter will try to determine the type based on the counter type.
|
||||||
|
|
||||||
|
This key is optional.
|
||||||
|
|
||||||
|
##### labels
|
||||||
|
|
||||||
|
Labels is a map of key-value pairs that will be added as labels to the metric.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```
|
||||||
|
# HELP windows_performancecounter_memory_cache_faults_sec
|
||||||
|
# TYPE windows_performancecounter_memory_cache_faults_sec counter
|
||||||
|
windows_performancecounter_memory_cache_faults_sec 7.028097e+06
|
||||||
|
# HELP windows_performancecounter_processor_information_processor_time
|
||||||
|
# TYPE windows_performancecounter_processor_information_processor_time counter
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,0",state="active"} 8.3809375e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,0",state="idle"} 8380.9375
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,1",state="active"} 8.2868125e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,1",state="idle"} 8286.8125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,10",state="active"} 9.720046875e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,10",state="idle"} 9720.046875
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,11",state="active"} 9.994921875e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,11",state="idle"} 9994.921875
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,12",state="active"} 1.014403125e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,12",state="idle"} 10144.03125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,13",state="active"} 1.0155453125e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,13",state="idle"} 10155.453125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,14",state="active"} 1.01290625e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,14",state="idle"} 10129.0625
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,15",state="active"} 1.0134890625e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,15",state="idle"} 10134.890625
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,16",state="active"} 1.01405625e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,16",state="idle"} 10140.5625
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,17",state="active"} 1.0153421875e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,17",state="idle"} 10153.421875
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,18",state="active"} 1.0086390625e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,18",state="idle"} 10086.390625
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,19",state="active"} 1.0123453125e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,19",state="idle"} 10123.453125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,2",state="active"} 8.3548125e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,2",state="idle"} 8354.8125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,20",state="active"} 1.011703125e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,20",state="idle"} 10117.03125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,21",state="active"} 1.0140984375e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,21",state="idle"} 10140.984375
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,22",state="active"} 1.014615625e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,22",state="idle"} 10146.15625
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,23",state="active"} 1.0145125e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,23",state="idle"} 10145.125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,3",state="active"} 8.488953125e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,3",state="idle"} 8488.953125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,4",state="active"} 9.338234375e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,4",state="idle"} 9338.234375
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,5",state="active"} 9.776453125e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,5",state="idle"} 9776.453125
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,6",state="active"} 9.736265625e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,6",state="idle"} 9736.265625
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,7",state="active"} 9.959375e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,7",state="idle"} 9959.375
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,8",state="active"} 9.939421875e+10
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,8",state="idle"} 9939.421875
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,9",state="active"} 1.0059484375e+11
|
||||||
|
windows_performancecounter_processor_information_processor_time{core="0,9",state="idle"} 10059.484375
|
||||||
|
```
|
||||||
|
|
||||||
|
## Metrics
|
||||||
|
|
||||||
|
The perfdata collector returns metrics based on the user configuration.
|
||||||
|
The metrics are named based on the object name and the counter name.
|
||||||
|
The instance name is added as a label to the metric.
|
||||||
@@ -14,16 +14,16 @@ None
|
|||||||
|
|
||||||
## Metrics
|
## Metrics
|
||||||
|
|
||||||
| Name | Description | Type | Labels |
|
| Name | Description | Type | Labels |
|
||||||
|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|
|
|----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|
|
||||||
| `windows_system_context_switches_total` | Total number of [context switches](https://en.wikipedia.org/wiki/Context_switch) | counter | None |
|
| `windows_system_boot_time_timestamp_seconds` | Unix timestamp of last system boot | gauge | None |
|
||||||
| `windows_system_exception_dispatches_total` | Total exceptions dispatched by the system | counter | None |
|
| `windows_system_context_switches_total` | Total number of [context switches](https://en.wikipedia.org/wiki/Context_switch) | counter | None |
|
||||||
| `windows_system_processes` | Number of process contexts currently loaded or running on the operating system | gauge | None |
|
| `windows_system_exception_dispatches_total` | Total exceptions dispatched by the system | counter | None |
|
||||||
| `windows_system_process_limit` | The size of the user-mode portion of the virtual address space of the calling process, in bytes. This value depends on the type of process, the type of processor, and the configuration of the operating system. | gauge | None |
|
| `windows_system_processes` | Number of process contexts currently loaded or running on the operating system | gauge | None |
|
||||||
| `windows_system_processor_queue_length` | Number of threads in the processor queue. There is a single queue for processor time even on computers with multiple processors. | gauge | None |
|
| `windows_system_process_limit` | The size of the user-mode portion of the virtual address space of the calling process, in bytes. This value depends on the type of process, the type of processor, and the configuration of the operating system. | gauge | None |
|
||||||
| `windows_system_system_calls_total` | Total combined calls to Windows NT system service routines by all processes running on the computer | counter | None |
|
| `windows_system_processor_queue_length` | Number of threads in the processor queue. There is a single queue for processor time even on computers with multiple processors. | gauge | None |
|
||||||
| `windows_system_system_up_time` | Time of last boot of system | gauge | None |
|
| `windows_system_system_calls_total` | Total combined calls to Windows NT system service routines by all processes running on the computer | counter | None |
|
||||||
| `windows_system_threads` | Number of Windows system [threads](https://en.wikipedia.org/wiki/Thread_(computing)) | gauge | None |
|
| `windows_system_threads` | Number of Windows system [threads](https://en.wikipedia.org/wiki/Thread_(computing)) | gauge | None |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ windows_system_processes{instance="localhost"}
|
|||||||
## Useful queries
|
## Useful queries
|
||||||
Find hosts that have rebooted in the last 24 hours
|
Find hosts that have rebooted in the last 24 hours
|
||||||
```
|
```
|
||||||
time() - windows_system_system_up_time < 86400
|
time() - windows_system_boot_time_timestamp_seconds < 86400
|
||||||
```
|
```
|
||||||
|
|
||||||
## Alerting examples
|
## Alerting examples
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
<Wix xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"
|
||||||
xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
|
xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<DirectoryRef Id="APPLICATIONFOLDER">
|
<DirectoryRef Id="APPLICATIONFOLDER">
|
||||||
<Component Transitive="yes">
|
<Component Transitive="yes">
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
Start="auto"
|
Start="auto"
|
||||||
Type="ownProcess"
|
Type="ownProcess"
|
||||||
Vital="yes"
|
Vital="yes"
|
||||||
Arguments="--log.file eventlog [ConfigFileFlag] [CollectorsFlag] [ListenFlag] [MetricsPathFlag] [TextfileDirsFlag] [ExtraFlags]">
|
Arguments="[ConfigFileFlag] [CollectorsFlag] [ListenFlag] [MetricsPathFlag] [TextfileDirsFlag] [ExtraFlags]">
|
||||||
<util:ServiceConfig
|
<util:ServiceConfig
|
||||||
ResetPeriodInDays="1"
|
ResetPeriodInDays="1"
|
||||||
FirstFailureActionType="restart"
|
FirstFailureActionType="restart"
|
||||||
|
|||||||
@@ -24,9 +24,9 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
<Wix xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall"
|
||||||
xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall"
|
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui"
|
||||||
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
|
xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||||
<Package UpgradeCode="66a6eb5b-1fc2-4b14-a362-5ceec6413308" Name="$(var.ProductName)" Version="$(var.Version)"
|
<Package UpgradeCode="66a6eb5b-1fc2-4b14-a362-5ceec6413308" Name="$(var.ProductName)" Version="$(var.Version)"
|
||||||
Manufacturer="prometheus-community" Language="1033" Scope="perMachine">
|
Manufacturer="prometheus-community" Language="1033" Scope="perMachine">
|
||||||
<SummaryInformation Manufacturer="prometheus-community" Description="$(var.ProductName) $(var.Version) installer" />
|
<SummaryInformation Manufacturer="prometheus-community" Description="$(var.ProductName) $(var.Version) installer" />
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
type collectorHypervisorRootVirtualProcessor struct {
|
type collectorHypervisorRootVirtualProcessor struct {
|
||||||
perfDataCollectorHypervisorRootVirtualProcessor *perfdata.Collector
|
perfDataCollectorHypervisorRootVirtualProcessor *perfdata.Collector
|
||||||
|
|
||||||
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Idle Time
|
|
||||||
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time
|
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Guest Run Time
|
||||||
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Hypervisor Run Time
|
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Hypervisor Run Time
|
||||||
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Remote Run Time
|
// \Hyper-V Hypervisor Root Virtual Processor(*)\% Remote Run Time
|
||||||
@@ -39,7 +38,6 @@ type collectorHypervisorRootVirtualProcessor struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
hypervisorRootVirtualProcessorGuestIdleTimePercent = "% Guest Idle Time"
|
|
||||||
hypervisorRootVirtualProcessorGuestRunTimePercent = "% Guest Run Time"
|
hypervisorRootVirtualProcessorGuestRunTimePercent = "% Guest Run Time"
|
||||||
hypervisorRootVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time"
|
hypervisorRootVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time"
|
||||||
hypervisorRootVirtualProcessorTotalRunTimePercent = "% Total Run Time"
|
hypervisorRootVirtualProcessorTotalRunTimePercent = "% Total Run Time"
|
||||||
@@ -51,7 +49,6 @@ func (c *Collector) buildHypervisorRootVirtualProcessor() error {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
c.perfDataCollectorHypervisorRootVirtualProcessor, err = perfdata.NewCollector("Hyper-V Hypervisor Root Virtual Processor", perfdata.InstancesAll, []string{
|
c.perfDataCollectorHypervisorRootVirtualProcessor, err = perfdata.NewCollector("Hyper-V Hypervisor Root Virtual Processor", perfdata.InstancesAll, []string{
|
||||||
hypervisorRootVirtualProcessorGuestIdleTimePercent,
|
|
||||||
hypervisorRootVirtualProcessorGuestRunTimePercent,
|
hypervisorRootVirtualProcessorGuestRunTimePercent,
|
||||||
hypervisorRootVirtualProcessorHypervisorRunTimePercent,
|
hypervisorRootVirtualProcessorHypervisorRunTimePercent,
|
||||||
hypervisorRootVirtualProcessorTotalRunTimePercent,
|
hypervisorRootVirtualProcessorTotalRunTimePercent,
|
||||||
@@ -115,13 +112,6 @@ func (c *Collector) collectHypervisorRootVirtualProcessor(ch chan<- prometheus.M
|
|||||||
coreId, "hypervisor",
|
coreId, "hypervisor",
|
||||||
)
|
)
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
c.hypervisorRootVirtualProcessorTimeTotal,
|
|
||||||
prometheus.CounterValue,
|
|
||||||
coreData[hypervisorRootVirtualProcessorGuestIdleTimePercent].FirstValue,
|
|
||||||
coreId, "guest_idle",
|
|
||||||
)
|
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.hypervisorRootVirtualProcessorTimeTotal,
|
c.hypervisorRootVirtualProcessorTimeTotal,
|
||||||
prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
type collectorHypervisorVirtualProcessor struct {
|
type collectorHypervisorVirtualProcessor struct {
|
||||||
perfDataCollectorHypervisorVirtualProcessor *perfdata.Collector
|
perfDataCollectorHypervisorVirtualProcessor *perfdata.Collector
|
||||||
|
|
||||||
// \Hyper-V Hypervisor Virtual Processor(*)\% Guest Idle Time
|
|
||||||
// \Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time
|
// \Hyper-V Hypervisor Virtual Processor(*)\% Guest Run Time
|
||||||
// \Hyper-V Hypervisor Virtual Processor(*)\% Hypervisor Run Time
|
// \Hyper-V Hypervisor Virtual Processor(*)\% Hypervisor Run Time
|
||||||
// \Hyper-V Hypervisor Virtual Processor(*)\% Remote Run Time
|
// \Hyper-V Hypervisor Virtual Processor(*)\% Remote Run Time
|
||||||
@@ -38,7 +37,6 @@ type collectorHypervisorVirtualProcessor struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
hypervisorVirtualProcessorGuestRunTimePercent = "% Guest Run Time"
|
|
||||||
hypervisorVirtualProcessorGuestIdleTimePercent = "% Guest Idle Time"
|
hypervisorVirtualProcessorGuestIdleTimePercent = "% Guest Idle Time"
|
||||||
hypervisorVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time"
|
hypervisorVirtualProcessorHypervisorRunTimePercent = "% Hypervisor Run Time"
|
||||||
hypervisorVirtualProcessorTotalRunTimePercent = "% Total Run Time"
|
hypervisorVirtualProcessorTotalRunTimePercent = "% Total Run Time"
|
||||||
@@ -50,7 +48,6 @@ func (c *Collector) buildHypervisorVirtualProcessor() error {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
c.perfDataCollectorHypervisorVirtualProcessor, err = perfdata.NewCollector("Hyper-V Hypervisor Virtual Processor", perfdata.InstancesAll, []string{
|
c.perfDataCollectorHypervisorVirtualProcessor, err = perfdata.NewCollector("Hyper-V Hypervisor Virtual Processor", perfdata.InstancesAll, []string{
|
||||||
hypervisorVirtualProcessorGuestRunTimePercent,
|
|
||||||
hypervisorVirtualProcessorGuestIdleTimePercent,
|
hypervisorVirtualProcessorGuestIdleTimePercent,
|
||||||
hypervisorVirtualProcessorHypervisorRunTimePercent,
|
hypervisorVirtualProcessorHypervisorRunTimePercent,
|
||||||
hypervisorVirtualProcessorTotalRunTimePercent,
|
hypervisorVirtualProcessorTotalRunTimePercent,
|
||||||
@@ -104,13 +101,6 @@ func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metri
|
|||||||
vmName := parts[0]
|
vmName := parts[0]
|
||||||
coreId := coreParts[2]
|
coreId := coreParts[2]
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
c.hypervisorVirtualProcessorTimeTotal,
|
|
||||||
prometheus.CounterValue,
|
|
||||||
coreData[hypervisorVirtualProcessorGuestRunTimePercent].FirstValue,
|
|
||||||
vmName, coreId, "guest_run",
|
|
||||||
)
|
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.hypervisorVirtualProcessorTimeTotal,
|
c.hypervisorVirtualProcessorTimeTotal,
|
||||||
prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ func (c *Collector) buildAppPoolWAS() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectAppPoolWAS(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectAppPoolWAS(ch chan<- prometheus.Metric) error {
|
||||||
perfData, err := c.perfDataCollectorWebService.Collect()
|
perfData, err := c.perfDataCollectorAppPoolWAS.Collect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err)
|
return fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ const (
|
|||||||
func (c *Collector) buildWebServiceCache() error {
|
func (c *Collector) buildWebServiceCache() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
c.perfDataCollectorWebService, err = perfdata.NewCollector("Web Service Cache", perfdata.InstancesAll, []string{
|
c.serviceCachePerfDataCollector, err = perfdata.NewCollector("Web Service Cache", perfdata.InstancesAll, []string{
|
||||||
serviceCacheActiveFlushedEntries,
|
serviceCacheActiveFlushedEntries,
|
||||||
serviceCacheCurrentFileCacheMemoryUsage,
|
serviceCacheCurrentFileCacheMemoryUsage,
|
||||||
serviceCacheMaximumFileCacheMemoryUsage,
|
serviceCacheMaximumFileCacheMemoryUsage,
|
||||||
@@ -314,7 +314,7 @@ func (c *Collector) buildWebServiceCache() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectWebServiceCache(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectWebServiceCache(ch chan<- prometheus.Metric) error {
|
||||||
perfData, err := c.perfDataCollectorWebService.Collect()
|
perfData, err := c.serviceCachePerfDataCollector.Collect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to collect Web Service Cache metrics: %w", err)
|
return fmt.Errorf("failed to collect Web Service Cache metrics: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package logical_disk
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -312,12 +313,17 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
|||||||
return fmt.Errorf("failed to collect LogicalDisk metrics: %w", err)
|
return fmt.Errorf("failed to collect LogicalDisk metrics: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volumes, err := getAllMountedVolumes()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get volumes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
for name, volume := range perfData {
|
for name, volume := range perfData {
|
||||||
if c.config.VolumeExclude.MatchString(name) || !c.config.VolumeInclude.MatchString(name) {
|
if c.config.VolumeExclude.MatchString(name) || !c.config.VolumeInclude.MatchString(name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err = getVolumeInfo(name)
|
info, err = getVolumeInfo(volumes, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Warn("failed to get volume information for "+name,
|
c.logger.Warn("failed to get volume information for "+name,
|
||||||
slog.Any("err", err),
|
slog.Any("err", err),
|
||||||
@@ -477,34 +483,15 @@ func getDriveType(driveType uint32) string {
|
|||||||
const diskExtentSize = 24
|
const diskExtentSize = 24
|
||||||
|
|
||||||
// getDiskIDByVolume returns the disk ID for a given volume.
|
// getDiskIDByVolume returns the disk ID for a given volume.
|
||||||
func getVolumeInfo(rootDrive string) (volumeInfo, error) {
|
func getVolumeInfo(volumes map[string]string, rootDrive string) (volumeInfo, error) {
|
||||||
volumePath := rootDrive
|
volumePath := rootDrive
|
||||||
|
|
||||||
// If rootDrive is a NTFS directory, convert it to a volume GUID.
|
// If rootDrive is a NTFS directory, convert it to a volume GUID.
|
||||||
if strings.Contains(volumePath, `\`) {
|
if volumeGUID, ok := volumes[rootDrive]; ok {
|
||||||
// GetVolumeNameForVolumeMountPoint expects a trailing backslash.
|
|
||||||
volumePath += `\`
|
|
||||||
|
|
||||||
volumePathName, err := windows.UTF16PtrFromString(volumePath)
|
|
||||||
if err != nil {
|
|
||||||
return volumeInfo{}, fmt.Errorf("could not convert rootDrive to volume path %s: %w", volumePath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
volumeGUIDPtr := make([]uint16, 50)
|
|
||||||
if err := windows.GetVolumeNameForVolumeMountPoint(volumePathName, &volumeGUIDPtr[0], uint32(len(volumeGUIDPtr))); err != nil {
|
|
||||||
return volumeInfo{}, fmt.Errorf("could not get volume GUID for volume %s: %w", volumePath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
volumePath = windows.UTF16ToString(volumeGUIDPtr)
|
|
||||||
|
|
||||||
// GetVolumeNameForVolumeMountPoint returns the volume GUID path as \\?\Volume{GUID}\
|
// GetVolumeNameForVolumeMountPoint returns the volume GUID path as \\?\Volume{GUID}\
|
||||||
// According https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol#remarks
|
// According https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol#remarks
|
||||||
// Win32 Drive Namespace is prefixed with \\.\, so we need to remove the \\?\ prefix.
|
// Win32 Drive Namespace is prefixed with \\.\, so we need to remove the \\?\ prefix.
|
||||||
volumePath, _ = strings.CutPrefix(volumePath, `\\?\`)
|
volumePath, _ = strings.CutPrefix(volumeGUID, `\\?\`)
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/55710326/how-to-get-the-physical-device-that-a-volume-guid-path-belongs-to#comment98104360_55710326
|
|
||||||
// DeviceIoControl expects no trailing backslash in the volume GUID path.
|
|
||||||
volumePath = strings.TrimRight(volumePath, `\`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
volumePathPtr := windows.StringToUTF16Ptr(`\\.\` + volumePath)
|
volumePathPtr := windows.StringToUTF16Ptr(`\\.\` + volumePath)
|
||||||
@@ -581,3 +568,59 @@ func getVolumeInfo(rootDrive string) (volumeInfo, error) {
|
|||||||
readonly: float64(fsFlags & windows.FILE_READ_ONLY_VOLUME),
|
readonly: float64(fsFlags & windows.FILE_READ_ONLY_VOLUME),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAllMountedVolumes() (map[string]string, error) {
|
||||||
|
guidBuf := make([]uint16, windows.MAX_PATH+1)
|
||||||
|
guidBufLen := uint32(len(guidBuf) * 2)
|
||||||
|
|
||||||
|
hFindVolume, err := windows.FindFirstVolume(&guidBuf[0], guidBufLen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("FindFirstVolume: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = windows.FindVolumeClose(hFindVolume)
|
||||||
|
}()
|
||||||
|
|
||||||
|
volumes := map[string]string{}
|
||||||
|
|
||||||
|
for ; ; err = windows.FindNextVolume(hFindVolume, &guidBuf[0], guidBufLen) {
|
||||||
|
if err != nil {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, windows.ERROR_NO_MORE_FILES):
|
||||||
|
return volumes, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("FindNextVolume: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rootPathLen uint32
|
||||||
|
|
||||||
|
rootPathBuf := make([]uint16, windows.MAX_PATH+1)
|
||||||
|
rootPathBufLen := uint32(len(rootPathBuf) * 2)
|
||||||
|
|
||||||
|
for {
|
||||||
|
err = windows.GetVolumePathNamesForVolumeName(&guidBuf[0], &rootPathBuf[0], rootPathBufLen, &rootPathLen)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, windows.ERROR_NO_MORE_FILES) {
|
||||||
|
rootPathBuf = make([]uint16, (rootPathLen+1)/2)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("GetVolumePathNamesForVolumeName: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mountPoint := windows.UTF16ToString(rootPathBuf)
|
||||||
|
|
||||||
|
// Skip unmounted volumes
|
||||||
|
if len(mountPoint) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes[strings.TrimSuffix(mountPoint, `\`)] = strings.TrimSuffix(windows.UTF16ToString(guidBuf), `\`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -257,13 +257,15 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
|||||||
// Result must order, to prevent test failures.
|
// Result must order, to prevent test failures.
|
||||||
sort.Strings(c.config.CollectorsEnabled)
|
sort.Strings(c.config.CollectorsEnabled)
|
||||||
|
|
||||||
|
errs := make([]error, 0, len(c.config.CollectorsEnabled))
|
||||||
|
|
||||||
for _, name := range c.config.CollectorsEnabled {
|
for _, name := range c.config.CollectorsEnabled {
|
||||||
if _, ok := subCollectors[name]; !ok {
|
if _, ok := subCollectors[name]; !ok {
|
||||||
return fmt.Errorf("unknown collector: %s", name)
|
return fmt.Errorf("unknown collector: %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := subCollectors[name].build(); err != nil {
|
if err := subCollectors[name].build(); err != nil {
|
||||||
return fmt.Errorf("failed to build %s collector: %w", name, err)
|
errs = append(errs, fmt.Errorf("failed to build %s collector: %w", name, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.collectorFns = append(c.collectorFns, subCollectors[name].collect)
|
c.collectorFns = append(c.collectorFns, subCollectors[name].collect)
|
||||||
@@ -291,7 +293,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
|||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
return nil
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect sends the metric values for each metric
|
// Collect sends the metric values for each metric
|
||||||
@@ -408,7 +410,7 @@ func (c *Collector) collect(
|
|||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
success = 0.0
|
success = 0.0
|
||||||
|
|
||||||
c.logger.Error(fmt.Sprintf("mssql class collector %s for instance %s failed after %s", collector, sqlInstance, duration),
|
c.logger.Debug(fmt.Sprintf("mssql class collector %s for instance %s failed after %s", collector, sqlInstance, duration),
|
||||||
slog.Any("err", err),
|
slog.Any("err", err),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ const (
|
|||||||
func (c *Collector) buildSQLErrors() error {
|
func (c *Collector) buildSQLErrors() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
|
c.sqlErrorsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
|
||||||
errs := make([]error, 0, len(c.mssqlInstances))
|
errs := make([]error, 0, len(c.mssqlInstances))
|
||||||
counters := []string{
|
counters := []string{
|
||||||
sqlErrorsErrorsPerSec,
|
sqlErrorsErrorsPerSec,
|
||||||
}
|
}
|
||||||
|
|
||||||
for sqlInstance := range c.mssqlInstances {
|
for sqlInstance := range c.mssqlInstances {
|
||||||
c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), perfdata.InstancesAll, counters)
|
c.sqlErrorsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), perfdata.InstancesAll, counters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, fmt.Errorf("failed to create SQL Errors collector for instance %s: %w", sqlInstance, err))
|
errs = append(errs, fmt.Errorf("failed to create SQL Errors collector for instance %s: %w", sqlInstance, err))
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ func (c *Collector) buildSQLErrors() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectSQLErrors(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectSQLErrors(ch chan<- prometheus.Metric) error {
|
||||||
return c.collect(ch, subCollectorSQLErrors, c.dbReplicaPerfDataCollectors, c.collectSQLErrorsInstance)
|
return c.collect(ch, subCollectorSQLErrors, c.sqlErrorsPerfDataCollectors, c.collectSQLErrorsInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectSQLErrorsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
|
func (c *Collector) collectSQLErrorsInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const (
|
|||||||
func (c *Collector) buildSQLStats() error {
|
func (c *Collector) buildSQLStats() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
c.genStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
|
c.sqlStatsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
|
||||||
errs := make([]error, 0, len(c.mssqlInstances))
|
errs := make([]error, 0, len(c.mssqlInstances))
|
||||||
counters := []string{
|
counters := []string{
|
||||||
sqlStatsAutoParamAttemptsPerSec,
|
sqlStatsAutoParamAttemptsPerSec,
|
||||||
@@ -74,7 +74,7 @@ func (c *Collector) buildSQLStats() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for sqlInstance := range c.mssqlInstances {
|
for sqlInstance := range c.mssqlInstances {
|
||||||
c.genStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), nil, counters)
|
c.sqlStatsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), nil, counters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, fmt.Errorf("failed to create SQL Statistics collector for instance %s: %w", sqlInstance, err))
|
errs = append(errs, fmt.Errorf("failed to create SQL Statistics collector for instance %s: %w", sqlInstance, err))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,8 +304,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for nicName, nicData := range data {
|
for nicName, nicData := range data {
|
||||||
if c.config.NicExclude.MatchString(nicName) ||
|
if c.config.NicExclude.MatchString(nicName) || !c.config.NicInclude.MatchString(nicName) {
|
||||||
!c.config.NicInclude.MatchString(nicName) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,14 +13,12 @@
|
|||||||
|
|
||||||
//go:build windows
|
//go:build windows
|
||||||
|
|
||||||
package perfdata
|
package performancecounter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"maps"
|
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
@@ -30,7 +28,7 @@ import (
|
|||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "perfdata"
|
const Name = "performancecounter"
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Objects []Object `yaml:"objects"`
|
Objects []Object `yaml:"objects"`
|
||||||
@@ -41,9 +39,11 @@ var ConfigDefaults = Config{
|
|||||||
Objects: make([]Object, 0),
|
Objects: make([]Object, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Collector is a Prometheus collector for perfdata metrics.
|
// A Collector is a Prometheus collector for performance counter metrics.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
|
|
||||||
|
logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config *Config) *Collector {
|
func New(config *Config) *Collector {
|
||||||
@@ -70,7 +70,7 @@ func NewWithFlags(app *kingpin.Application) *Collector {
|
|||||||
var objects string
|
var objects string
|
||||||
|
|
||||||
app.Flag(
|
app.Flag(
|
||||||
"collector.perfdata.objects",
|
"collector.performancecounter.objects",
|
||||||
"Objects of performance data to observe. See docs for more information on how to use this flag. By default, no objects are observed.",
|
"Objects of performance data to observe. See docs for more information on how to use this flag. By default, no objects are observed.",
|
||||||
).Default("").StringVar(&objects)
|
).Default("").StringVar(&objects)
|
||||||
|
|
||||||
@@ -102,10 +102,19 @@ func (c *Collector) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger.Warn("The perfdata collector is in an experimental state! The configuration may change in future. Please report any issues.")
|
c.logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
for i, object := range c.config.Objects {
|
for i, object := range c.config.Objects {
|
||||||
collector, err := perfdata.NewCollector(object.Object, object.Instances, slices.Sorted(maps.Keys(object.Counters)))
|
counters := make([]string, 0, len(object.Counters))
|
||||||
|
for j, counter := range object.Counters {
|
||||||
|
counters = append(counters, counter.Name)
|
||||||
|
|
||||||
|
if counter.Metric == "" {
|
||||||
|
c.config.Objects[i].Counters[j].Metric = sanitizeMetricName(fmt.Sprintf("%s_%s_%s_%s", types.Namespace, Name, object.Object, counter.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collector, err := perfdata.NewCollector(object.Object, object.Instances, counters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create v2 collector: %w", err)
|
return fmt.Errorf("failed to create v2 collector: %w", err)
|
||||||
}
|
}
|
||||||
@@ -123,40 +132,64 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
|||||||
// Collect sends the metric values for each metric
|
// Collect sends the metric values for each metric
|
||||||
// to the provided prometheus Metric channel.
|
// to the provided prometheus Metric channel.
|
||||||
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
||||||
for _, object := range c.config.Objects {
|
for _, perfDataObject := range c.config.Objects {
|
||||||
data, err := object.collector.Collect()
|
collectedPerfData, err := perfDataObject.collector.Collect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to collect data: %w", err)
|
return fmt.Errorf("failed to collect data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for instance, counters := range data {
|
for collectedInstance, collectedInstanceCounters := range collectedPerfData {
|
||||||
for counter, value := range counters {
|
for _, counter := range perfDataObject.Counters {
|
||||||
var labels prometheus.Labels
|
collectedCounterValue, ok := collectedInstanceCounters[counter.Name]
|
||||||
if instance != perfdata.InstanceEmpty {
|
if !ok {
|
||||||
labels = prometheus.Labels{object.InstanceLabel: instance}
|
c.logger.Warn(fmt.Sprintf("counter %s not found in collected data", counter.Name))
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
metricType := value.Type
|
labels := make(prometheus.Labels, len(counter.Labels)+1)
|
||||||
|
if collectedInstance != perfdata.InstanceEmpty {
|
||||||
|
labels[perfDataObject.InstanceLabel] = collectedInstance
|
||||||
|
}
|
||||||
|
|
||||||
if val, ok := object.Counters[counter]; ok {
|
for key, value := range counter.Labels {
|
||||||
switch val.Type {
|
labels[key] = value
|
||||||
case "counter":
|
}
|
||||||
metricType = prometheus.CounterValue
|
|
||||||
case "gauge":
|
var metricType prometheus.ValueType
|
||||||
metricType = prometheus.GaugeValue
|
|
||||||
}
|
switch counter.Type {
|
||||||
|
case "counter":
|
||||||
|
metricType = prometheus.CounterValue
|
||||||
|
case "gauge":
|
||||||
|
metricType = prometheus.GaugeValue
|
||||||
|
default:
|
||||||
|
metricType = collectedCounterValue.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
sanitizeMetricName(fmt.Sprintf("%s_perfdata_%s_%s", types.Namespace, object.Object, counter)),
|
counter.Metric,
|
||||||
fmt.Sprintf("Performance data for \\%s\\%s", object.Object, counter),
|
"windows_exporter: custom Performance Counter metric",
|
||||||
nil,
|
nil,
|
||||||
labels,
|
labels,
|
||||||
),
|
),
|
||||||
metricType,
|
metricType,
|
||||||
value.FirstValue,
|
collectedCounterValue.FirstValue,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if collectedCounterValue.SecondValue != 0 {
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
prometheus.NewDesc(
|
||||||
|
counter.Metric+"_second",
|
||||||
|
"windows_exporter: custom Performance Counter metric",
|
||||||
|
nil,
|
||||||
|
labels,
|
||||||
|
),
|
||||||
|
metricType,
|
||||||
|
collectedCounterValue.SecondValue,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,19 +13,19 @@
|
|||||||
|
|
||||||
//go:build windows
|
//go:build windows
|
||||||
|
|
||||||
package perfdata_test
|
package performancecounter_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/collector/performancecounter"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
|
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkCollector(b *testing.B) {
|
func BenchmarkCollector(b *testing.B) {
|
||||||
perfDataObjects := `[{"object":"Processor Information","instances":["*"],"counters":{"*": {}}}]`
|
perfDataObjects := `[{"object":"Processor Information","instances":["*"],"instance_label":"core","counters":[{"name":"% Processor Time","metric":"windows_performancecounter_processor_information_processor_time","labels":{"state":"active"}},{"name":"% Idle Time","metric":"windows_performancecounter_processor_information_processor_time","labels":{"state":"idle"}}]},{"object":"Memory","counters":[{"name":"Cache Faults/sec","type":"counter"}]}]`
|
||||||
kingpin.CommandLine.GetArg("collector.perfdata.objects").StringVar(&perfDataObjects)
|
kingpin.CommandLine.GetArg("collector.perfdata.objects").StringVar(&perfDataObjects)
|
||||||
|
|
||||||
testutils.FuncBenchmarkCollector(b, perfdata.Name, perfdata.NewWithFlags)
|
testutils.FuncBenchmarkCollector(b, performancecounter.Name, performancecounter.NewWithFlags)
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
//go:build windows
|
//go:build windows
|
||||||
|
|
||||||
package perfdata_test
|
package performancecounter_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/collector/performancecounter"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -32,7 +32,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type collectorAdapter struct {
|
type collectorAdapter struct {
|
||||||
perfdata.Collector
|
performancecounter.Collector
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe implements the prometheus.Collector interface.
|
// Describe implements the prometheus.Collector interface.
|
||||||
@@ -51,31 +51,40 @@ func TestCollector(t *testing.T) {
|
|||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
object string
|
object string
|
||||||
instances []string
|
instances []string
|
||||||
counters map[string]perfdata.Counter
|
instanceLabel string
|
||||||
|
counters []performancecounter.Counter
|
||||||
expectedMetrics *regexp.Regexp
|
expectedMetrics *regexp.Regexp
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
object: "Memory",
|
object: "Memory",
|
||||||
instances: nil,
|
instances: nil,
|
||||||
counters: map[string]perfdata.Counter{"Available Bytes": {Type: "gauge"}},
|
counters: []performancecounter.Counter{{Name: "Available Bytes", Type: "gauge"}},
|
||||||
expectedMetrics: regexp.MustCompile(`^# HELP windows_perfdata_memory_available_bytes Performance data for \\\\Memory\\\\Available Bytes\s*# TYPE windows_perfdata_memory_available_bytes gauge\s*windows_perfdata_memory_available_bytes \d`),
|
expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_memory_available_bytes windows_exporter: custom Performance Counter metric\S*\s*# TYPE windows_performancecounter_memory_available_bytes gauge\s*windows_performancecounter_memory_available_bytes \d`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
object: "Process",
|
object: "Process",
|
||||||
instances: []string{"*"},
|
instances: []string{"*"},
|
||||||
counters: map[string]perfdata.Counter{"Thread Count": {Type: "counter"}},
|
counters: []performancecounter.Counter{{Name: "Thread Count", Type: "counter"}},
|
||||||
expectedMetrics: regexp.MustCompile(`^# HELP windows_perfdata_process_thread_count Performance data for \\\\Process\\\\Thread Count\s*# TYPE windows_perfdata_process_thread_count counter\s*windows_perfdata_process_thread_count\{instance=".+"} \d`),
|
expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_process_thread_count windows_exporter: custom Performance Counter metric\S*\s*# TYPE windows_performancecounter_process_thread_count counter\s*windows_performancecounter_process_thread_count\{instance=".+"} \d`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
object: "Processor Information",
|
||||||
|
instances: []string{"*"},
|
||||||
|
instanceLabel: "core",
|
||||||
|
counters: []performancecounter.Counter{{Name: "% Processor Time", Metric: "windows_performancecounter_processor_information_processor_time", Labels: map[string]string{"state": "active"}}, {Name: "% Idle Time", Metric: "windows_performancecounter_processor_information_processor_time", Labels: map[string]string{"state": "idle"}}},
|
||||||
|
expectedMetrics: regexp.MustCompile(`^# HELP windows_performancecounter_processor_information_processor_time windows_exporter: custom Performance Counter metric\s+# TYPE windows_performancecounter_processor_information_processor_time counter\s+windows_performancecounter_processor_information_processor_time\{core="0,0",state="active"} [0-9.e+]+\s+windows_performancecounter_processor_information_processor_time\{core="0,0",state="idle"} [0-9.e+]+`),
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.object, func(t *testing.T) {
|
t.Run(tc.object, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
perfDataCollector := perfdata.New(&perfdata.Config{
|
perfDataCollector := performancecounter.New(&performancecounter.Config{
|
||||||
Objects: []perfdata.Object{
|
Objects: []performancecounter.Object{
|
||||||
{
|
{
|
||||||
Object: tc.object,
|
Object: tc.object,
|
||||||
Instances: tc.instances,
|
Instances: tc.instances,
|
||||||
Counters: tc.counters,
|
InstanceLabel: tc.instanceLabel,
|
||||||
|
Counters: tc.counters,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -13,19 +13,24 @@
|
|||||||
|
|
||||||
//go:build windows
|
//go:build windows
|
||||||
|
|
||||||
package perfdata
|
package performancecounter
|
||||||
|
|
||||||
import "github.com/prometheus-community/windows_exporter/internal/perfdata"
|
import "github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
|
|
||||||
type Object struct {
|
type Object struct {
|
||||||
Object string `json:"object" yaml:"object"`
|
Object string `json:"object" yaml:"object"`
|
||||||
Instances []string `json:"instances" yaml:"instances"`
|
Instances []string `json:"instances" yaml:"instances"`
|
||||||
Counters map[string]Counter `json:"counters" yaml:"counters"`
|
Counters []Counter `json:"counters" yaml:"counters"`
|
||||||
InstanceLabel string `json:"instance_label" yaml:"instance_label"` //nolint:tagliatelle
|
InstanceLabel string `json:"instance_label" yaml:"instance_label"` //nolint:tagliatelle
|
||||||
|
|
||||||
collector *perfdata.Collector
|
collector *perfdata.Collector
|
||||||
}
|
}
|
||||||
|
|
||||||
type Counter struct {
|
type Counter struct {
|
||||||
Type string `json:"type" yaml:"type"`
|
Name string `json:"name" yaml:"name"`
|
||||||
|
Type string `json:"type" yaml:"type"`
|
||||||
|
Metric string `json:"metric" yaml:"metric"`
|
||||||
|
Labels map[string]string `json:"labels" yaml:"labels"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/54691ebe11bb9ec32b4e35cd31fcb94a352de134/receiver/windowsperfcountersreceiver/README.md?plain=1#L150
|
||||||
@@ -46,7 +46,7 @@ type Collector struct {
|
|||||||
processes *prometheus.Desc
|
processes *prometheus.Desc
|
||||||
processesLimit *prometheus.Desc
|
processesLimit *prometheus.Desc
|
||||||
systemCallsTotal *prometheus.Desc
|
systemCallsTotal *prometheus.Desc
|
||||||
systemUpTime *prometheus.Desc
|
bootTime *prometheus.Desc
|
||||||
threads *prometheus.Desc
|
threads *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +92,12 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
|||||||
return fmt.Errorf("failed to create System collector: %w", err)
|
return fmt.Errorf("failed to create System collector: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.bootTime = prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(types.Namespace, Name, "boot_time_timestamp_seconds"),
|
||||||
|
"Unix timestamp of system boot time",
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
c.contextSwitchesTotal = prometheus.NewDesc(
|
c.contextSwitchesTotal = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "context_switches_total"),
|
prometheus.BuildFQName(types.Namespace, Name, "context_switches_total"),
|
||||||
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
|
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
|
||||||
@@ -129,12 +135,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
c.systemUpTime = prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "system_up_time"),
|
|
||||||
"System boot time (WMI source: PerfOS_System.SystemUpTime)",
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
c.threads = prometheus.NewDesc(
|
c.threads = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "threads"),
|
prometheus.BuildFQName(types.Namespace, Name, "threads"),
|
||||||
"Current number of threads (WMI source: PerfOS_System.Threads)",
|
"Current number of threads (WMI source: PerfOS_System.Threads)",
|
||||||
@@ -184,7 +184,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
|||||||
data[systemCallsPersec].FirstValue,
|
data[systemCallsPersec].FirstValue,
|
||||||
)
|
)
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.systemUpTime,
|
c.bootTime,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
data[systemUpTime].FirstValue,
|
data[systemUpTime].FirstValue,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ type Collector struct {
|
|||||||
// Only set for testing to get predictable output.
|
// Only set for testing to get predictable output.
|
||||||
mTime *float64
|
mTime *float64
|
||||||
|
|
||||||
mTimeDesc *prometheus.Desc
|
modTimeDesc *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config *Config) *Collector {
|
func New(config *Config) *Collector {
|
||||||
@@ -105,9 +105,9 @@ func (c *Collector) Close() error {
|
|||||||
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
c.logger = logger.With(slog.String("collector", Name))
|
c.logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
c.logger.Info("textfile Collector directories: " + strings.Join(c.config.TextFileDirectories, ","))
|
c.logger.Info("textfile directories: " + strings.Join(c.config.TextFileDirectories, ","))
|
||||||
|
|
||||||
c.mTimeDesc = prometheus.NewDesc(
|
c.modTimeDesc = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, "textfile", "mtime_seconds"),
|
prometheus.BuildFQName(types.Namespace, "textfile", "mtime_seconds"),
|
||||||
"Unixtime mtime of textfiles successfully read.",
|
"Unixtime mtime of textfiles successfully read.",
|
||||||
[]string{"file"},
|
[]string{"file"},
|
||||||
@@ -165,7 +165,7 @@ func (c *Collector) convertMetricFamily(logger *slog.Logger, metricFamily *dto.M
|
|||||||
|
|
||||||
for _, metric := range metricFamily.GetMetric() {
|
for _, metric := range metricFamily.GetMetric() {
|
||||||
if metric.TimestampMs != nil {
|
if metric.TimestampMs != nil {
|
||||||
logger.Warn(fmt.Sprintf("Ignoring unsupported custom timestamp on textfile Collector metric %v", metric))
|
logger.Warn(fmt.Sprintf("Ignoring unsupported custom timestamp on textfile metric %v", metric))
|
||||||
}
|
}
|
||||||
|
|
||||||
labels := metric.GetLabel()
|
labels := metric.GetLabel()
|
||||||
@@ -259,23 +259,24 @@ func (c *Collector) convertMetricFamily(logger *slog.Logger, metricFamily *dto.M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) exportMTimes(mTimes map[string]time.Time, ch chan<- prometheus.Metric) {
|
func (c *Collector) exportMTimes(modTimes map[string]time.Time, ch chan<- prometheus.Metric) {
|
||||||
// Export the mtimes of the successful files.
|
// Export the mtimes of the successful files.
|
||||||
if len(mTimes) > 0 {
|
if len(modTimes) > 0 {
|
||||||
// Sorting is needed for predictable output comparison in tests.
|
// Sorting is needed for predictable output comparison in tests.
|
||||||
filenames := make([]string, 0, len(mTimes))
|
filenames := make([]string, 0, len(modTimes))
|
||||||
for filename := range mTimes {
|
for filename := range modTimes {
|
||||||
filenames = append(filenames, filename)
|
filenames = append(filenames, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(filenames)
|
sort.Strings(filenames)
|
||||||
|
|
||||||
for _, filename := range filenames {
|
for _, filename := range filenames {
|
||||||
mtime := float64(mTimes[filename].UnixNano() / 1e9)
|
modTime := float64(modTimes[filename].UnixNano() / 1e9)
|
||||||
if c.mTime != nil {
|
if c.mTime != nil {
|
||||||
mtime = *c.mTime
|
modTime = *c.mTime
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(c.mTimeDesc, prometheus.GaugeValue, mtime, filename)
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(c.modTimeDesc, prometheus.GaugeValue, modTime, filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,6 +315,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
|||||||
// This will ensure that duplicate metrics are correctly detected between multiple .prom files.
|
// This will ensure that duplicate metrics are correctly detected between multiple .prom files.
|
||||||
var metricFamilies []*dto.MetricFamily
|
var metricFamilies []*dto.MetricFamily
|
||||||
|
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
// Iterate over files and accumulate their metrics.
|
// Iterate over files and accumulate their metrics.
|
||||||
for _, directory := range c.config.TextFileDirectories {
|
for _, directory := range c.config.TextFileDirectories {
|
||||||
err := filepath.WalkDir(directory, func(path string, dirEntry os.DirEntry, err error) error {
|
err := filepath.WalkDir(directory, func(path string, dirEntry os.DirEntry, err error) error {
|
||||||
@@ -326,24 +329,20 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
|||||||
|
|
||||||
families_array, err := scrapeFile(path, c.logger)
|
families_array, err := scrapeFile(path, c.logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Error(fmt.Sprintf("Error scraping file: %q. Skip File.", path),
|
errs = append(errs, fmt.Errorf("error scraping file %q: %w", path, err))
|
||||||
slog.Any("err", err),
|
|
||||||
)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fileInfo, err := os.Stat(path)
|
fileInfo, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Error(fmt.Sprintf("Error reading file info: %q. Skip File.", path),
|
errs = append(errs, fmt.Errorf("error reading file info %q: %w", path, err))
|
||||||
slog.Any("err", err),
|
|
||||||
)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, hasName := mTimes[fileInfo.Name()]; hasName {
|
if _, hasName := mTimes[fileInfo.Name()]; hasName {
|
||||||
c.logger.Error(fmt.Sprintf("Duplicate filename detected: %q. Skip File.", path))
|
errs = append(errs, fmt.Errorf("duplicate filename detected: %q", path))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -355,25 +354,24 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil && directory != "" {
|
if err != nil && directory != "" {
|
||||||
c.logger.Error("Error reading textfile Collector directory: "+directory,
|
errs = append(errs, fmt.Errorf("error reading textfile directory %q: %w", directory, err))
|
||||||
slog.Any("err", err),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.exportMTimes(mTimes, ch)
|
||||||
|
|
||||||
// If duplicates are detected across *multiple* files, return error.
|
// If duplicates are detected across *multiple* files, return error.
|
||||||
if duplicateMetricEntry(metricFamilies) {
|
if duplicateMetricEntry(metricFamilies) {
|
||||||
c.logger.Error("Duplicate metrics detected across multiple files")
|
c.logger.Warn("duplicate metrics detected across multiple files")
|
||||||
} else {
|
} else {
|
||||||
for _, mf := range metricFamilies {
|
for _, mf := range metricFamilies {
|
||||||
c.convertMetricFamily(c.logger, mf, ch)
|
c.convertMetricFamily(c.logger, mf, ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.exportMTimes(mTimes, ch)
|
return errors.Join(errs...)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func scrapeFile(path string, logger *slog.Logger) ([]*dto.MetricFamily, error) {
|
func scrapeFile(path string, logger *slog.Logger) ([]*dto.MetricFamily, error) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/prometheus-community/windows_exporter/pkg/collector"
|
"github.com/prometheus-community/windows_exporter/pkg/collector"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,30 +49,26 @@ func TestMultipleDirectories(t *testing.T) {
|
|||||||
metrics := make(chan prometheus.Metric)
|
metrics := make(chan prometheus.Metric)
|
||||||
got := ""
|
got := ""
|
||||||
|
|
||||||
|
errCh := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
errCh <- textFileCollector.Collect(metrics)
|
||||||
var metric dto.Metric
|
|
||||||
|
|
||||||
val := <-metrics
|
close(metrics)
|
||||||
|
|
||||||
err := val.Write(&metric)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
got += metric.String()
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err := textFileCollector.Collect(metrics)
|
for val := range metrics {
|
||||||
if err != nil {
|
var metric dto.Metric
|
||||||
t.Errorf("Unexpected error %s", err)
|
|
||||||
|
err := val.Write(&metric)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
got += metric.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require.NoError(t, <-errCh)
|
||||||
|
|
||||||
for _, f := range []string{"dir1", "dir2", "dir3", "dir3sub"} {
|
for _, f := range []string{"dir1", "dir2", "dir3", "dir3sub"} {
|
||||||
if !strings.Contains(got, f) {
|
assert.Contains(t, got, f)
|
||||||
t.Errorf("Unexpected output %s: %q", f, got)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,31 +86,24 @@ func TestDuplicateFileName(t *testing.T) {
|
|||||||
metrics := make(chan prometheus.Metric)
|
metrics := make(chan prometheus.Metric)
|
||||||
got := ""
|
got := ""
|
||||||
|
|
||||||
|
errCh := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
errCh <- textFileCollector.Collect(metrics)
|
||||||
var metric dto.Metric
|
|
||||||
|
|
||||||
val := <-metrics
|
close(metrics)
|
||||||
|
|
||||||
err := val.Write(&metric)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
got += metric.String()
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err := textFileCollector.Collect(metrics)
|
for val := range metrics {
|
||||||
if err != nil {
|
var metric dto.Metric
|
||||||
t.Errorf("Unexpected error %s", err)
|
|
||||||
|
err := val.Write(&metric)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
got += metric.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(got, "file") {
|
require.ErrorContains(t, <-errCh, "duplicate filename detected")
|
||||||
t.Errorf("Unexpected output %q", got)
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(got, "sub_file") {
|
assert.Contains(t, got, "file")
|
||||||
t.Errorf("Unexpected output %q", got)
|
assert.NotContains(t, got, "sub_file")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,16 +24,16 @@ const (
|
|||||||
cpuStolenMs = "CPU stolen time" // \VM Processor(*)\CPU stolen time
|
cpuStolenMs = "CPU stolen time" // \VM Processor(*)\CPU stolen time
|
||||||
cpuTimePercents = "% Processor Time" // \VM Processor(*)\% Processor Time
|
cpuTimePercents = "% Processor Time" // \VM Processor(*)\% Processor Time
|
||||||
|
|
||||||
memActiveMB = "MemActiveMB" // \VM Memory\Memory Active in MB
|
memActiveMB = "Memory Active in MB" // \VM Memory\Memory Active in MB
|
||||||
memBalloonedMB = "MemBalloonedMB" // \VM Memory\Memory Ballooned in MB
|
memBalloonedMB = "Memory Ballooned in MB" // \VM Memory\Memory Ballooned in MB
|
||||||
memLimitMB = "MemLimitMB" // \VM Memory\Memory Limit in MB
|
memLimitMB = "Memory Limit in MB" // \VM Memory\Memory Limit in MB
|
||||||
memMappedMB = "MemMappedMB" // \VM Memory\Memory Mapped in MB
|
memMappedMB = "Memory Mapped in MB" // \VM Memory\Memory Mapped in MB
|
||||||
memOverheadMB = "MemOverheadMB" // \VM Memory\Memory Overhead in MB
|
memOverheadMB = "Memory Overhead in MB" // \VM Memory\Memory Overhead in MB
|
||||||
memReservationMB = "MemReservationMB" // \VM Memory\Memory Reservation in MB
|
memReservationMB = "Memory Reservation in MB" // \VM Memory\Memory Reservation in MB
|
||||||
memSharedMB = "MemSharedMB" // \VM Memory\Memory Shared in MB
|
memSharedMB = "Memory Shared in MB" // \VM Memory\Memory Shared in MB
|
||||||
memSharedSavedMB = "MemSharedSavedMB" // \VM Memory\Memory Shared Saved in MB
|
memSharedSavedMB = "Memory Shared Saved in MB" // \VM Memory\Memory Shared Saved in MB
|
||||||
memShares = "MemShares" // \VM Memory\Memory Shares
|
memShares = "Memory Shares" // \VM Memory\Memory Shares
|
||||||
memSwappedMB = "MemSwappedMB" // \VM Memory\Memory Swapped in MB
|
memSwappedMB = "Memory Swapped in MB" // \VM Memory\Memory Swapped in MB
|
||||||
memTargetSizeMB = "MemTargetSizeMB" // \VM Memory\Memory Target Size
|
memTargetSizeMB = "Memory Target Size" // \VM Memory\Memory Target Size
|
||||||
memUsedMB = "MemUsedMB" // \VM Memory\Memory Used in MB
|
memUsedMB = "Memory Used in MB" // \VM Memory\Memory Used in MB
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ var _ http.Handler = (*MetricsHTTPHandler)(nil)
|
|||||||
const defaultScrapeTimeout = 10.0
|
const defaultScrapeTimeout = 10.0
|
||||||
|
|
||||||
type MetricsHTTPHandler struct {
|
type MetricsHTTPHandler struct {
|
||||||
metricCollectors *collector.MetricCollectors
|
metricCollectors *collector.Collection
|
||||||
// exporterMetricsRegistry is a separate registry for the metrics about
|
// exporterMetricsRegistry is a separate registry for the metrics about
|
||||||
// the exporter itself.
|
// the exporter itself.
|
||||||
exporterMetricsRegistry *prometheus.Registry
|
exporterMetricsRegistry *prometheus.Registry
|
||||||
@@ -49,15 +49,13 @@ type MetricsHTTPHandler struct {
|
|||||||
type Options struct {
|
type Options struct {
|
||||||
DisableExporterMetrics bool
|
DisableExporterMetrics bool
|
||||||
TimeoutMargin float64
|
TimeoutMargin float64
|
||||||
MaxRequests int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(logger *slog.Logger, metricCollectors *collector.MetricCollectors, options *Options) *MetricsHTTPHandler {
|
func New(logger *slog.Logger, metricCollectors *collector.Collection, options *Options) *MetricsHTTPHandler {
|
||||||
if options == nil {
|
if options == nil {
|
||||||
options = &Options{
|
options = &Options{
|
||||||
DisableExporterMetrics: false,
|
DisableExporterMetrics: false,
|
||||||
TimeoutMargin: 0.5,
|
TimeoutMargin: 0.5,
|
||||||
MaxRequests: 5,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +63,9 @@ func New(logger *slog.Logger, metricCollectors *collector.MetricCollectors, opti
|
|||||||
metricCollectors: metricCollectors,
|
metricCollectors: metricCollectors,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
options: *options,
|
options: *options,
|
||||||
concurrencyCh: make(chan struct{}, options.MaxRequests),
|
|
||||||
|
// We are expose metrics directly from the memory region of the Win32 API. We should not allow more than one request at a time.
|
||||||
|
concurrencyCh: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !options.DisableExporterMetrics {
|
if !options.DisableExporterMetrics {
|
||||||
@@ -126,82 +126,48 @@ func (c *MetricsHTTPHandler) getScrapeTimeout(logger *slog.Logger, r *http.Reque
|
|||||||
|
|
||||||
func (c *MetricsHTTPHandler) handlerFactory(logger *slog.Logger, scrapeTimeout time.Duration, requestedCollectors []string) (http.Handler, error) {
|
func (c *MetricsHTTPHandler) handlerFactory(logger *slog.Logger, scrapeTimeout time.Duration, requestedCollectors []string) (http.Handler, error) {
|
||||||
reg := prometheus.NewRegistry()
|
reg := prometheus.NewRegistry()
|
||||||
|
|
||||||
var metricCollectors *collector.MetricCollectors
|
|
||||||
if len(requestedCollectors) == 0 {
|
|
||||||
metricCollectors = c.metricCollectors
|
|
||||||
} else {
|
|
||||||
filteredCollectors := make(collector.Map)
|
|
||||||
|
|
||||||
for _, name := range requestedCollectors {
|
|
||||||
metricCollector, ok := c.metricCollectors.Collectors[name]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("couldn't find collector %s", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredCollectors[name] = metricCollector
|
|
||||||
}
|
|
||||||
|
|
||||||
metricCollectors = &collector.MetricCollectors{
|
|
||||||
Collectors: filteredCollectors,
|
|
||||||
MISession: c.metricCollectors.MISession,
|
|
||||||
PerfCounterQuery: c.metricCollectors.PerfCounterQuery,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reg.MustRegister(version.NewCollector("windows_exporter"))
|
reg.MustRegister(version.NewCollector("windows_exporter"))
|
||||||
|
|
||||||
if err := reg.Register(metricCollectors.NewPrometheusCollector(scrapeTimeout, c.logger)); err != nil {
|
collectionHandler, err := c.metricCollectors.NewHandler(scrapeTimeout, c.logger, requestedCollectors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't create collector handler: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := reg.Register(collectionHandler); err != nil {
|
||||||
return nil, fmt.Errorf("couldn't register Prometheus collector: %w", err)
|
return nil, fmt.Errorf("couldn't register Prometheus collector: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var handler http.Handler
|
var regHandler http.Handler
|
||||||
if c.exporterMetricsRegistry != nil {
|
if c.exporterMetricsRegistry != nil {
|
||||||
handler = promhttp.HandlerFor(
|
regHandler = promhttp.HandlerFor(
|
||||||
prometheus.Gatherers{c.exporterMetricsRegistry, reg},
|
prometheus.Gatherers{c.exporterMetricsRegistry, reg},
|
||||||
promhttp.HandlerOpts{
|
promhttp.HandlerOpts{
|
||||||
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
|
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
|
||||||
ErrorHandling: promhttp.ContinueOnError,
|
ErrorHandling: promhttp.ContinueOnError,
|
||||||
MaxRequestsInFlight: c.options.MaxRequests,
|
MaxRequestsInFlight: 1,
|
||||||
Registry: c.exporterMetricsRegistry,
|
Registry: c.exporterMetricsRegistry,
|
||||||
|
EnableOpenMetrics: true,
|
||||||
|
ProcessStartTime: c.metricCollectors.GetStartTime(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Note that we have to use h.exporterMetricsRegistry here to
|
// Note that we have to use h.exporterMetricsRegistry here to
|
||||||
// use the same promhttp metrics for all expositions.
|
// use the same promhttp metrics for all expositions.
|
||||||
handler = promhttp.InstrumentMetricHandler(
|
regHandler = promhttp.InstrumentMetricHandler(
|
||||||
c.exporterMetricsRegistry, handler,
|
c.exporterMetricsRegistry, regHandler,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
handler = promhttp.HandlerFor(
|
regHandler = promhttp.HandlerFor(
|
||||||
reg,
|
reg,
|
||||||
promhttp.HandlerOpts{
|
promhttp.HandlerOpts{
|
||||||
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
|
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
|
||||||
ErrorHandling: promhttp.ContinueOnError,
|
ErrorHandling: promhttp.ContinueOnError,
|
||||||
MaxRequestsInFlight: c.options.MaxRequests,
|
MaxRequestsInFlight: 1,
|
||||||
|
EnableOpenMetrics: true,
|
||||||
|
ProcessStartTime: c.metricCollectors.GetStartTime(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.withConcurrencyLimit(handler.ServeHTTP), nil
|
return regHandler, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (c *MetricsHTTPHandler) withConcurrencyLimit(next http.HandlerFunc) http.HandlerFunc {
|
|
||||||
if c.options.MaxRequests <= 0 {
|
|
||||||
return next
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
select {
|
|
||||||
case c.concurrencyCh <- struct{}{}:
|
|
||||||
defer func() { <-c.concurrencyCh }()
|
|
||||||
default:
|
|
||||||
w.WriteHeader(http.StatusServiceUnavailable)
|
|
||||||
_, _ = w.Write([]byte("Too many concurrent requests"))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
next(w, r)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ func AddFlags(a *kingpin.Application, config *log.Config) {
|
|||||||
config.Config = new(promslog.Config)
|
config.Config = new(promslog.Config)
|
||||||
flag.AddFlags(a, config.Config)
|
flag.AddFlags(a, config.Config)
|
||||||
|
|
||||||
config.File = &log.AllowedFile{}
|
if config.File == nil {
|
||||||
a.Flag(FileFlagName, FileFlagHelp).Default("stderr").SetValue(config.File)
|
config.File = &log.AllowedFile{}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Flag(FileFlagName, FileFlagHelp).Default(config.File.String()).SetValue(config.File)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ type AllowedFile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *AllowedFile) String() string {
|
func (f *AllowedFile) String() string {
|
||||||
|
if f == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
return f.s
|
return f.s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,13 @@ func (c *Collector) Collect() (CounterValues, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectRoutine() {
|
func (c *Collector) collectRoutine() {
|
||||||
|
var (
|
||||||
|
itemCount uint32
|
||||||
|
bytesNeeded uint32
|
||||||
|
)
|
||||||
|
|
||||||
|
buf := make([]byte, 1)
|
||||||
|
|
||||||
for range c.collectCh {
|
for range c.collectCh {
|
||||||
if ret := PdhCollectQueryData(c.handle); ret != ErrorSuccess {
|
if ret := PdhCollectQueryData(c.handle); ret != ErrorSuccess {
|
||||||
c.counterValuesCh <- nil
|
c.counterValuesCh <- nil
|
||||||
@@ -207,25 +214,24 @@ func (c *Collector) collectRoutine() {
|
|||||||
for _, counter := range c.counters {
|
for _, counter := range c.counters {
|
||||||
for _, instance := range counter.Instances {
|
for _, instance := range counter.Instances {
|
||||||
// Get the info with the current buffer size
|
// Get the info with the current buffer size
|
||||||
var itemCount uint32
|
bytesNeeded = uint32(cap(buf))
|
||||||
|
|
||||||
// Get the info with the current buffer size
|
for {
|
||||||
bufLen := uint32(0)
|
ret := PdhGetRawCounterArray(instance, &bytesNeeded, &itemCount, &buf[0])
|
||||||
|
|
||||||
ret := PdhGetRawCounterArray(instance, &bufLen, &itemCount, nil)
|
if ret == ErrorSuccess {
|
||||||
if ret != PdhMoreData {
|
break
|
||||||
return nil, fmt.Errorf("PdhGetRawCounterArray: %w", NewPdhError(ret))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, bufLen)
|
if err := NewPdhError(ret); ret != PdhMoreData && !isKnownCounterDataError(err) {
|
||||||
|
|
||||||
ret = PdhGetRawCounterArray(instance, &bufLen, &itemCount, &buf[0])
|
|
||||||
if ret != ErrorSuccess {
|
|
||||||
if err := NewPdhError(ret); !isKnownCounterDataError(err) {
|
|
||||||
return nil, fmt.Errorf("PdhGetRawCounterArray: %w", err)
|
return nil, fmt.Errorf("PdhGetRawCounterArray: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
if bytesNeeded <= uint32(cap(buf)) {
|
||||||
|
return nil, fmt.Errorf("PdhGetRawCounterArray reports buffer too small (%d), but buffer is large enough (%d): %w", uint32(cap(buf)), bytesNeeded, NewPdhError(ret))
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = make([]byte, bytesNeeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
items := unsafe.Slice((*PdhRawCounterItem)(unsafe.Pointer(&buf[0])), itemCount)
|
items := unsafe.Slice((*PdhRawCounterItem)(unsafe.Pointer(&buf[0])), itemCount)
|
||||||
|
|||||||
@@ -61,4 +61,6 @@ func BenchmarkTestCollector(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
performanceData.Close()
|
performanceData.Close()
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//go:build windows
|
|
||||||
|
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -27,26 +25,10 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
types "github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interface guard.
|
|
||||||
var _ prometheus.Collector = (*Prometheus)(nil)
|
|
||||||
|
|
||||||
// Prometheus implements prometheus.Collector for a set of Windows MetricCollectors.
|
|
||||||
type Prometheus struct {
|
|
||||||
maxScrapeDuration time.Duration
|
|
||||||
logger *slog.Logger
|
|
||||||
metricCollectors *MetricCollectors
|
|
||||||
|
|
||||||
// Base metrics returned by Prometheus
|
|
||||||
scrapeDurationDesc *prometheus.Desc
|
|
||||||
collectorScrapeDurationDesc *prometheus.Desc
|
|
||||||
collectorScrapeSuccessDesc *prometheus.Desc
|
|
||||||
collectorScrapeTimeoutDesc *prometheus.Desc
|
|
||||||
}
|
|
||||||
|
|
||||||
type collectorStatus struct {
|
type collectorStatus struct {
|
||||||
name string
|
name string
|
||||||
statusCode collectorStatusCode
|
statusCode collectorStatusCode
|
||||||
@@ -60,64 +42,26 @@ const (
|
|||||||
failed
|
failed
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPrometheusCollector returns a new Prometheus where the set of MetricCollectors must
|
func (c *Collection) collectAll(ch chan<- prometheus.Metric, logger *slog.Logger, maxScrapeDuration time.Duration) {
|
||||||
// return metrics within the given timeout.
|
|
||||||
func (c *MetricCollectors) NewPrometheusCollector(timeout time.Duration, logger *slog.Logger) *Prometheus {
|
|
||||||
return &Prometheus{
|
|
||||||
maxScrapeDuration: timeout,
|
|
||||||
metricCollectors: c,
|
|
||||||
logger: logger,
|
|
||||||
scrapeDurationDesc: prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(types.Namespace, "exporter", "scrape_duration_seconds"),
|
|
||||||
"windows_exporter: Total scrape duration.",
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
),
|
|
||||||
collectorScrapeDurationDesc: prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(types.Namespace, "exporter", "collector_duration_seconds"),
|
|
||||||
"windows_exporter: Duration of a collection.",
|
|
||||||
[]string{"collector"},
|
|
||||||
nil,
|
|
||||||
),
|
|
||||||
collectorScrapeSuccessDesc: prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(types.Namespace, "exporter", "collector_success"),
|
|
||||||
"windows_exporter: Whether the collector was successful.",
|
|
||||||
[]string{"collector"},
|
|
||||||
nil,
|
|
||||||
),
|
|
||||||
collectorScrapeTimeoutDesc: prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(types.Namespace, "exporter", "collector_timeout"),
|
|
||||||
"windows_exporter: Whether the collector timed out.",
|
|
||||||
[]string{"collector"},
|
|
||||||
nil,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prometheus) Describe(_ chan<- *prometheus.Desc) {}
|
|
||||||
|
|
||||||
// Collect sends the collected metrics from each of the MetricCollectors to
|
|
||||||
// prometheus.
|
|
||||||
func (p *Prometheus) Collect(ch chan<- prometheus.Metric) {
|
|
||||||
collectorStartTime := time.Now()
|
collectorStartTime := time.Now()
|
||||||
|
|
||||||
// WaitGroup to wait for all collectors to finish
|
// WaitGroup to wait for all collectors to finish
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(len(p.metricCollectors.Collectors))
|
wg.Add(len(c.collectors))
|
||||||
|
|
||||||
// Using a channel to collect the status of each collector
|
// Using a channel to collect the status of each collector
|
||||||
// A channel is safe to use concurrently while a map is not
|
// A channel is safe to use concurrently while a map is not
|
||||||
collectorStatusCh := make(chan collectorStatus, len(p.metricCollectors.Collectors))
|
collectorStatusCh := make(chan collectorStatus, len(c.collectors))
|
||||||
|
|
||||||
// Execute all collectors concurrently
|
// Execute all collectors concurrently
|
||||||
// timeout handling is done in the execute function
|
// timeout handling is done in the execute function
|
||||||
for name, metricsCollector := range p.metricCollectors.Collectors {
|
for name, metricsCollector := range c.collectors {
|
||||||
go func(name string, metricsCollector Collector) {
|
go func(name string, metricsCollector Collector) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
collectorStatusCh <- collectorStatus{
|
collectorStatusCh <- collectorStatus{
|
||||||
name: name,
|
name: name,
|
||||||
statusCode: p.execute(name, metricsCollector, ch),
|
statusCode: c.collectCollector(ch, logger, name, metricsCollector, maxScrapeDuration),
|
||||||
}
|
}
|
||||||
}(name, metricsCollector)
|
}(name, metricsCollector)
|
||||||
}
|
}
|
||||||
@@ -139,14 +83,14 @@ func (p *Prometheus) Collect(ch chan<- prometheus.Metric) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
p.collectorScrapeSuccessDesc,
|
c.collectorScrapeSuccessDesc,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
successValue,
|
successValue,
|
||||||
status.name,
|
status.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
p.collectorScrapeTimeoutDesc,
|
c.collectorScrapeTimeoutDesc,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
timeoutValue,
|
timeoutValue,
|
||||||
status.name,
|
status.name,
|
||||||
@@ -154,13 +98,13 @@ func (p *Prometheus) Collect(ch chan<- prometheus.Metric) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
p.scrapeDurationDesc,
|
c.scrapeDurationDesc,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
time.Since(collectorStartTime).Seconds(),
|
time.Since(collectorStartTime).Seconds(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prometheus) execute(name string, c Collector, ch chan<- prometheus.Metric) collectorStatusCode {
|
func (c *Collection) collectCollector(ch chan<- prometheus.Metric, logger *slog.Logger, name string, collector Collector, maxScrapeDuration time.Duration) collectorStatusCode {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
numMetrics int
|
numMetrics int
|
||||||
@@ -173,10 +117,10 @@ func (p *Prometheus) execute(name string, c Collector, ch chan<- prometheus.Metr
|
|||||||
bufCh := make(chan prometheus.Metric, 1000)
|
bufCh := make(chan prometheus.Metric, 1000)
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), p.maxScrapeDuration)
|
ctx, cancel := context.WithTimeout(context.Background(), maxScrapeDuration)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Execute the collector
|
// execute the collector
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -188,7 +132,7 @@ func (p *Prometheus) execute(name string, c Collector, ch chan<- prometheus.Metr
|
|||||||
close(bufCh)
|
close(bufCh)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
errCh <- c.Collect(bufCh)
|
errCh <- collector.Collect(bufCh)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
@@ -232,7 +176,7 @@ func (p *Prometheus) execute(name string, c Collector, ch chan<- prometheus.Metr
|
|||||||
|
|
||||||
duration = time.Since(t)
|
duration = time.Since(t)
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
p.collectorScrapeDurationDesc,
|
c.collectorScrapeDurationDesc,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
duration.Seconds(),
|
duration.Seconds(),
|
||||||
name,
|
name,
|
||||||
@@ -242,13 +186,13 @@ func (p *Prometheus) execute(name string, c Collector, ch chan<- prometheus.Metr
|
|||||||
|
|
||||||
duration = time.Since(t)
|
duration = time.Since(t)
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
p.collectorScrapeDurationDesc,
|
c.collectorScrapeDurationDesc,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
duration.Seconds(),
|
duration.Seconds(),
|
||||||
name,
|
name,
|
||||||
)
|
)
|
||||||
|
|
||||||
p.logger.Warn(fmt.Sprintf("collector %s timeouted after %s, resulting in %d metrics", name, p.maxScrapeDuration, numMetrics))
|
logger.Warn(fmt.Sprintf("collector %s timeouted after %s, resulting in %d metrics", name, maxScrapeDuration, numMetrics))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// Drain channel in case of premature return to not leak a goroutine.
|
// Drain channel in case of premature return to not leak a goroutine.
|
||||||
@@ -260,13 +204,10 @@ func (p *Prometheus) execute(name string, c Collector, ch chan<- prometheus.Metr
|
|||||||
return pending
|
return pending
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, perfdata.ErrNoData) && !errors.Is(err, types.ErrNoData) {
|
||||||
loggerFn := p.logger.Warn
|
loggerFn := logger.Warn
|
||||||
if errors.Is(err, types.ErrNoData) ||
|
if errors.Is(err, perfdata.ErrPerformanceCounterNotInitialized) || errors.Is(err, mi.MI_RESULT_INVALID_NAMESPACE) {
|
||||||
errors.Is(err, perfdata.ErrNoData) ||
|
loggerFn = logger.Debug
|
||||||
errors.Is(err, perfdata.ErrPerformanceCounterNotInitialized) ||
|
|
||||||
errors.Is(err, mi.MI_RESULT_INVALID_NAMESPACE) {
|
|
||||||
loggerFn = p.logger.Debug
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loggerFn(fmt.Sprintf("collector %s failed after %s, resulting in %d metrics", name, duration, numMetrics),
|
loggerFn(fmt.Sprintf("collector %s failed after %s, resulting in %d metrics", name, duration, numMetrics),
|
||||||
@@ -276,7 +217,7 @@ func (p *Prometheus) execute(name string, c Collector, ch chan<- prometheus.Metr
|
|||||||
return failed
|
return failed
|
||||||
}
|
}
|
||||||
|
|
||||||
p.logger.Debug(fmt.Sprintf("collector %s succeeded after %s, resulting in %d metrics", name, duration, numMetrics))
|
logger.Debug(fmt.Sprintf("collector %s succeeded after %s, resulting in %d metrics", name, duration, numMetrics))
|
||||||
|
|
||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"maps"
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
|
gotime "time"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/ad"
|
"github.com/prometheus-community/windows_exporter/internal/collector/ad"
|
||||||
@@ -52,7 +54,7 @@ import (
|
|||||||
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
|
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/os"
|
"github.com/prometheus-community/windows_exporter/internal/collector/os"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
|
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/collector/performancecounter"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
|
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
|
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/process"
|
"github.com/prometheus-community/windows_exporter/internal/collector/process"
|
||||||
@@ -72,10 +74,12 @@ import (
|
|||||||
"github.com/prometheus-community/windows_exporter/internal/collector/update"
|
"github.com/prometheus-community/windows_exporter/internal/collector/update"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/vmware"
|
"github.com/prometheus-community/windows_exporter/internal/collector/vmware"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse.
|
// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse.
|
||||||
func NewWithFlags(app *kingpin.Application) *MetricCollectors {
|
func NewWithFlags(app *kingpin.Application) *Collection {
|
||||||
collectors := map[string]Collector{}
|
collectors := map[string]Collector{}
|
||||||
|
|
||||||
for name, builder := range BuildersWithFlags {
|
for name, builder := range BuildersWithFlags {
|
||||||
@@ -88,7 +92,7 @@ func NewWithFlags(app *kingpin.Application) *MetricCollectors {
|
|||||||
// NewWithConfig To be called by the external libraries for collector initialization without running [kingpin.Parse].
|
// NewWithConfig To be called by the external libraries for collector initialization without running [kingpin.Parse].
|
||||||
//
|
//
|
||||||
//goland:noinspection GoUnusedExportedFunction
|
//goland:noinspection GoUnusedExportedFunction
|
||||||
func NewWithConfig(config Config) *MetricCollectors {
|
func NewWithConfig(config Config) *Collection {
|
||||||
collectors := Map{}
|
collectors := Map{}
|
||||||
collectors[ad.Name] = ad.New(&config.AD)
|
collectors[ad.Name] = ad.New(&config.AD)
|
||||||
collectors[adcs.Name] = adcs.New(&config.ADCS)
|
collectors[adcs.Name] = adcs.New(&config.ADCS)
|
||||||
@@ -119,7 +123,7 @@ func NewWithConfig(config Config) *MetricCollectors {
|
|||||||
collectors[nps.Name] = nps.New(&config.Nps)
|
collectors[nps.Name] = nps.New(&config.Nps)
|
||||||
collectors[os.Name] = os.New(&config.OS)
|
collectors[os.Name] = os.New(&config.OS)
|
||||||
collectors[pagefile.Name] = pagefile.New(&config.Paging)
|
collectors[pagefile.Name] = pagefile.New(&config.Paging)
|
||||||
collectors[perfdata.Name] = perfdata.New(&config.PerfData)
|
collectors[performancecounter.Name] = performancecounter.New(&config.PerformanceCounter)
|
||||||
collectors[physical_disk.Name] = physical_disk.New(&config.PhysicalDisk)
|
collectors[physical_disk.Name] = physical_disk.New(&config.PhysicalDisk)
|
||||||
collectors[printer.Name] = printer.New(&config.Printer)
|
collectors[printer.Name] = printer.New(&config.Printer)
|
||||||
collectors[process.Name] = process.New(&config.Process)
|
collectors[process.Name] = process.New(&config.Process)
|
||||||
@@ -143,23 +147,48 @@ func NewWithConfig(config Config) *MetricCollectors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New To be called by the external libraries for collector initialization.
|
// New To be called by the external libraries for collector initialization.
|
||||||
func New(collectors Map) *MetricCollectors {
|
func New(collectors Map) *Collection {
|
||||||
return &MetricCollectors{
|
return &Collection{
|
||||||
Collectors: collectors,
|
collectors: collectors,
|
||||||
|
concurrencyCh: make(chan struct{}, 1),
|
||||||
|
scrapeDurationDesc: prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(types.Namespace, "exporter", "scrape_duration_seconds"),
|
||||||
|
"windows_exporter: Total scrape duration.",
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
collectorScrapeDurationDesc: prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(types.Namespace, "exporter", "collector_duration_seconds"),
|
||||||
|
"windows_exporter: Duration of a collection.",
|
||||||
|
[]string{"collector"},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
collectorScrapeSuccessDesc: prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(types.Namespace, "exporter", "collector_success"),
|
||||||
|
"windows_exporter: Whether the collector was successful.",
|
||||||
|
[]string{"collector"},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
collectorScrapeTimeoutDesc: prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(types.Namespace, "exporter", "collector_timeout"),
|
||||||
|
"windows_exporter: Whether the collector timed out.",
|
||||||
|
[]string{"collector"},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable removes all collectors that not enabledCollectors.
|
// Enable removes all collectors that not enabledCollectors.
|
||||||
func (c *MetricCollectors) Enable(enabledCollectors []string) error {
|
func (c *Collection) Enable(enabledCollectors []string) error {
|
||||||
for _, name := range enabledCollectors {
|
for _, name := range enabledCollectors {
|
||||||
if _, ok := c.Collectors[name]; !ok {
|
if _, ok := c.collectors[name]; !ok {
|
||||||
return fmt.Errorf("unknown collector %s", name)
|
return fmt.Errorf("unknown collector %s", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for name := range c.Collectors {
|
for name := range c.collectors {
|
||||||
if !slices.Contains(enabledCollectors, name) {
|
if !slices.Contains(enabledCollectors, name) {
|
||||||
delete(c.Collectors, name)
|
delete(c.collectors, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,23 +196,25 @@ func (c *MetricCollectors) Enable(enabledCollectors []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build To be called by the exporter for collector initialization.
|
// Build To be called by the exporter for collector initialization.
|
||||||
func (c *MetricCollectors) Build(logger *slog.Logger) error {
|
func (c *Collection) Build(logger *slog.Logger) error {
|
||||||
|
c.startTime = gotime.Now()
|
||||||
|
|
||||||
err := c.initMI()
|
err := c.initMI()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error from initialize MI: %w", err)
|
return fmt.Errorf("error from initialize MI: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(len(c.Collectors))
|
wg.Add(len(c.collectors))
|
||||||
|
|
||||||
errCh := make(chan error, len(c.Collectors))
|
errCh := make(chan error, len(c.collectors))
|
||||||
errs := make([]error, 0, len(c.Collectors))
|
errs := make([]error, 0, len(c.collectors))
|
||||||
|
|
||||||
for _, collector := range c.Collectors {
|
for _, collector := range c.collectors {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
if err = collector.Build(logger, c.MISession); err != nil {
|
if err = collector.Build(logger, c.miSession); err != nil {
|
||||||
errCh <- fmt.Errorf("error build collector %s: %w", collector.GetName(), err)
|
errCh <- fmt.Errorf("error build collector %s: %w", collector.GetName(), err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -201,21 +232,21 @@ func (c *MetricCollectors) Build(logger *slog.Logger) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close To be called by the exporter for collector cleanup.
|
// Close To be called by the exporter for collector cleanup.
|
||||||
func (c *MetricCollectors) Close() error {
|
func (c *Collection) Close() error {
|
||||||
errs := make([]error, 0, len(c.Collectors))
|
errs := make([]error, 0, len(c.collectors))
|
||||||
|
|
||||||
for _, collector := range c.Collectors {
|
for _, collector := range c.collectors {
|
||||||
if err := collector.Close(); err != nil {
|
if err := collector.Close(); err != nil {
|
||||||
errs = append(errs, fmt.Errorf("error from close collector %s: %w", collector.GetName(), err))
|
errs = append(errs, fmt.Errorf("error from close collector %s: %w", collector.GetName(), err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app, err := c.MISession.GetApplication()
|
app, err := c.miSession.GetApplication()
|
||||||
if err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
if err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
||||||
errs = append(errs, fmt.Errorf("error from get MI application: %w", err))
|
errs = append(errs, fmt.Errorf("error from get MI application: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.MISession.Close(); err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
if err := c.miSession.Close(); err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
||||||
errs = append(errs, fmt.Errorf("error from close MI session: %w", err))
|
errs = append(errs, fmt.Errorf("error from close MI session: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,8 +257,8 @@ func (c *MetricCollectors) Close() error {
|
|||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close To be called by the exporter for collector cleanup.
|
// initMI To be called by the exporter for collector initialization.
|
||||||
func (c *MetricCollectors) initMI() error {
|
func (c *Collection) initMI() error {
|
||||||
app, err := mi.Application_Initialize()
|
app, err := mi.Application_Initialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error from initialize MI application: %w", err)
|
return fmt.Errorf("error from initialize MI application: %w", err)
|
||||||
@@ -242,10 +273,34 @@ func (c *MetricCollectors) initMI() error {
|
|||||||
return fmt.Errorf("error from set locale: %w", err)
|
return fmt.Errorf("error from set locale: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.MISession, err = app.NewSession(destinationOptions)
|
c.miSession, err = app.NewSession(destinationOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error from create NewSession: %w", err)
|
return fmt.Errorf("error from create NewSession: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithCollectors To be called by the exporter for collector initialization.
|
||||||
|
func (c *Collection) WithCollectors(collectors []string) (*Collection, error) {
|
||||||
|
metricCollectors := &Collection{
|
||||||
|
miSession: c.miSession,
|
||||||
|
startTime: c.startTime,
|
||||||
|
concurrencyCh: c.concurrencyCh,
|
||||||
|
scrapeDurationDesc: c.scrapeDurationDesc,
|
||||||
|
collectorScrapeDurationDesc: c.collectorScrapeDurationDesc,
|
||||||
|
collectorScrapeSuccessDesc: c.collectorScrapeSuccessDesc,
|
||||||
|
collectorScrapeTimeoutDesc: c.collectorScrapeTimeoutDesc,
|
||||||
|
collectors: maps.Clone(c.collectors),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := metricCollectors.Enable(collectors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return metricCollectors, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Collection) GetStartTime() gotime.Time {
|
||||||
|
return c.startTime
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ import (
|
|||||||
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
|
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/os"
|
"github.com/prometheus-community/windows_exporter/internal/collector/os"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
|
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/collector/performancecounter"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
|
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
|
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/process"
|
"github.com/prometheus-community/windows_exporter/internal/collector/process"
|
||||||
@@ -67,54 +67,54 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
AD ad.Config `yaml:"ad"`
|
AD ad.Config `yaml:"ad"`
|
||||||
ADCS adcs.Config `yaml:"adcs"`
|
ADCS adcs.Config `yaml:"adcs"`
|
||||||
ADFS adfs.Config `yaml:"adfs"`
|
ADFS adfs.Config `yaml:"adfs"`
|
||||||
Cache cache.Config `yaml:"cache"`
|
Cache cache.Config `yaml:"cache"`
|
||||||
Container container.Config `yaml:"container"`
|
Container container.Config `yaml:"container"`
|
||||||
CPU cpu.Config `yaml:"cpu"`
|
CPU cpu.Config `yaml:"cpu"`
|
||||||
CPUInfo cpu_info.Config `yaml:"cpu_info"`
|
CPUInfo cpu_info.Config `yaml:"cpu_info"`
|
||||||
Cs cs.Config `yaml:"cs"`
|
Cs cs.Config `yaml:"cs"`
|
||||||
DFSR dfsr.Config `yaml:"dfsr"`
|
DFSR dfsr.Config `yaml:"dfsr"`
|
||||||
Dhcp dhcp.Config `yaml:"dhcp"`
|
Dhcp dhcp.Config `yaml:"dhcp"`
|
||||||
DiskDrive diskdrive.Config `yaml:"disk_drive"`
|
DiskDrive diskdrive.Config `yaml:"disk_drive"`
|
||||||
DNS dns.Config `yaml:"dns"`
|
DNS dns.Config `yaml:"dns"`
|
||||||
Exchange exchange.Config `yaml:"exchange"`
|
Exchange exchange.Config `yaml:"exchange"`
|
||||||
Filetime filetime.Config `yaml:"filetime"`
|
Filetime filetime.Config `yaml:"filetime"`
|
||||||
Fsrmquota fsrmquota.Config `yaml:"fsrmquota"`
|
Fsrmquota fsrmquota.Config `yaml:"fsrmquota"`
|
||||||
HyperV hyperv.Config `yaml:"hyper_v"`
|
HyperV hyperv.Config `yaml:"hyper_v"`
|
||||||
IIS iis.Config `yaml:"iis"`
|
IIS iis.Config `yaml:"iis"`
|
||||||
License license.Config `yaml:"license"`
|
License license.Config `yaml:"license"`
|
||||||
LogicalDisk logical_disk.Config `yaml:"logical_disk"`
|
LogicalDisk logical_disk.Config `yaml:"logical_disk"`
|
||||||
Logon logon.Config `yaml:"logon"`
|
Logon logon.Config `yaml:"logon"`
|
||||||
Memory memory.Config `yaml:"memory"`
|
Memory memory.Config `yaml:"memory"`
|
||||||
MSCluster mscluster.Config `yaml:"ms_cluster"`
|
MSCluster mscluster.Config `yaml:"ms_cluster"`
|
||||||
Msmq msmq.Config `yaml:"msmq"`
|
Msmq msmq.Config `yaml:"msmq"`
|
||||||
Mssql mssql.Config `yaml:"mssql"`
|
Mssql mssql.Config `yaml:"mssql"`
|
||||||
Net net.Config `yaml:"net"`
|
Net net.Config `yaml:"net"`
|
||||||
NetFramework netframework.Config `yaml:"net_framework"`
|
NetFramework netframework.Config `yaml:"net_framework"`
|
||||||
Nps nps.Config `yaml:"nps"`
|
Nps nps.Config `yaml:"nps"`
|
||||||
OS os.Config `yaml:"os"`
|
OS os.Config `yaml:"os"`
|
||||||
Paging pagefile.Config `yaml:"paging"`
|
Paging pagefile.Config `yaml:"paging"`
|
||||||
PerfData perfdata.Config `yaml:"perf_data"`
|
PerformanceCounter performancecounter.Config `yaml:"performance_counter"`
|
||||||
PhysicalDisk physical_disk.Config `yaml:"physical_disk"`
|
PhysicalDisk physical_disk.Config `yaml:"physical_disk"`
|
||||||
Printer printer.Config `yaml:"printer"`
|
Printer printer.Config `yaml:"printer"`
|
||||||
Process process.Config `yaml:"process"`
|
Process process.Config `yaml:"process"`
|
||||||
RemoteFx remote_fx.Config `yaml:"remote_fx"`
|
RemoteFx remote_fx.Config `yaml:"remote_fx"`
|
||||||
ScheduledTask scheduled_task.Config `yaml:"scheduled_task"`
|
ScheduledTask scheduled_task.Config `yaml:"scheduled_task"`
|
||||||
Service service.Config `yaml:"service"`
|
Service service.Config `yaml:"service"`
|
||||||
SMB smb.Config `yaml:"smb"`
|
SMB smb.Config `yaml:"smb"`
|
||||||
SMBClient smbclient.Config `yaml:"smb_client"`
|
SMBClient smbclient.Config `yaml:"smb_client"`
|
||||||
SMTP smtp.Config `yaml:"smtp"`
|
SMTP smtp.Config `yaml:"smtp"`
|
||||||
System system.Config `yaml:"system"`
|
System system.Config `yaml:"system"`
|
||||||
TCP tcp.Config `yaml:"tcp"`
|
TCP tcp.Config `yaml:"tcp"`
|
||||||
TerminalServices terminal_services.Config `yaml:"terminal_services"`
|
TerminalServices terminal_services.Config `yaml:"terminal_services"`
|
||||||
Textfile textfile.Config `yaml:"textfile"`
|
Textfile textfile.Config `yaml:"textfile"`
|
||||||
ThermalZone thermalzone.Config `yaml:"thermal_zone"`
|
ThermalZone thermalzone.Config `yaml:"thermal_zone"`
|
||||||
Time time.Config `yaml:"time"`
|
Time time.Config `yaml:"time"`
|
||||||
UDP udp.Config `yaml:"udp"`
|
UDP udp.Config `yaml:"udp"`
|
||||||
Update update.Config `yaml:"update"`
|
Update update.Config `yaml:"update"`
|
||||||
Vmware vmware.Config `yaml:"vmware"`
|
Vmware vmware.Config `yaml:"vmware"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigDefaults Is an interface to be used by the external libraries. It holds all ConfigDefaults form all collectors
|
// ConfigDefaults Is an interface to be used by the external libraries. It holds all ConfigDefaults form all collectors
|
||||||
@@ -122,52 +122,52 @@ type Config struct {
|
|||||||
//nolint:gochecknoglobals
|
//nolint:gochecknoglobals
|
||||||
//goland:noinspection GoUnusedGlobalVariable
|
//goland:noinspection GoUnusedGlobalVariable
|
||||||
var ConfigDefaults = Config{
|
var ConfigDefaults = Config{
|
||||||
AD: ad.ConfigDefaults,
|
AD: ad.ConfigDefaults,
|
||||||
ADCS: adcs.ConfigDefaults,
|
ADCS: adcs.ConfigDefaults,
|
||||||
ADFS: adfs.ConfigDefaults,
|
ADFS: adfs.ConfigDefaults,
|
||||||
Cache: cache.ConfigDefaults,
|
Cache: cache.ConfigDefaults,
|
||||||
Container: container.ConfigDefaults,
|
Container: container.ConfigDefaults,
|
||||||
CPU: cpu.ConfigDefaults,
|
CPU: cpu.ConfigDefaults,
|
||||||
CPUInfo: cpu_info.ConfigDefaults,
|
CPUInfo: cpu_info.ConfigDefaults,
|
||||||
Cs: cs.ConfigDefaults,
|
Cs: cs.ConfigDefaults,
|
||||||
DFSR: dfsr.ConfigDefaults,
|
DFSR: dfsr.ConfigDefaults,
|
||||||
Dhcp: dhcp.ConfigDefaults,
|
Dhcp: dhcp.ConfigDefaults,
|
||||||
DiskDrive: diskdrive.ConfigDefaults,
|
DiskDrive: diskdrive.ConfigDefaults,
|
||||||
DNS: dns.ConfigDefaults,
|
DNS: dns.ConfigDefaults,
|
||||||
Exchange: exchange.ConfigDefaults,
|
Exchange: exchange.ConfigDefaults,
|
||||||
Filetime: filetime.ConfigDefaults,
|
Filetime: filetime.ConfigDefaults,
|
||||||
Fsrmquota: fsrmquota.ConfigDefaults,
|
Fsrmquota: fsrmquota.ConfigDefaults,
|
||||||
HyperV: hyperv.ConfigDefaults,
|
HyperV: hyperv.ConfigDefaults,
|
||||||
IIS: iis.ConfigDefaults,
|
IIS: iis.ConfigDefaults,
|
||||||
License: license.ConfigDefaults,
|
License: license.ConfigDefaults,
|
||||||
LogicalDisk: logical_disk.ConfigDefaults,
|
LogicalDisk: logical_disk.ConfigDefaults,
|
||||||
Logon: logon.ConfigDefaults,
|
Logon: logon.ConfigDefaults,
|
||||||
Memory: memory.ConfigDefaults,
|
Memory: memory.ConfigDefaults,
|
||||||
MSCluster: mscluster.ConfigDefaults,
|
MSCluster: mscluster.ConfigDefaults,
|
||||||
Msmq: msmq.ConfigDefaults,
|
Msmq: msmq.ConfigDefaults,
|
||||||
Mssql: mssql.ConfigDefaults,
|
Mssql: mssql.ConfigDefaults,
|
||||||
Net: net.ConfigDefaults,
|
Net: net.ConfigDefaults,
|
||||||
NetFramework: netframework.ConfigDefaults,
|
NetFramework: netframework.ConfigDefaults,
|
||||||
Nps: nps.ConfigDefaults,
|
Nps: nps.ConfigDefaults,
|
||||||
OS: os.ConfigDefaults,
|
OS: os.ConfigDefaults,
|
||||||
Paging: pagefile.ConfigDefaults,
|
Paging: pagefile.ConfigDefaults,
|
||||||
PerfData: perfdata.ConfigDefaults,
|
PerformanceCounter: performancecounter.ConfigDefaults,
|
||||||
PhysicalDisk: physical_disk.ConfigDefaults,
|
PhysicalDisk: physical_disk.ConfigDefaults,
|
||||||
Printer: printer.ConfigDefaults,
|
Printer: printer.ConfigDefaults,
|
||||||
Process: process.ConfigDefaults,
|
Process: process.ConfigDefaults,
|
||||||
RemoteFx: remote_fx.ConfigDefaults,
|
RemoteFx: remote_fx.ConfigDefaults,
|
||||||
ScheduledTask: scheduled_task.ConfigDefaults,
|
ScheduledTask: scheduled_task.ConfigDefaults,
|
||||||
Service: service.ConfigDefaults,
|
Service: service.ConfigDefaults,
|
||||||
SMB: smb.ConfigDefaults,
|
SMB: smb.ConfigDefaults,
|
||||||
SMBClient: smbclient.ConfigDefaults,
|
SMBClient: smbclient.ConfigDefaults,
|
||||||
SMTP: smtp.ConfigDefaults,
|
SMTP: smtp.ConfigDefaults,
|
||||||
System: system.ConfigDefaults,
|
System: system.ConfigDefaults,
|
||||||
TCP: tcp.ConfigDefaults,
|
TCP: tcp.ConfigDefaults,
|
||||||
TerminalServices: terminal_services.ConfigDefaults,
|
TerminalServices: terminal_services.ConfigDefaults,
|
||||||
Textfile: textfile.ConfigDefaults,
|
Textfile: textfile.ConfigDefaults,
|
||||||
ThermalZone: thermalzone.ConfigDefaults,
|
ThermalZone: thermalzone.ConfigDefaults,
|
||||||
Time: time.ConfigDefaults,
|
Time: time.ConfigDefaults,
|
||||||
UDP: udp.ConfigDefaults,
|
UDP: udp.ConfigDefaults,
|
||||||
Update: update.ConfigDefaults,
|
Update: update.ConfigDefaults,
|
||||||
Vmware: vmware.ConfigDefaults,
|
Vmware: vmware.ConfigDefaults,
|
||||||
}
|
}
|
||||||
|
|||||||
62
pkg/collector/handler.go
Normal file
62
pkg/collector/handler.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2024 The Prometheus Authors
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface guard.
|
||||||
|
var _ prometheus.Collector = (*Handler)(nil)
|
||||||
|
|
||||||
|
// Handler implements [prometheus.Collector] for a set of Windows Collection.
|
||||||
|
type Handler struct {
|
||||||
|
maxScrapeDuration time.Duration
|
||||||
|
logger *slog.Logger
|
||||||
|
collection *Collection
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHandler returns a new Handler that implements a [prometheus.Collector] for the given metrics Collection.
|
||||||
|
func (c *Collection) NewHandler(maxScrapeDuration time.Duration, logger *slog.Logger, collectors []string) (*Handler, error) {
|
||||||
|
collection := c
|
||||||
|
|
||||||
|
if len(collectors) != 0 {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
collection, err = c.WithCollectors(collectors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create handler with collectors: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Handler{
|
||||||
|
maxScrapeDuration: maxScrapeDuration,
|
||||||
|
collection: collection,
|
||||||
|
logger: logger,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Handler) Describe(_ chan<- *prometheus.Desc) {}
|
||||||
|
|
||||||
|
// Collect sends the collected metrics from each of the Collection to
|
||||||
|
// prometheus.
|
||||||
|
func (p *Handler) Collect(ch chan<- prometheus.Metric) {
|
||||||
|
p.collection.collectAll(ch, p.logger, p.maxScrapeDuration)
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ import (
|
|||||||
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
|
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/os"
|
"github.com/prometheus-community/windows_exporter/internal/collector/os"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
|
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/collector/performancecounter"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
|
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
|
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/process"
|
"github.com/prometheus-community/windows_exporter/internal/collector/process"
|
||||||
@@ -78,54 +78,54 @@ func NewBuilderWithFlags[C Collector](fn BuilderWithFlags[C]) BuilderWithFlags[C
|
|||||||
|
|
||||||
//nolint:gochecknoglobals
|
//nolint:gochecknoglobals
|
||||||
var BuildersWithFlags = map[string]BuilderWithFlags[Collector]{
|
var BuildersWithFlags = map[string]BuilderWithFlags[Collector]{
|
||||||
ad.Name: NewBuilderWithFlags(ad.NewWithFlags),
|
ad.Name: NewBuilderWithFlags(ad.NewWithFlags),
|
||||||
adcs.Name: NewBuilderWithFlags(adcs.NewWithFlags),
|
adcs.Name: NewBuilderWithFlags(adcs.NewWithFlags),
|
||||||
adfs.Name: NewBuilderWithFlags(adfs.NewWithFlags),
|
adfs.Name: NewBuilderWithFlags(adfs.NewWithFlags),
|
||||||
cache.Name: NewBuilderWithFlags(cache.NewWithFlags),
|
cache.Name: NewBuilderWithFlags(cache.NewWithFlags),
|
||||||
container.Name: NewBuilderWithFlags(container.NewWithFlags),
|
container.Name: NewBuilderWithFlags(container.NewWithFlags),
|
||||||
cpu.Name: NewBuilderWithFlags(cpu.NewWithFlags),
|
cpu.Name: NewBuilderWithFlags(cpu.NewWithFlags),
|
||||||
cpu_info.Name: NewBuilderWithFlags(cpu_info.NewWithFlags),
|
cpu_info.Name: NewBuilderWithFlags(cpu_info.NewWithFlags),
|
||||||
cs.Name: NewBuilderWithFlags(cs.NewWithFlags),
|
cs.Name: NewBuilderWithFlags(cs.NewWithFlags),
|
||||||
dfsr.Name: NewBuilderWithFlags(dfsr.NewWithFlags),
|
dfsr.Name: NewBuilderWithFlags(dfsr.NewWithFlags),
|
||||||
dhcp.Name: NewBuilderWithFlags(dhcp.NewWithFlags),
|
dhcp.Name: NewBuilderWithFlags(dhcp.NewWithFlags),
|
||||||
diskdrive.Name: NewBuilderWithFlags(diskdrive.NewWithFlags),
|
diskdrive.Name: NewBuilderWithFlags(diskdrive.NewWithFlags),
|
||||||
dns.Name: NewBuilderWithFlags(dns.NewWithFlags),
|
dns.Name: NewBuilderWithFlags(dns.NewWithFlags),
|
||||||
exchange.Name: NewBuilderWithFlags(exchange.NewWithFlags),
|
exchange.Name: NewBuilderWithFlags(exchange.NewWithFlags),
|
||||||
filetime.Name: NewBuilderWithFlags(filetime.NewWithFlags),
|
filetime.Name: NewBuilderWithFlags(filetime.NewWithFlags),
|
||||||
fsrmquota.Name: NewBuilderWithFlags(fsrmquota.NewWithFlags),
|
fsrmquota.Name: NewBuilderWithFlags(fsrmquota.NewWithFlags),
|
||||||
hyperv.Name: NewBuilderWithFlags(hyperv.NewWithFlags),
|
hyperv.Name: NewBuilderWithFlags(hyperv.NewWithFlags),
|
||||||
iis.Name: NewBuilderWithFlags(iis.NewWithFlags),
|
iis.Name: NewBuilderWithFlags(iis.NewWithFlags),
|
||||||
license.Name: NewBuilderWithFlags(license.NewWithFlags),
|
license.Name: NewBuilderWithFlags(license.NewWithFlags),
|
||||||
logical_disk.Name: NewBuilderWithFlags(logical_disk.NewWithFlags),
|
logical_disk.Name: NewBuilderWithFlags(logical_disk.NewWithFlags),
|
||||||
logon.Name: NewBuilderWithFlags(logon.NewWithFlags),
|
logon.Name: NewBuilderWithFlags(logon.NewWithFlags),
|
||||||
memory.Name: NewBuilderWithFlags(memory.NewWithFlags),
|
memory.Name: NewBuilderWithFlags(memory.NewWithFlags),
|
||||||
mscluster.Name: NewBuilderWithFlags(mscluster.NewWithFlags),
|
mscluster.Name: NewBuilderWithFlags(mscluster.NewWithFlags),
|
||||||
msmq.Name: NewBuilderWithFlags(msmq.NewWithFlags),
|
msmq.Name: NewBuilderWithFlags(msmq.NewWithFlags),
|
||||||
mssql.Name: NewBuilderWithFlags(mssql.NewWithFlags),
|
mssql.Name: NewBuilderWithFlags(mssql.NewWithFlags),
|
||||||
net.Name: NewBuilderWithFlags(net.NewWithFlags),
|
net.Name: NewBuilderWithFlags(net.NewWithFlags),
|
||||||
netframework.Name: NewBuilderWithFlags(netframework.NewWithFlags),
|
netframework.Name: NewBuilderWithFlags(netframework.NewWithFlags),
|
||||||
nps.Name: NewBuilderWithFlags(nps.NewWithFlags),
|
nps.Name: NewBuilderWithFlags(nps.NewWithFlags),
|
||||||
os.Name: NewBuilderWithFlags(os.NewWithFlags),
|
os.Name: NewBuilderWithFlags(os.NewWithFlags),
|
||||||
pagefile.Name: NewBuilderWithFlags(pagefile.NewWithFlags),
|
pagefile.Name: NewBuilderWithFlags(pagefile.NewWithFlags),
|
||||||
perfdata.Name: NewBuilderWithFlags(perfdata.NewWithFlags),
|
performancecounter.Name: NewBuilderWithFlags(performancecounter.NewWithFlags),
|
||||||
physical_disk.Name: NewBuilderWithFlags(physical_disk.NewWithFlags),
|
physical_disk.Name: NewBuilderWithFlags(physical_disk.NewWithFlags),
|
||||||
printer.Name: NewBuilderWithFlags(printer.NewWithFlags),
|
printer.Name: NewBuilderWithFlags(printer.NewWithFlags),
|
||||||
process.Name: NewBuilderWithFlags(process.NewWithFlags),
|
process.Name: NewBuilderWithFlags(process.NewWithFlags),
|
||||||
remote_fx.Name: NewBuilderWithFlags(remote_fx.NewWithFlags),
|
remote_fx.Name: NewBuilderWithFlags(remote_fx.NewWithFlags),
|
||||||
scheduled_task.Name: NewBuilderWithFlags(scheduled_task.NewWithFlags),
|
scheduled_task.Name: NewBuilderWithFlags(scheduled_task.NewWithFlags),
|
||||||
service.Name: NewBuilderWithFlags(service.NewWithFlags),
|
service.Name: NewBuilderWithFlags(service.NewWithFlags),
|
||||||
smb.Name: NewBuilderWithFlags(smb.NewWithFlags),
|
smb.Name: NewBuilderWithFlags(smb.NewWithFlags),
|
||||||
smbclient.Name: NewBuilderWithFlags(smbclient.NewWithFlags),
|
smbclient.Name: NewBuilderWithFlags(smbclient.NewWithFlags),
|
||||||
smtp.Name: NewBuilderWithFlags(smtp.NewWithFlags),
|
smtp.Name: NewBuilderWithFlags(smtp.NewWithFlags),
|
||||||
system.Name: NewBuilderWithFlags(system.NewWithFlags),
|
system.Name: NewBuilderWithFlags(system.NewWithFlags),
|
||||||
tcp.Name: NewBuilderWithFlags(tcp.NewWithFlags),
|
tcp.Name: NewBuilderWithFlags(tcp.NewWithFlags),
|
||||||
terminal_services.Name: NewBuilderWithFlags(terminal_services.NewWithFlags),
|
terminal_services.Name: NewBuilderWithFlags(terminal_services.NewWithFlags),
|
||||||
textfile.Name: NewBuilderWithFlags(textfile.NewWithFlags),
|
textfile.Name: NewBuilderWithFlags(textfile.NewWithFlags),
|
||||||
thermalzone.Name: NewBuilderWithFlags(thermalzone.NewWithFlags),
|
thermalzone.Name: NewBuilderWithFlags(thermalzone.NewWithFlags),
|
||||||
time.Name: NewBuilderWithFlags(time.NewWithFlags),
|
time.Name: NewBuilderWithFlags(time.NewWithFlags),
|
||||||
udp.Name: NewBuilderWithFlags(udp.NewWithFlags),
|
udp.Name: NewBuilderWithFlags(udp.NewWithFlags),
|
||||||
update.Name: NewBuilderWithFlags(update.NewWithFlags),
|
update.Name: NewBuilderWithFlags(update.NewWithFlags),
|
||||||
vmware.Name: NewBuilderWithFlags(vmware.NewWithFlags),
|
vmware.Name: NewBuilderWithFlags(vmware.NewWithFlags),
|
||||||
}
|
}
|
||||||
|
|
||||||
func Available() []string {
|
func Available() []string {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package collector
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
@@ -25,10 +26,16 @@ import (
|
|||||||
|
|
||||||
const DefaultCollectors = "cpu,cs,memory,logical_disk,physical_disk,net,os,service,system"
|
const DefaultCollectors = "cpu,cs,memory,logical_disk,physical_disk,net,os,service,system"
|
||||||
|
|
||||||
type MetricCollectors struct {
|
type Collection struct {
|
||||||
Collectors Map
|
collectors Map
|
||||||
MISession *mi.Session
|
miSession *mi.Session
|
||||||
PerfCounterQuery string
|
startTime time.Time
|
||||||
|
concurrencyCh chan struct{}
|
||||||
|
|
||||||
|
scrapeDurationDesc *prometheus.Desc
|
||||||
|
collectorScrapeDurationDesc *prometheus.Desc
|
||||||
|
collectorScrapeSuccessDesc *prometheus.Desc
|
||||||
|
collectorScrapeTimeoutDesc *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ windows_exporter_collector_success{collector="memory"} 1
|
|||||||
windows_exporter_collector_success{collector="net"} 1
|
windows_exporter_collector_success{collector="net"} 1
|
||||||
windows_exporter_collector_success{collector="os"} 1
|
windows_exporter_collector_success{collector="os"} 1
|
||||||
windows_exporter_collector_success{collector="pagefile"} 1
|
windows_exporter_collector_success{collector="pagefile"} 1
|
||||||
windows_exporter_collector_success{collector="perfdata"} 1
|
windows_exporter_collector_success{collector="performancecounter"} 1
|
||||||
windows_exporter_collector_success{collector="physical_disk"} 1
|
windows_exporter_collector_success{collector="physical_disk"} 1
|
||||||
windows_exporter_collector_success{collector="printer"} 1
|
windows_exporter_collector_success{collector="printer"} 1
|
||||||
windows_exporter_collector_success{collector="process"} 1
|
windows_exporter_collector_success{collector="process"} 1
|
||||||
@@ -146,7 +146,7 @@ windows_exporter_collector_timeout{collector="memory"} 0
|
|||||||
windows_exporter_collector_timeout{collector="net"} 0
|
windows_exporter_collector_timeout{collector="net"} 0
|
||||||
windows_exporter_collector_timeout{collector="os"} 0
|
windows_exporter_collector_timeout{collector="os"} 0
|
||||||
windows_exporter_collector_timeout{collector="pagefile"} 0
|
windows_exporter_collector_timeout{collector="pagefile"} 0
|
||||||
windows_exporter_collector_timeout{collector="perfdata"} 0
|
windows_exporter_collector_timeout{collector="performancecounter"} 0
|
||||||
windows_exporter_collector_timeout{collector="physical_disk"} 0
|
windows_exporter_collector_timeout{collector="physical_disk"} 0
|
||||||
windows_exporter_collector_timeout{collector="printer"} 0
|
windows_exporter_collector_timeout{collector="printer"} 0
|
||||||
windows_exporter_collector_timeout{collector="process"} 0
|
windows_exporter_collector_timeout{collector="process"} 0
|
||||||
@@ -319,12 +319,10 @@ windows_exporter_collector_timeout{collector="udp"} 0
|
|||||||
# TYPE windows_pagefile_free_bytes gauge
|
# TYPE windows_pagefile_free_bytes gauge
|
||||||
# HELP windows_pagefile_limit_bytes Number of bytes that can be stored in the operating system paging files. 0 (zero) indicates that there are no paging files
|
# HELP windows_pagefile_limit_bytes Number of bytes that can be stored in the operating system paging files. 0 (zero) indicates that there are no paging files
|
||||||
# TYPE windows_pagefile_limit_bytes gauge
|
# TYPE windows_pagefile_limit_bytes gauge
|
||||||
# HELP windows_perfdata_memory_cache_faults_sec Performance data for \\Memory\\Cache Faults/sec
|
# HELP windows_performancecounter_memory_cache_faults_sec windows_exporter: custom Performance Counter metric
|
||||||
# TYPE windows_perfdata_memory_cache_faults_sec counter
|
# TYPE windows_performancecounter_memory_cache_faults_sec counter
|
||||||
# HELP windows_perfdata_processor_information__privileged_time Performance data for \\Processor Information\\% Privileged Time
|
# HELP windows_performancecounter_processor_information_processor_time windows_exporter: custom Performance Counter metric
|
||||||
# TYPE windows_perfdata_processor_information__privileged_time counter
|
# TYPE windows_performancecounter_processor_information_processor_time counter
|
||||||
# HELP windows_perfdata_processor_information__processor_time Performance data for \\Processor Information\\% Processor Time
|
|
||||||
# TYPE windows_perfdata_processor_information__processor_time counter
|
|
||||||
# HELP windows_physical_disk_idle_seconds_total Seconds that the disk was idle (PhysicalDisk.PercentIdleTime)
|
# HELP windows_physical_disk_idle_seconds_total Seconds that the disk was idle (PhysicalDisk.PercentIdleTime)
|
||||||
# TYPE windows_physical_disk_idle_seconds_total counter
|
# TYPE windows_physical_disk_idle_seconds_total counter
|
||||||
# HELP windows_physical_disk_read_bytes_total The number of bytes transferred from the disk during read operations (PhysicalDisk.DiskReadBytesPerSec)
|
# HELP windows_physical_disk_read_bytes_total The number of bytes transferred from the disk during read operations (PhysicalDisk.DiskReadBytesPerSec)
|
||||||
@@ -387,6 +385,8 @@ windows_service_state{name="Themes",state="running"} 1
|
|||||||
windows_service_state{name="Themes",state="start pending"} 0
|
windows_service_state{name="Themes",state="start pending"} 0
|
||||||
windows_service_state{name="Themes",state="stop pending"} 0
|
windows_service_state{name="Themes",state="stop pending"} 0
|
||||||
windows_service_state{name="Themes",state="stopped"} 0
|
windows_service_state{name="Themes",state="stopped"} 0
|
||||||
|
# HELP windows_system_boot_time_timestamp_seconds Unix timestamp of system boot time
|
||||||
|
# TYPE windows_system_boot_time_timestamp_seconds gauge
|
||||||
# HELP windows_system_context_switches_total Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)
|
# HELP windows_system_context_switches_total Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)
|
||||||
# TYPE windows_system_context_switches_total counter
|
# TYPE windows_system_context_switches_total counter
|
||||||
# HELP windows_system_exception_dispatches_total Total number of exceptions dispatched (WMI source: PerfOS_System.ExceptionDispatchesPersec)
|
# HELP windows_system_exception_dispatches_total Total number of exceptions dispatched (WMI source: PerfOS_System.ExceptionDispatchesPersec)
|
||||||
@@ -399,8 +399,6 @@ windows_service_state{name="Themes",state="stopped"} 0
|
|||||||
# TYPE windows_system_processor_queue_length gauge
|
# TYPE windows_system_processor_queue_length gauge
|
||||||
# HELP windows_system_system_calls_total Total number of system calls (WMI source: PerfOS_System.SystemCallsPersec)
|
# HELP windows_system_system_calls_total Total number of system calls (WMI source: PerfOS_System.SystemCallsPersec)
|
||||||
# TYPE windows_system_system_calls_total counter
|
# TYPE windows_system_system_calls_total counter
|
||||||
# HELP windows_system_system_up_time System boot time (WMI source: PerfOS_System.SystemUpTime)
|
|
||||||
# TYPE windows_system_system_up_time gauge
|
|
||||||
# HELP windows_system_threads Current number of threads (WMI source: PerfOS_System.Threads)
|
# HELP windows_system_threads Current number of threads (WMI source: PerfOS_System.Threads)
|
||||||
# TYPE windows_system_threads gauge
|
# TYPE windows_system_threads gauge
|
||||||
# HELP windows_tcp_connection_failures_total (TCP.ConnectionFailures)
|
# HELP windows_tcp_connection_failures_total (TCP.ConnectionFailures)
|
||||||
|
|||||||
@@ -18,15 +18,15 @@ mkdir $textfile_dir | Out-Null
|
|||||||
Copy-Item 'e2e-textfile.prom' -Destination "$($textfile_dir)/e2e-textfile.prom"
|
Copy-Item 'e2e-textfile.prom' -Destination "$($textfile_dir)/e2e-textfile.prom"
|
||||||
|
|
||||||
# Omit dynamic collector information that will change after each run
|
# Omit dynamic collector information that will change after each run
|
||||||
$skip_re = "^(go_|windows_exporter_build_info|windows_exporter_collector_duration_seconds|windows_exporter_scrape_duration_seconds|process_|windows_textfile_mtime_seconds|windows_cpu|windows_cs|windows_cache|windows_logon|windows_pagefile|windows_logical_disk|windows_physical_disk|windows_memory|windows_net|windows_os|windows_process|windows_service_process|windows_printer|windows_udp|windows_tcp|windows_system|windows_time|windows_session|windows_perfdata|windows_textfile_mtime_seconds)"
|
$skip_re = "^(go_|windows_exporter_build_info|windows_exporter_collector_duration_seconds|windows_exporter_scrape_duration_seconds|process_|windows_textfile_mtime_seconds|windows_cpu|windows_cs|windows_cache|windows_logon|windows_pagefile|windows_logical_disk|windows_physical_disk|windows_memory|windows_net|windows_os|windows_process|windows_service_process|windows_printer|windows_udp|windows_tcp|windows_system|windows_time|windows_session|windows_performancecounter|windows_performancecounter|windows_textfile_mtime_seconds)"
|
||||||
|
|
||||||
# Start process in background, awaiting HTTP requests.
|
# Start process in background, awaiting HTTP requests.
|
||||||
# Use default collectors, port and address: http://localhost:9182/metrics
|
# Use default collectors, port and address: http://localhost:9182/metrics
|
||||||
$exporter_proc = Start-Process `
|
$exporter_proc = Start-Process `
|
||||||
-PassThru `
|
-PassThru `
|
||||||
-FilePath ..\windows_exporter.exe `
|
-FilePath ..\windows_exporter.exe `
|
||||||
-ArgumentList "--log.level=debug","--web.disable-exporter-metrics","--collectors.enabled=[defaults],cpu_info,textfile,process,pagefile,perfdata,scheduled_task,tcp,udp,time,system,service,logical_disk,printer,os,net,memory,logon,cache","--collector.process.include=explorer.exe","--collector.scheduled_task.include=.*GAEvents","--collector.service.include=Themes","--collector.textfile.directories=$($textfile_dir)",@"
|
-ArgumentList "--log.level=debug","--web.disable-exporter-metrics","--collectors.enabled=[defaults],cpu_info,textfile,process,pagefile,performancecounter,scheduled_task,tcp,udp,time,system,service,logical_disk,printer,os,net,memory,logon,cache","--collector.process.include=explorer.exe","--collector.scheduled_task.include=.*GAEvents","--collector.service.include=Themes","--collector.textfile.directories=$($textfile_dir)",@"
|
||||||
--collector.perfdata.objects="[{\"object\":\"Processor Information\",\"instance_label\":\"core\",\"instances\":[\"*\"],\"counters\":{\"% Processor Time\":{},\"% Privileged Time\":{}}},{\"object\":\"Memory\",\"counters\":{\"Cache Faults/sec\":{\"type\":\"counter\"}}}]"
|
--collector.performancecounter.objects="[{\"object\":\"Processor Information\",\"instances\":[\"*\"],\"instance_label\":\"core\",\"counters\":[{\"name\":\"% Processor Time\",\"metric\":\"windows_performancecounter_processor_information_processor_time\",\"labels\":{\"state\":\"active\"}},{\"name\":\"% Idle Time\",\"metric\":\"windows_performancecounter_processor_information_processor_time\",\"labels\":{\"state\":\"idle\"}}]},{\"object\":\"Memory\",\"counters\":[{\"name\":\"Cache Faults/sec\",\"type\":\"counter\"}]}]"
|
||||||
"@ `
|
"@ `
|
||||||
-WindowStyle Hidden `
|
-WindowStyle Hidden `
|
||||||
-RedirectStandardOutput "$($temp_dir)/windows_exporter.log" `
|
-RedirectStandardOutput "$($temp_dir)/windows_exporter.log" `
|
||||||
|
|||||||
Reference in New Issue
Block a user