Compare commits

..

14 Commits

Author SHA1 Message Date
Jan-Otto Kröpke
23397701ff pdh/registry: fix panic when T is a struct type (#2366) (#2367)
Co-authored-by: Kayla Ondracek <112117836+kondracek-nr@users.noreply.github.com>
2026-03-20 20:27:02 +01:00
Jan-Otto Kröpke
d93821bf10 gpu: skip Microsoft Basic Render Driver metrics (#2363)
Co-authored-by: Elliot Nevills <elliotnev27@users.noreply.github.com>
2026-03-20 01:47:27 +01:00
renovate[bot]
302043390e chore(deps): update module golang.org/x/time to v0.15.0 (0.31) (#2361)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:41:30 +01:00
renovate[bot]
02b8ab6c11 chore(deps): update module github.com/golang-jwt/jwt/v5 to v5.3.1 (0.31) (#2360)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:41:19 +01:00
renovate[bot]
f8ee898b51 fix(deps): update module github.com/prometheus/exporter-toolkit to v0.15.1 (0.31) (#2355)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:37:56 +01:00
renovate[bot]
2a95da9776 fix(deps): update module github.com/prometheus/common to v0.67.5 (0.31) (#2354)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>
2026-03-20 01:34:11 +01:00
renovate[bot]
71fba4d94d chore(deps): update module github.com/prometheus/procfs to v0.20.1 (0.31) (#2351)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:14:08 +01:00
renovate[bot]
f434749e0f chore(deps): update module go.yaml.in/yaml/v2 to v2.4.4 (0.31) (#2347)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:12:39 +01:00
renovate[bot]
29628fc974 chore(deps): update module google.golang.org/protobuf to v1.36.11 (0.31) (#2348)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:12:08 +01:00
renovate[bot]
92bc41dc70 chore(deps): update dependency golangci/golangci-lint to v2.6.0 (#2246)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>

(cherry picked from commit 3d0587d28c)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2026-03-20 01:11:18 +01:00
renovate[bot]
d197738861 fix(deps): update module github.com/bmatcuk/doublestar/v4 to v4.10.0 (0.31) (#2353)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:02:39 +01:00
renovate[bot]
f56143758b chore(deps): update module github.com/coreos/go-systemd/v22 to v22.7.0 (0.31) (#2350)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:02:27 +01:00
renovate[bot]
e20de61dbe fix(deps): update golang.org/x/ (0.31) (#2352)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:01:59 +01:00
renovate[bot]
278a22fd94 chore(deps): update github actions (0.31) (major) (#2356)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 01:01:52 +01:00
125 changed files with 298 additions and 5433 deletions

View File

@@ -18,7 +18,7 @@ jobs:
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
steps:
- name: git checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set docker hub repo name
@@ -42,7 +42,7 @@ jobs:
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
steps:
- name: git checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set quay.io org name

View File

@@ -91,5 +91,5 @@ jobs:
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
with:
# renovate: github=golangci/golangci-lint
version: v2.11.4
version: v2.4.0
args: "--max-same-issues=0"

View File

@@ -10,6 +10,7 @@ on:
release:
types:
- published
- edited
permissions:
contents: write

View File

@@ -11,7 +11,7 @@ jobs:
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
runs-on: ubuntu-latest
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# opt out of defaults to avoid marking issues as stale and closing them

View File

@@ -15,7 +15,6 @@ linters:
- gocognit
- goconst
- gocyclo
- godoclint
- godot
- lll
- maintidx
@@ -24,7 +23,6 @@ linters:
- paralleltest
- tagliatelle
- testpackage
- unqueryvet
- varnamelen
- wrapcheck
- wsl

View File

@@ -19,7 +19,7 @@
<configuration default="false" name="all" type="GoApplicationRunConfiguration" factoryName="Go Application" folderName="run">
<module name="windows_exporter" />
<working_directory value="$PROJECT_DIR$" />
<parameters value="--web.listen-address=127.0.0.1:9182 --log.level=info --collectors.enabled=ad,adcs,adfs,cache,container,cpu,cpu_info,dfsr,dhcp,diskdrive,dns,exchange,file,fsrmquota,hyperv,iis,license,logical_disk,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,performancecounter --debug.enabled --collector.performancecounter.objects='[{ &quot;name&quot;: &quot;memory&quot;, &quot;type&quot;: &quot;formatted&quot;, &quot;object&quot;: &quot;Memory&quot;, &quot;counters&quot;: [{ &quot;name&quot;:&quot;Cache Faults/sec&quot;, &quot;type&quot;:&quot;counter&quot; }]}]'" />
<parameters value="--web.listen-address=127.0.0.1:9182 --log.level=info --collectors.enabled=ad,adcs,adfs,cache,container,cpu,cpu_info,dfsr,dhcp,diskdrive,dns,exchange,filetime,fsrmquota,hyperv,iis,license,logical_disk,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,performancecounter --debug.enabled --collector.performancecounter.objects='[{ &quot;name&quot;: &quot;memory&quot;, &quot;type&quot;: &quot;formatted&quot;, &quot;object&quot;: &quot;Memory&quot;, &quot;counters&quot;: [{ &quot;name&quot;:&quot;Cache Faults/sec&quot;, &quot;type&quot;:&quot;counter&quot; }]}]'" />
<sudo value="true" />
<kind value="PACKAGE" />
<package value="github.com/prometheus-community/windows_exporter/cmd/windows_exporter" />

View File

@@ -1,11 +1,10 @@
Maintainers in alphabetical order
* [Ben Reedy](https://github.com/breed808) - breed808@breed808.com
* [Calle Pettersson](https://github.com/carlpett) - calle@cape.nu
* [Jan-Otto Kröpke](https://github.com/jkroepke) - github@jkroepke.de
Alumni
* [Brian Brazil](https://github.com/brian-brazil)
* [Calle Pettersson](https://github.com/carlpett)
* [Martin Lindhe](https://github.com/martinlindhe)

View File

@@ -26,7 +26,7 @@ A Prometheus exporter for Windows machines.
| [dhcp](docs/collector.dhcp.md) | DHCP Server | |
| [dns](docs/collector.dns.md) | DNS Server | |
| [exchange](docs/collector.exchange.md) | Exchange metrics | |
| [file](docs/collector.file.md) | File metrics | |
| [filetime](docs/collector.filetime.md) | FileTime metrics | |
| [fsrmquota](docs/collector.fsrmquota.md) | Microsoft File Server Resource Manager (FSRM) Quotas collector | |
| [gpu](docs/collector.gpu.md) | GPU metrics | |
| [hyperv](docs/collector.hyperv.md) | Hyper-V hosts | |
@@ -55,6 +55,7 @@ A Prometheus exporter for Windows machines.
| [tcp](docs/collector.tcp.md) | TCP connections | |
| [terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS) | |
| [textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file | |
| [thermalzone](docs/collector.thermalzone.md) | Thermal information | |
| [time](docs/collector.time.md) | Windows Time Service | |
| [udp](docs/collector.udp.md) | UDP connections | |
| [update](docs/collector.update.md) | Windows Update Service | |

View File

@@ -201,7 +201,7 @@ func isWindowsService() (bool, error) {
}
}
for ; ; parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Add(unsafe.Pointer(parentProcess), uintptr(parentProcess.NextEntryOffset))) {
for ; ; parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Pointer(uintptr(unsafe.Pointer(parentProcess)) + uintptr(parentProcess.NextEntryOffset))) {
if parentProcess.UniqueProcessID == currentProcess.InheritedFromUniqueProcessId {
return strings.EqualFold("services.exe", parentProcess.ImageName.String()), nil
}

View File

@@ -1,13 +0,0 @@
## Sample dashboard for Windows Exporter
This sample dashboard is heavily inspired by [this dashboard in Chinese](https://grafana.com/grafana/dashboards/10467-windows-exporter-for-prometheus-dashboard-cn-v20230531/).
First row shows an Overview of your Windows landscape.
<br/>
![Screenshot of overview row.](dashboard-overview.png)
Second row provides resource details about specific Windows VM picked from the variables at the top.
<br/>
![Screenshot of resource details (part 1).](resource-details-part1.png)
<br/>
![Screenshot of resource details (part 2).](resource-details-part2.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,6 @@ This directory contains documentation of the collectors in the windows_exporter,
- [`diskdrive`](collector.diskdrive.md)
- [`dns`](collector.dns.md)
- [`exchange`](collector.exchange.md)
- [`file`](collector.file.md)
- [`fsrmquota`](collector.fsrmquota.md)
- [`hyperv`](collector.hyperv.md)
- [`iis`](collector.iis.md)
@@ -43,6 +42,7 @@ This directory contains documentation of the collectors in the windows_exporter,
- [`tcp`](collector.tcp.md)
- [`terminal_services`](collector.terminal_services.md)
- [`textfile`](collector.textfile.md)
- [`thermalzone`](collector.thermalzone.md)
- [`time`](collector.time.md)
- [`udp`](collector.udp.md)
- [`update`](collector.update.md)

View File

@@ -48,27 +48,6 @@ Show per-cpu utilisation using the processor utility metrics
```
rate(windows_cpu_processor_utility_total{instance="localhost"}[5m]) / rate(windows_cpu_processor_rtc_total{instance="localhost"}[5m])
```
Show average CPU utilization percentage (like Windows Task Manager)
```
sum by (instance) (
clamp_max(
(
rate(windows_cpu_processor_utility_total{
job=~"$job",
}[1m])
/
rate(windows_cpu_processor_rtc_total{
job=~"$job",
}[1m])
), 100
)
) /
count by (instance) (
windows_cpu_processor_utility_total{
job=~"$job"
}
)
```
Show actual average CPU frequency in Hz
```
avg by(instance) (
@@ -80,36 +59,7 @@ avg by(instance) (
## Alerting examples
#### Average CPU utilization over 1 hour exceeds 80% (New CPU metric)
```yaml
# Alert on hosts with 1h avg CPU more than 80%
- alert: HighCPUUtilization
expr: |
avg_over_time(
(
sum by (instance) (
(
rate(windows_cpu_processor_utility_total{}[1m])
/
rate(windows_cpu_processor_rtc_total{}[1m])
)
) /
count by (instance) (
windows_cpu_processor_utility_total{}
)
)[1h:]
) > 80
for: 1m
labels:
severity: warning
metric_name: CPUUtilization
annotations:
summary: "High CPU utilization on {{ $labels.instance }}"
description: |
CPU utilization on {{ $labels.instance }} has averaged more than 80% over the last hour (current value: {{ printf "%.2f" $value }})
```
#### Average CPU utilization over 1 hour exceeds 80% (Old CPU metric)
**prometheus.rules**
```yaml
# Alert on hosts with more than 80% CPU usage over a 10 minute period
- alert: CpuUsage
@@ -120,10 +70,6 @@ avg by(instance) (
annotations:
summary: "CPU Usage (instance {{ $labels.instance }})"
description: "CPU Usage is more than 80%\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
```
#### CPU not using boost frequencies
```yaml
# Alert on hosts which are not boosting their CPU frequencies
- alert: NoCpuTurbo
expr: |

View File

@@ -30,7 +30,7 @@ groups:
rules:
- alert: Drive_Status
expr: windows_diskdrive_status{status="OK"} != 1
expr: windows_disk_drive_status{status="OK"} != 1
for: 10m
labels:
severity: high

View File

@@ -1,40 +0,0 @@
# file collector
The file collector exposes modified timestamps and file size of files in the filesystem.
The collector
|||
-|-
Metric name prefix | `file`
Enabled by default? | No
## Flags
### `--collector.file.file-patterns`
Comma-separated list of file patterns. Each pattern is a glob pattern that can contain `*`, `?`, and `**` (recursive).
See https://github.com/bmatcuk/doublestar#patterns for an extended description of the pattern syntax.
## Metrics
| Name | Description | Type | Labels |
|----------------------------------------|------------------------|-------|--------|
| `windows_file_mtime_timestamp_seconds` | File modification time | gauge | `file` |
| `windows_file_size_bytes` | File size | gauge | `file` |
### Example metric
```
# HELP windows_file_mtime_timestamp_seconds File modification time
# TYPE windows_file_mtime_timestamp_seconds gauge
windows_file_mtime_timestamp_seconds{file="C:\\Users\\admin\\Desktop\\Dashboard.lnk"} 1.726434517e+09
# HELP windows_file_size_bytes File size
# TYPE windows_file_size_bytes gauge
windows_file_size_bytes{file="C:\\Users\\admin\\Desktop\\Dashboard.lnk"} 123
```
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -0,0 +1,36 @@
# filetime collector
The filetime collector exposes modified timestamps of files in the filesystem.
The collector
|||
-|-
Metric name prefix | `filetime`
Enabled by default? | No
## Flags
### `--collectors.filetime.file-patterns`
Comma-separated list of file patterns. Each pattern is a glob pattern that can contain `*`, `?`, and `**` (recursive).
See https://github.com/bmatcuk/doublestar#patterns for an extended description of the pattern syntax.
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_filetime_mtime_timestamp_seconds` | File modification time | gauge | `file`
### Example metric
```
# HELP windows_filetime_mtime_timestamp_seconds File modification time
# TYPE windows_filetime_mtime_timestamp_seconds gauge
windows_filetime_mtime_timestamp_seconds{file="C:\\Users\\admin\\Desktop\\Dashboard.lnk"} 1.726434517e+09
```
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -154,11 +154,11 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi
### Hyper-V Hypervisor Virtual Processor
| Name | Description | Type | Labels |
|--------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|---------|-----------------------|
| `windows_hyperv_hypervisor_virtual_processor_mode_time_total` | Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote) | counter | `vm`, `core`, `state` |
| `windows_hyperv_hypervisor_virtual_processor_run_time_total` | Time that processor spent | counter | `vm`, `core` |
| `windows_hyperv_hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total` | The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor. | counter | `vm`, `core` |
| Name | Description | Type | Labels |
|--------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|---------|--------------|
| `windows_hyperv_hypervisor_virtual_processor_time_total` | Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote) | counter | `vm`, `core` |
| `windows_hyperv_hypervisor_virtual_processor_total_run_time_total` | Time that processor spent | counter | `vm`, `core` |
| `windows_hyperv_hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total` | The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor. | counter | `vm`, `core` |
### Hyper-V Virtual Network Adapter
@@ -237,7 +237,7 @@ Some metrics explained: https://learn.microsoft.com/en-us/archive/blogs/chrisavi
| `windows_hyperv_virtual_storage_device_bytes_written` | Represents the total number of bytes that have been written on this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_operations_written_total` | Represents the total number of write operations that have occurred on this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_latency_seconds` | Represents the average IO transfer latency for this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_throughput_total` | Represents the total number of 8KB IO transfers completed by this virtual device. | counter | `device` |
| `windows_hyperv_virtual_storage_device_throughput` | Represents the average number of 8KB IO transfers completed by this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_normalized_throughput` | Represents the average number of IO transfers completed by this virtual device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_lower_queue_length` | Represents the average queue length on the underlying storage subsystem for this device. | gauge | `device` |
| `windows_hyperv_virtual_storage_device_lower_latency_seconds` | Represents the average IO transfer latency on the underlying storage subsystem for this virtual device. | gauge | `device` |
@@ -265,19 +265,19 @@ _This collector does not yet have explained examples, we would appreciate your h
## Useful queries
Percent of physical CPU resources used per VM (on instance "localhost")
```
(sum (rate(windows_hyperv_hypervisor_virtual_processor_mode_time_total{state="hypervisor",instance="localhost"}[1m]))) / ignoring(state,vm) group_left max (windows_cpu_logical_processor{instance="localhost"}) / 100000
(sum (rate(windows_hyperv_hypervisor_virtual_processor_time_total{state="hypervisor",instance="localhost"}[1m]))) / ignoring(state,vm) group_left max (windows_cpu_logical_processor{instance="localhost"}) / 100000
```
Percent of physical CPU resources used by all VMs (on all monitored hosts)
```
(sum by (instance)(rate(windows_hyperv_hypervisor_virtual_processor_run_time_total{}[1m]))) / max by (instance)(windows_cpu_logical_processor{}) / 100000
(sum by (instance)(rate(windows_hyperv_hypervisor_virtual_processor_total_run_time_total{}[1m]))) / max by (instance)(windows_cpu_logical_processor{}) / 100000
```
Percent of physical CPU resources by the hosts themselves (on all monitored hosts)
```
(sum by (instance)(rate(windows_hyperv_hypervisor_root_virtual_processor_time_total{state="total"}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
(sum by (instance)(rate(windows_hyperv_hypervisor_root_virtual_processor_total_run_time_total{state="total"}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
```
Percent of physical CPU resources by the hypervisor (on all monitored hosts)
```
(sum by (instance)(rate(windows_hyperv_hypervisor_logical_processor_time_total{}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
(sum by (instance)(rate(windows_hyperv_hypervisor_logical_processor_total_run_time_total{}[1m]))) / sum by (instance)(windows_cpu_logical_processor{}) / 100000
```
## Alerting examples

View File

@@ -5,14 +5,14 @@ The MSCluster_Cluster class is a dynamic WMI class that represents a cluster.
|||
-|-
Metric name prefix | `mscluster`
Classes | `MSCluster_Cluster`,`MSCluster_Network`,`MSCluster_Node`,`MSCluster_Resource`,`MSCluster_ResourceGroup`,`MSCluster_DiskPartition`,`MSFT_VirtualDisk`
Classes | `MSCluster_Cluster`,`MSCluster_Network`,`MSCluster_Node`,`MSCluster_Resource`,`MSCluster_ResourceGroup`
Enabled by default? | No
## Flags
### `--collectors.mscluster.enabled`
Comma-separated list of collectors to use, for example:
`--collectors.mscluster.enabled=cluster,network,node,resource,resouregroup,shared_volumes,virtualdisk`.
`--collectors.mscluster.enabled=cluster,network,node,resource,resouregroup`.
Matching is case-sensitive.
## Metrics
@@ -170,68 +170,17 @@ Matching is case-sensitive.
| `mscluster_resourcegroup_State` | The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending | gauge | `name` |
| `mscluster_resourcegroup_UpdateDomain` | | gauge | `name` |
### Shared Volumes
| Name | Description | Type | Labels |
|------------------------------------------|----------------------------------------------------------------|-------|-----------------------------|
| `mscluster_shared_volumes_info` | Cluster Shared Volumes information (value is always 1) | gauge | `name`,`path`,`volume_guid` |
| `mscluster_shared_volumes_total_bytes` | Total size of the Cluster Shared Volume in bytes | gauge | `name`,`volume_guid` |
| `mscluster_shared_volumes_free_bytes` | Free space on the Cluster Shared Volume in bytes | gauge | `name`,`volume_guid` |
### Virtual Disk
| Name | Description | Type | Labels |
|-----------------------------------------------------------|------------------------------------------------------------------------------------------------|-------|--------|
| `mscluster_virtualdisk_info` | Virtual disk information (value is always 1) | gauge | `name`, `unique_id` |
| `mscluster_virtualdisk_health_status` | Health status of the virtual disk. 0: Healthy, 1: Warning, 2: Unhealthy, 5: Unknown | gauge | `name`, `unique_id` |
| `mscluster_virtualdisk_size_bytes` | Total size of the virtual disk in bytes | gauge | `name`, `unique_id` |
| `mscluster_virtualdisk_footprint_on_pool_bytes` | Physical storage consumed by the virtual disk on the storage pool in bytes | gauge | `name`, `unique_id` |
| `mscluster_virtualdisk_storage_efficiency_percent` | Storage efficiency percentage (Size / FootprintOnPool * 100) | gauge | `name`, `unique_id` |
### Example metric
Query the state of all cluster resource owned by node1
```
windows_mscluster_resource_owner_node{node_name="node1"}
```
Query virtual disk storage efficiency for thin provisioned disks
```
windows_mscluster_virtualdisk_storage_efficiency_percent
```
## Useful queries
Counts the number of Network Name cluster resource
```
count(windows_mscluster_resource_state{type="Network Name"})
```
Find virtual disks with low storage efficiency (over-provisioned)
```
windows_mscluster_virtualdisk_storage_efficiency_percent < 50
```
Calculate total virtual disk capacity vs physical usage
```
sum(windows_mscluster_virtualdisk_size_bytes) / sum(windows_mscluster_virtualdisk_footprint_on_pool_bytes) * 100
```
## Alerting examples
#### Low free space on cluster shared volume
```yaml
# Alerts if volume has less then 20% free space
- alert: LowCSVFreeSpace
expr: |
(
max by (name, cluster) (windows_mscluster_shared_volumes_free_bytes{name!="ClusterPerformanceHistory"})
/
max by (name, cluster) (windows_mscluster_shared_volumes_total_bytes{name!="ClusterPerformanceHistory"})
) * 100 < 20
for: 10m
labels:
severity: warning
annotations:
summary: "Low CSV free space on {{ $labels.name }}"
description: |
Cluster Shared Volume {{ $labels.name }} on cluster {{ $labels.cluster }} has less than 20% free space (current: {{ printf "%.2f" $value }}%)
```
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -72,18 +72,18 @@ Comma-separated list of collectors to use. Defaults to all, if not specified.
| Name | Description | Type | Labels |
|----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------|
| `windows_netframework_clrmemory_allocated_bytes_total` | Displays the total number of bytes allocated on the garbage collection heap. | counter | `process`, `process_id` |
| `windows_netframework_clrmemory_finalization_survivors` | Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_heap_size_bytes` | Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_promoted_bytes` | Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_number_gc_handles` | Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_collections_total` | Displays the number of times the generation objects are garbage collected since the application started. | counter | `process`, `process_id` |
| `windows_netframework_clrmemory_induced_gc_total` | Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect. | counter | `process`, `process_id` |
| `windows_netframework_clrmemory_number_pinned_objects` | Displays the number of pinned objects encountered in the last garbage collection. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_number_sink_blocksinuse` | Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_committed_bytes` | Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_reserved_bytes` | Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_gc_time_percent` | Displays the percentage of time that was spent performing a garbage collection in the last sample. | gauge | `process`, `process_id` |
| `windows_netframework_clrmemory_allocated_bytes_total` | Displays the total number of bytes allocated on the garbage collection heap. | counter | `process` |
| `windows_netframework_clrmemory_finalization_survivors` | Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized. | gauge | `process` |
| `windows_netframework_clrmemory_heap_size_bytes` | Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated. | gauge | `process` |
| `windows_netframework_clrmemory_promoted_bytes` | Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection. | gauge | `process` |
| `windows_netframework_clrmemory_number_gc_handles` | Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment. | gauge | `process` |
| `windows_netframework_clrmemory_collections_total` | Displays the number of times the generation objects are garbage collected since the application started. | counter | `process` |
| `windows_netframework_clrmemory_induced_gc_total` | Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect. | counter | `process` |
| `windows_netframework_clrmemory_number_pinned_objects` | Displays the number of pinned objects encountered in the last garbage collection. | gauge | `process` |
| `windows_netframework_clrmemory_number_sink_blocksinuse` | Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector. | gauge | `process` |
| `windows_netframework_clrmemory_committed_bytes` | Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file. | gauge | `process` |
| `windows_netframework_clrmemory_reserved_bytes` | Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used. | gauge | `process` |
| `windows_netframework_clrmemory_gc_time_percent` | Displays the percentage of time that was spent performing a garbage collection in the last sample. | gauge | `process` |
### CLR Remoting

View File

@@ -14,11 +14,10 @@ None
## Metrics
| Name | Description | Type | Labels |
|----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|-----------------------------------------------------------------------------------------------------------------|
| `windows_os_hostname` | Labelled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain | gauge | `domain`, `fqdn`, `hostname` |
| `windows_os_info` | Contains full product name & version in labels. Note that the `major_version` for Windows 11 is "10"; a build number greater than 22000 represents Windows 11. | gauge | `product`, `version`, `major_version`, `minor_version`, `build_number`, `revision`, `installation_type` |
| `windows_os_install_time_timestamp_seconds` | Unix timestamp of OS installation time | gauge | None |
| Name | Description | Type | Labels |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|------------------------------------------------------------------------|
| `windows_os_hostname` | Labelled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain | gauge | `domain`, `fqdn`, `hostname` |
| `windows_os_info` | Contains full product name & version in labels. Note that the `major_version` for Windows 11 is "10"; a build number greater than 22000 represents Windows 11. | gauge | `product`, `version`, `major_version`, `minor_version`, `build_number` |
### Example metric
@@ -28,29 +27,11 @@ None
windows_os_hostname{domain="",fqdn="PC",hostname="PC"} 1
# HELP windows_os_info Contains full product name & version in labels. Note that the "major_version" for Windows 11 is \\"10\\"; a build number greater than 22000 represents Windows 11.
# TYPE windows_os_info gauge
windows_os_info{build_number="19045",installation_type="Client",major_version="10",minor_version="0",product="Windows 10 Pro",revision="4842",version="10.0.19045"} 1
# HELP windows_os_install_time_timestamp_seconds Unix timestamp of OS installation time
# TYPE windows_os_install_time_timestamp_seconds gauge
windows_os_install_time_timestamp_seconds 1.6725312e+09
windows_os_info{build_number="19045",major_version="10",minor_version="0",product="Windows 10 Pro",revision="4842",version="10.0.19045"} 1
```
## Useful queries
_This collector does not yet have useful queries, we would appreciate your help adding them!_
## Alerting examples
#### Average CPU utilization over 1 hour exceeds 80% (New CPU metric)
```yaml
# Alerts if Agent/Host is down for 5min
- alert: HypervHostDown
expr: up{app="hyper-v"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: Hyper-V host {{ $labels.instance }} is down
description: |
Hyper-V host {{ $labels.instance }} has been unreachable for more than 5 minutes.
Job: {{ $labels.job }}
```
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -260,27 +260,3 @@ collector:
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.
# Examples
## thermalzone collector
```yaml
collector:
performancecounter:
objects: |-
- name: thermalzone
object: "Thermal Zone Information"
instances: ["*"]
type: formatted
counters:
- name: "Temperature"
type: "gauge"
metric: windows_thermalzone_percent_passive_limit
- name: "% Passive Limit"
type: "gauge"
metric: windows_thermalzone_temperature_celsius
- name: "Throttle Reasons"
type: "gauge"
metric: windows_thermalzone_throttle_reasons
```

View File

@@ -10,17 +10,7 @@ Enabled by default? | Yes
## Flags
### `--collector.service.include`
Regexp of service to exclude. Service name (not the display name!) must both
match `include` and not match `exclude` to be included.
Recommended to keep down number of returned metrics.
### `--collector.service.exclude`
Regexp of service to include. Process name (not the display name!) must both
match `include` and not match `exclude` to be included.
Recommended to keep down number of returned metrics.
None
## Metrics

View File

@@ -0,0 +1,32 @@
# thermalzone collector
The thermalzone collector exposes metrics about system temps. Note that temperature is given in Kelvin
|||
-|-
Metric name prefix | `thermalzone`
Classes | [`Win32_PerfRawData_Counters_ThermalZoneInformation`](https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_thermalzoneinformation/#temperature_properties)
Enabled by default? | No
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_thermalzone_percent_passive_limit` | % Passive Limit is the current limit this thermal zone is placing on the devices it controls. A limit of 100% indicates the devices are unconstrained. A limit of 0% indicates the devices are fully constrained. | gauge | None
`windows_thermalzone_temperature_celsius ` | Temperature of the thermal zone, in degrees Celsius. | gauge | None
`windows_thermalzone_throttle_reasons ` | Throttle Reasons indicate reasons why the thermal zone is limiting performance of the devices it controls. 0x0 - The zone is not throttled. 0x1 - The zone is throttled for thermal reasons. 0x2 - The zone is throttled to limit electrical current. | gauge | None
[`Throttle reasons` source](https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/examples--requirements-and-diagnostics)
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -14,11 +14,14 @@ The Windows Update service is responsible for managing the installation of updat
## Flags
### `--collector.update.online`
Whether to search for updates online. If set to `false` via `--no-collector.update.online`, the collector will only list updates that are already found by the Windows Update service.
Set to `true` via `--collector.update.online` to search for updates online, which will take longer to complete.
> [!NOTE]
> The collector name used in the CLI flags is `updates`, while the metric prefix is `update`. This naming mismatch is known and intentional for compatibility reasons.
### `--collector.update.scrape-interval`
### `--collector.updates.online`
Whether to search for updates online. If set to `false`, the collector will only list updates that are already found by the Windows Update service.
Set to `true` to search for updates online, which will take longer to complete.
### `--collector.updates.scrape-interval`
Define the interval of scraping Windows Update information
## Metrics

2
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/prometheus-community/windows_exporter
go 1.26.0
go 1.25.0
require (
github.com/alecthomas/kingpin/v2 v2.4.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -71,16 +71,11 @@
<Property Id="TEXTFILE_DIRS" Secure="yes" />
<SetProperty Id="TextfileDirsFlag" After="InstallFiles" Sequence="execute" Value="--collector.textfile.directories=&quot;[TEXTFILE_DIRS]&quot;" Condition="TEXTFILE_DIRS" />
<!-- Configuration for how the installer shows in Add/Remove Programs. -->
<Icon Id="icon.ico" SourceFile=".\icon.ico"/>
<Property Id="ARPPRODUCTICON" Value="icon.ico" />
<Property Id="ARPHELPLINK" Value="https://github.com/prometheus-community/windows_exporter/issues" />
<Property Id="ARPSIZE" Value="9000" />
<Property Id="ARPURLINFOABOUT" Value="https://github.com/prometheus-community/windows_exporter" />
<Property Id="ARPCOMMENTS" Value="Prometheus exporter for Windows machines" />
<!-- Disable the repair option; the functionality is available through Change instead. -->
<Property Id="ARPNOREPAIR" Value="1" />
<Property Id="ARPSIZE" Value="10000" />
<!--<Property Id="ARPNOMODIFY" Value="0" />-->
<!--<Property Id="ARPNOREPAIR" Value="1" />-->
<Property Id="START_MENU_FOLDER" Value="0" />
<Property Id="NOSTART" Value="0" />

View File

@@ -131,7 +131,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.addressBookOperationsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "address_book_operations_total"),
"",
@@ -508,7 +508,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "DirectoryServices", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "DirectoryServices", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create DirectoryServices collector: %w", err)
}

View File

@@ -83,7 +83,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.requestsPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "requests_total"),
"Total certificate requests processed",
@@ -165,7 +165,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "Certification Authority", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Certification Authority", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Certification Authority collector: %w", err)
}

View File

@@ -113,7 +113,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.adLoginConnectionFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ad_login_connection_failures_total"),
"Total number of connection failures to an Active Directory domain controller",
@@ -375,7 +375,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "AD FS", nil)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "AD FS", nil)
if err != nil {
return fmt.Errorf("failed to create AD FS collector: %w", err)
}

View File

@@ -99,7 +99,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.asyncCopyReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "async_copy_reads_total"),
"(AsyncCopyReadsTotal)",
@@ -277,7 +277,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "Cache", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Cache", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Cache collector: %w", err)
}

View File

@@ -90,7 +90,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.mu = sync.Mutex{}
c.logicalProcessors = prometheus.NewDesc(
@@ -183,7 +183,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "Processor Information", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Processor Information", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Processor Information collector: %w", err)
}

View File

@@ -455,21 +455,21 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
if slices.Contains(c.config.CollectorsEnabled, "connection") {
c.perfDataCollectorConnection, err = pdh.NewCollector[perfDataCounterValuesConnection](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "DFS Replication Connections", pdh.InstancesAll)
c.perfDataCollectorConnection, err = pdh.NewCollector[perfDataCounterValuesConnection](pdh.CounterTypeRaw, "DFS Replication Connections", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create DFS Replication Connections collector: %w", err)
}
}
if slices.Contains(c.config.CollectorsEnabled, "folder") {
c.perfDataCollectorFolder, err = pdh.NewCollector[perfDataCounterValuesFolder](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "DFS Replicated Folders", pdh.InstancesAll)
c.perfDataCollectorFolder, err = pdh.NewCollector[perfDataCounterValuesFolder](pdh.CounterTypeRaw, "DFS Replicated Folders", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create DFS Replicated Folders collector: %w", err)
}
}
if slices.Contains(c.config.CollectorsEnabled, "volume") {
c.perfDataCollectorVolume, err = pdh.NewCollector[perfDataCounterValuesVolume](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "DFS Replication Service Volumes", pdh.InstancesAll)
c.perfDataCollectorVolume, err = pdh.NewCollector[perfDataCounterValuesVolume](pdh.CounterTypeRaw, "DFS Replication Service Volumes", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create DFS Replication Service Volumes collector: %w", err)
}

View File

@@ -378,7 +378,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
nil,
)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](c.logger, pdh.CounterTypeRaw, "DHCP Server", nil)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "DHCP Server", nil)
if err != nil {
return fmt.Errorf("failed to create DHCP Server collector: %w", err)
}

View File

@@ -132,7 +132,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
for _, collector := range c.config.CollectorsEnabled {
if !slices.Contains([]string{subCollectorMetrics, subCollectorWMIStats}, collector) {
return fmt.Errorf("unknown sub collector: %s. Possible values: %s", collector,
@@ -142,7 +142,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
}
if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) {
if err := c.buildMetricsCollector(logger); err != nil {
if err := c.buildMetricsCollector(); err != nil {
return err
}
}
@@ -156,7 +156,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
return nil
}
func (c *Collector) buildMetricsCollector(logger *slog.Logger) error {
func (c *Collector) buildMetricsCollector() error {
c.zoneTransferRequestsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_requests_received_total"),
"Number of zone transfer requests (AXFR/IXFR) received by the master DNS server",
@@ -299,7 +299,7 @@ func (c *Collector) buildMetricsCollector(logger *slog.Logger) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "DNS", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "DNS", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create DNS collector: %w", err)
}

View File

@@ -78,7 +78,6 @@ type Collector struct {
collectorWorkloadManagementWorkloads
config Config
logger *slog.Logger
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
@@ -136,10 +135,10 @@ func NewWithFlags(app *kingpin.Application) *Collector {
}
sb := strings.Builder{}
_, _ = fmt.Fprintf(&sb, "%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object")
sb.WriteString(fmt.Sprintf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object"))
for _, cname := range ConfigDefaults.CollectorsEnabled {
_, _ = fmt.Fprintf(&sb, "%-32s %-32s\n", cname, collectorDesc[cname])
sb.WriteString(fmt.Sprintf("%-32s %-32s\n", cname, collectorDesc[cname]))
}
app.UsageTemplate(sb.String()).Usage(nil)
@@ -171,9 +170,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
subCollectors := map[string]struct {
build func() error
collect func(ch chan<- prometheus.Metric) error

View File

@@ -43,7 +43,7 @@ type perfDataCounterValuesActiveSync struct {
func (c *Collector) buildActiveSync() error {
var err error
c.perfDataCollectorActiveSync, err = pdh.NewCollector[perfDataCounterValuesActiveSync](c.logger, pdh.CounterTypeRaw, "MSExchange ActiveSync", pdh.InstancesAll)
c.perfDataCollectorActiveSync, err = pdh.NewCollector[perfDataCounterValuesActiveSync](pdh.CounterTypeRaw, "MSExchange ActiveSync", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange ActiveSync collector: %w", err)
}

View File

@@ -50,7 +50,7 @@ type perfDataCounterValuesADAccessProcesses struct {
func (c *Collector) buildADAccessProcesses() error {
var err error
c.perfDataCollectorADAccessProcesses, err = pdh.NewCollector[perfDataCounterValuesADAccessProcesses](c.logger, pdh.CounterTypeRaw, "MSExchange ADAccess Processes", pdh.InstancesAll)
c.perfDataCollectorADAccessProcesses, err = pdh.NewCollector[perfDataCounterValuesADAccessProcesses](pdh.CounterTypeRaw, "MSExchange ADAccess Processes", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange ADAccess Processes collector: %w", err)
}

View File

@@ -39,7 +39,7 @@ type perfDataCounterValuesAutoDiscover struct {
func (c *Collector) buildAutoDiscover() error {
var err error
c.perfDataCollectorAutoDiscover, err = pdh.NewCollector[perfDataCounterValuesAutoDiscover](c.logger, pdh.CounterTypeRaw, "MSExchangeAutodiscover", nil)
c.perfDataCollectorAutoDiscover, err = pdh.NewCollector[perfDataCounterValuesAutoDiscover](pdh.CounterTypeRaw, "MSExchangeAutodiscover", nil)
if err != nil {
return fmt.Errorf("failed to create MSExchange Autodiscover collector: %w", err)
}

View File

@@ -39,7 +39,7 @@ type perfDataCounterValuesAvailabilityService struct {
func (c *Collector) buildAvailabilityService() error {
var err error
c.perfDataCollectorAvailabilityService, err = pdh.NewCollector[perfDataCounterValuesAvailabilityService](c.logger, pdh.CounterTypeRaw, "MSExchange Availability Service", pdh.InstancesAll)
c.perfDataCollectorAvailabilityService, err = pdh.NewCollector[perfDataCounterValuesAvailabilityService](pdh.CounterTypeRaw, "MSExchange Availability Service", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange Availability Service collector: %w", err)
}

View File

@@ -52,7 +52,7 @@ type perfDataCounterValuesHTTPProxy struct {
func (c *Collector) buildHTTPProxy() error {
var err error
c.perfDataCollectorHTTPProxy, err = pdh.NewCollector[perfDataCounterValuesHTTPProxy](c.logger, pdh.CounterTypeRaw, "MSExchange HttpProxy", pdh.InstancesAll)
c.perfDataCollectorHTTPProxy, err = pdh.NewCollector[perfDataCounterValuesHTTPProxy](pdh.CounterTypeRaw, "MSExchange HttpProxy", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange HttpProxy collector: %w", err)
}

View File

@@ -39,7 +39,7 @@ type perfDataCounterValuesMapiHTTPEmsMDB struct {
func (c *Collector) buildMapiHTTPEmsMDB() error {
var err error
c.perfDataCollectorMapiHTTPEmsMDB, err = pdh.NewCollector[perfDataCounterValuesMapiHTTPEmsMDB](c.logger, pdh.CounterTypeRaw, "MSExchange MapiHttp Emsmdb", pdh.InstancesAll)
c.perfDataCollectorMapiHTTPEmsMDB, err = pdh.NewCollector[perfDataCounterValuesMapiHTTPEmsMDB](pdh.CounterTypeRaw, "MSExchange MapiHttp Emsmdb", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange MapiHttp Emsmdb: %w", err)
}

View File

@@ -41,7 +41,7 @@ type perfDataCounterValuesOWA struct {
func (c *Collector) buildOWA() error {
var err error
c.perfDataCollectorOWA, err = pdh.NewCollector[perfDataCounterValuesOWA](c.logger, pdh.CounterTypeRaw, "MSExchange OWA", pdh.InstancesAll)
c.perfDataCollectorOWA, err = pdh.NewCollector[perfDataCounterValuesOWA](pdh.CounterTypeRaw, "MSExchange OWA", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange OWA collector: %w", err)
}

View File

@@ -50,7 +50,7 @@ type perfDataCounterValuesRpcClientAccess struct {
func (c *Collector) buildRpcClientAccess() error {
var err error
c.perfDataCollectorRpcClientAccess, err = pdh.NewCollector[perfDataCounterValuesRpcClientAccess](c.logger, pdh.CounterTypeRaw, "MSExchange RpcClientAccess", pdh.InstancesAll)
c.perfDataCollectorRpcClientAccess, err = pdh.NewCollector[perfDataCounterValuesRpcClientAccess](pdh.CounterTypeRaw, "MSExchange RpcClientAccess", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange RpcClientAccess collector: %w", err)
}

View File

@@ -77,7 +77,7 @@ type perfDataCounterValuesTransportQueues struct {
func (c *Collector) buildTransportQueues() error {
var err error
c.perfDataCollectorTransportQueues, err = pdh.NewCollector[perfDataCounterValuesTransportQueues](c.logger, pdh.CounterTypeRaw, "MSExchangeTransport Queues", pdh.InstancesAll)
c.perfDataCollectorTransportQueues, err = pdh.NewCollector[perfDataCounterValuesTransportQueues](pdh.CounterTypeRaw, "MSExchangeTransport Queues", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchangeTransport Queues collector: %w", err)
}

View File

@@ -49,7 +49,7 @@ type perfDataCounterValuesWorkloadManagementWorkloads struct {
func (c *Collector) buildWorkloadManagementWorkloads() error {
var err error
c.perfDataCollectorWorkloadManagementWorkloads, err = pdh.NewCollector[perfDataCounterValuesWorkloadManagementWorkloads](c.logger, pdh.CounterTypeRaw, "MSExchange WorkloadManagement Workloads", pdh.InstancesAll)
c.perfDataCollectorWorkloadManagementWorkloads, err = pdh.NewCollector[perfDataCounterValuesWorkloadManagementWorkloads](pdh.CounterTypeRaw, "MSExchange WorkloadManagement Workloads", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSExchange WorkloadManagement Workloads collector: %w", err)
}

View File

@@ -15,7 +15,7 @@
//go:build windows
package file
package filetime
import (
"fmt"
@@ -33,7 +33,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
)
const Name = "file"
const Name = "filetime"
type Config struct {
FilePatterns []string `yaml:"file-patterns"`
@@ -50,7 +50,6 @@ type Collector struct {
logger *slog.Logger
fileMTime *prometheus.Desc
fileSize *prometheus.Desc
}
func New(config *Config) *Collector {
@@ -76,7 +75,7 @@ func NewWithFlags(app *kingpin.Application) *Collector {
c.config.FilePatterns = make([]string, 0)
app.Flag(
"collector.file.file-patterns",
"collector.filetime.file-patterns",
"Comma-separated list of file patterns. Each pattern is a glob pattern that can contain `*`, `?`, and `**` (recursive). See https://github.com/bmatcuk/doublestar#patterns",
).Default(strings.Join(ConfigDefaults.FilePatterns, ",")).StringsVar(&c.config.FilePatterns)
@@ -94,7 +93,7 @@ func (c *Collector) Close() error {
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
c.logger.Info("file collector is in an experimental state! It may subject to change.")
c.logger.Info("filetime collector is in an experimental state! It may subject to change.")
c.fileMTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "mtime_timestamp_seconds"),
@@ -103,13 +102,6 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
nil,
)
c.fileSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "size_bytes"),
"File size",
[]string{"file"},
nil,
)
for _, filePattern := range c.config.FilePatterns {
basePath, pattern := doublestar.SplitPattern(filePattern)
@@ -171,13 +163,6 @@ func (c *Collector) collectGlobFilePath(ch chan<- prometheus.Metric, filePattern
filePath,
)
ch <- prometheus.MustNewConstMetric(
c.fileSize,
prometheus.GaugeValue,
float64(fileInfo.Size()),
filePath,
)
return nil
}, doublestar.WithFilesOnly(), doublestar.WithCaseInsensitive())
if err != nil {

View File

@@ -15,21 +15,21 @@
//go:build windows
package file_test
package filetime_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/internal/collector/file"
"github.com/prometheus-community/windows_exporter/internal/collector/filetime"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils"
)
func BenchmarkCollector(b *testing.B) {
testutils.FuncBenchmarkCollector(b, file.Name, file.NewWithFlags)
testutils.FuncBenchmarkCollector(b, filetime.Name, filetime.NewWithFlags)
}
func TestCollector(t *testing.T) {
testutils.TestCollector(t, file.New, &file.Config{
testutils.TestCollector(t, filetime.New, &filetime.Config{
FilePatterns: []string{"*.*"},
})
}

View File

@@ -223,27 +223,27 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
errs := make([]error, 0)
c.gpuEnginePerfDataCollector, err = pdh.NewCollector[gpuEnginePerfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "GPU Engine", pdh.InstancesAll)
c.gpuEnginePerfDataCollector, err = pdh.NewCollector[gpuEnginePerfDataCounterValues](pdh.CounterTypeRaw, "GPU Engine", pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create GPU Engine perf data collector: %w", err))
}
c.gpuAdapterMemoryPerfDataCollector, err = pdh.NewCollector[gpuAdapterMemoryPerfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "GPU Adapter Memory", pdh.InstancesAll)
c.gpuAdapterMemoryPerfDataCollector, err = pdh.NewCollector[gpuAdapterMemoryPerfDataCounterValues](pdh.CounterTypeRaw, "GPU Adapter Memory", pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create GPU Adapter Memory perf data collector: %w", err))
}
c.gpuLocalAdapterMemoryPerfDataCollector, err = pdh.NewCollector[gpuLocalAdapterMemoryPerfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "GPU Local Adapter Memory", pdh.InstancesAll)
c.gpuLocalAdapterMemoryPerfDataCollector, err = pdh.NewCollector[gpuLocalAdapterMemoryPerfDataCounterValues](pdh.CounterTypeRaw, "GPU Local Adapter Memory", pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create GPU Local Adapter Memory perf data collector: %w", err))
}
c.gpuNonLocalAdapterMemoryPerfDataCollector, err = pdh.NewCollector[gpuNonLocalAdapterMemoryPerfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "GPU Non Local Adapter Memory", pdh.InstancesAll)
c.gpuNonLocalAdapterMemoryPerfDataCollector, err = pdh.NewCollector[gpuNonLocalAdapterMemoryPerfDataCounterValues](pdh.CounterTypeRaw, "GPU Non Local Adapter Memory", pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create GPU Non Local Adapter Memory perf data collector: %w", err))
}
c.gpuProcessMemoryPerfDataCollector, err = pdh.NewCollector[gpuProcessMemoryPerfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "GPU Process Memory", pdh.InstancesAll)
c.gpuProcessMemoryPerfDataCollector, err = pdh.NewCollector[gpuProcessMemoryPerfDataCounterValues](pdh.CounterTypeRaw, "GPU Process Memory", pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create GPU Process Memory perf data collector: %w", err))
}

View File

@@ -95,7 +95,6 @@ type Collector struct {
collectorVirtualSwitch
config Config
logger *slog.Logger
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
@@ -152,7 +151,6 @@ func (c *Collector) Close() error {
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
c.collectorFns = make([]func(ch chan<- prometheus.Metric) error, 0, len(c.config.CollectorsEnabled))
c.closeFns = make([]func(), 0, len(c.config.CollectorsEnabled))
@@ -258,10 +256,10 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
}
if buildNumber < subCollectors[name].minBuildNumber {
c.logger.Warn(fmt.Sprintf(
logger.Warn(fmt.Sprintf(
"collector %s requires windows build version %d. Current build version: %d",
name, subCollectors[name].minBuildNumber, buildNumber,
))
), slog.String("collector", name))
continue
}

View File

@@ -132,7 +132,7 @@ type perfDataCounterValuesDataStore struct {
func (c *Collector) buildDataStore() error {
var err error
c.perfDataCollectorDataStore, err = pdh.NewCollector[perfDataCounterValuesDataStore](c.logger, pdh.CounterTypeRaw, "Hyper-V DataStore", pdh.InstancesAll)
c.perfDataCollectorDataStore, err = pdh.NewCollector[perfDataCounterValuesDataStore](pdh.CounterTypeRaw, "Hyper-V DataStore", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V DataStore collector: %w", err)
}

View File

@@ -52,7 +52,7 @@ func (c *Collector) buildDynamicMemoryBalancer() error {
var err error
// https://learn.microsoft.com/en-us/archive/blogs/chrisavis/monitoring-dynamic-memory-in-windows-server-hyper-v-2012
c.perfDataCollectorDynamicMemoryBalancer, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryBalancer](c.logger, pdh.CounterTypeRaw, "Hyper-V Dynamic Memory Balancer", pdh.InstancesAll)
c.perfDataCollectorDynamicMemoryBalancer, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryBalancer](pdh.CounterTypeRaw, "Hyper-V Dynamic Memory Balancer", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err)
}

View File

@@ -63,7 +63,7 @@ type perfDataCounterValuesDynamicMemoryVM struct {
func (c *Collector) buildDynamicMemoryVM() error {
var err error
c.perfDataCollectorDynamicMemoryVM, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryVM](c.logger, pdh.CounterTypeRaw, "Hyper-V Dynamic Memory VM", pdh.InstancesAll)
c.perfDataCollectorDynamicMemoryVM, err = pdh.NewCollector[perfDataCounterValuesDynamicMemoryVM](pdh.CounterTypeRaw, "Hyper-V Dynamic Memory VM", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Dynamic Memory VM collector: %w", err)
}

View File

@@ -52,7 +52,7 @@ type perfDataCounterValuesHypervisorLogicalProcessor struct {
func (c *Collector) buildHypervisorLogicalProcessor() error {
var err error
c.perfDataCollectorHypervisorLogicalProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorLogicalProcessor](c.logger, pdh.CounterTypeRaw, "Hyper-V Hypervisor Logical Processor", pdh.InstancesAll)
c.perfDataCollectorHypervisorLogicalProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorLogicalProcessor](pdh.CounterTypeRaw, "Hyper-V Hypervisor Logical Processor", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Logical Processor collector: %w", err)
}

View File

@@ -80,7 +80,7 @@ type perfDataCounterValuesHypervisorRootPartition struct {
func (c *Collector) buildHypervisorRootPartition() error {
var err error
c.perfDataCollectorHypervisorRootPartition, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootPartition](c.logger, pdh.CounterTypeRaw, "Hyper-V Hypervisor Root Partition", []string{"Root"})
c.perfDataCollectorHypervisorRootPartition, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootPartition](pdh.CounterTypeRaw, "Hyper-V Hypervisor Root Partition", []string{"Root"})
if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Root Partition collector: %w", err)
}

View File

@@ -53,7 +53,7 @@ type perfDataCounterValuesHypervisorRootVirtualProcessor struct {
func (c *Collector) buildHypervisorRootVirtualProcessor() error {
var err error
c.perfDataCollectorHypervisorRootVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootVirtualProcessor](c.logger, pdh.CounterTypeRaw, "Hyper-V Hypervisor Root Virtual Processor", pdh.InstancesAll)
c.perfDataCollectorHypervisorRootVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorRootVirtualProcessor](pdh.CounterTypeRaw, "Hyper-V Hypervisor Root Virtual Processor", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Root Virtual Processor collector: %w", err)
}

View File

@@ -35,9 +35,7 @@ type collectorHypervisorVirtualProcessor struct {
// \Hyper-V Hypervisor Virtual Processor(*)\% Hypervisor Run Time
// \Hyper-V Hypervisor Virtual Processor(*)\% Remote Run Time
hypervisorVirtualProcessorTimeTotal *prometheus.Desc
hypervisorVirtualProcessorModeTimeTotal *prometheus.Desc // New name for better clarity
hypervisorVirtualProcessorTotalRunTimeTotal *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\% Total Run Time
hypervisorVirtualProcessorRunTimeTotal *prometheus.Desc // New name for better clarity
hypervisorVirtualProcessorContextSwitches *prometheus.Desc // \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch
}
@@ -54,39 +52,23 @@ type perfDataCounterValuesHypervisorVirtualProcessor struct {
func (c *Collector) buildHypervisorVirtualProcessor() error {
var err error
c.perfDataCollectorHypervisorVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorVirtualProcessor](c.logger, pdh.CounterTypeRaw, "Hyper-V Hypervisor Virtual Processor", pdh.InstancesAll)
c.perfDataCollectorHypervisorVirtualProcessor, err = pdh.NewCollector[perfDataCounterValuesHypervisorVirtualProcessor](pdh.CounterTypeRaw, "Hyper-V Hypervisor Virtual Processor", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Hypervisor Virtual Processor collector: %w", err)
}
c.hypervisorVirtualProcessorTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_time_total"),
"DEPRECATED: use hypervisor_virtual_processor_mode_time_total. Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)",
[]string{"vm", "core", "state"},
nil,
)
// New metric with better name for clarity, old one is kept for backward compatibility
c.hypervisorVirtualProcessorModeTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_mode_time_total"),
"Time that processor spent in different modes (hypervisor, guest_run, guest_idle, remote)",
[]string{"vm", "core", "state"},
nil,
)
// end same metric
c.hypervisorVirtualProcessorTotalRunTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_total_run_time_total"),
"DEPRECATED: use hypervisor_virtual_processor_run_time_total. Time that processor spent",
[]string{"vm", "core"},
nil,
)
// New metric with better name for clarity, old one is kept for backward compatibility
c.hypervisorVirtualProcessorRunTimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_run_time_total"),
"Time that processor spent",
[]string{"vm", "core"},
nil,
)
// end same metric
c.hypervisorVirtualProcessorContextSwitches = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hypervisor_virtual_processor_cpu_wait_time_per_dispatch_total"),
"The average time (in nanoseconds) spent waiting for a virtual processor to be dispatched onto a logical processor.",
@@ -138,42 +120,14 @@ func (c *Collector) collectHypervisorVirtualProcessor(ch chan<- prometheus.Metri
data.HypervisorVirtualProcessorRemoteRunTimePercent,
vmName, coreID, "remote",
)
// Same metric with new name for better clarity, old one is kept for backward compatibility
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorModeTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorHypervisorRunTimePercent,
vmName, coreID, "hypervisor",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorModeTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorGuestRunTimePercent,
vmName, coreID, "guest",
)
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorModeTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorRemoteRunTimePercent,
vmName, coreID, "remote",
)
// end same metric
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorTotalRunTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorTotalRunTimePercent,
vmName, coreID,
)
// Same metric with new name for better clarity, old one is kept for backward compatibility
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorRunTimeTotal,
prometheus.CounterValue,
data.HypervisorVirtualProcessorTotalRunTimePercent,
vmName, coreID,
)
// end same metric
ch <- prometheus.MustNewConstMetric(
c.hypervisorVirtualProcessorContextSwitches,
prometheus.CounterValue,

View File

@@ -52,7 +52,7 @@ type perfDataCounterValuesLegacyNetworkAdapter struct {
func (c *Collector) buildLegacyNetworkAdapter() error {
var err error
c.perfDataCollectorLegacyNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesLegacyNetworkAdapter](c.logger, pdh.CounterTypeRaw, "Hyper-V Legacy Network Adapter", pdh.InstancesAll)
c.perfDataCollectorLegacyNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesLegacyNetworkAdapter](pdh.CounterTypeRaw, "Hyper-V Legacy Network Adapter", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Legacy Network Adapter collector: %w", err)
}

View File

@@ -44,7 +44,7 @@ type perfDataCounterValuesVirtualMachineHealthSummary struct {
func (c *Collector) buildVirtualMachineHealthSummary() error {
var err error
c.perfDataCollectorVirtualMachineHealthSummary, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineHealthSummary](c.logger, pdh.CounterTypeRaw, "Hyper-V Virtual Machine Health Summary", nil)
c.perfDataCollectorVirtualMachineHealthSummary, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineHealthSummary](pdh.CounterTypeRaw, "Hyper-V Virtual Machine Health Summary", nil)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Machine Health Summary collector: %w", err)
}

View File

@@ -46,7 +46,7 @@ type perfDataCounterValuesVirtualMachineVidPartition struct {
func (c *Collector) buildVirtualMachineVidPartition() error {
var err error
c.perfDataCollectorVirtualMachineVidPartition, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineVidPartition](c.logger, pdh.CounterTypeRaw, "Hyper-V VM Vid Partition", pdh.InstancesAll)
c.perfDataCollectorVirtualMachineVidPartition, err = pdh.NewCollector[perfDataCounterValuesVirtualMachineVidPartition](pdh.CounterTypeRaw, "Hyper-V VM Vid Partition", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V VM Vid Partition collector: %w", err)
}

View File

@@ -52,7 +52,7 @@ type perfDataCounterValuesVirtualNetworkAdapter struct {
func (c *Collector) buildVirtualNetworkAdapter() error {
var err error
c.perfDataCollectorVirtualNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapter](c.logger, pdh.CounterTypeRaw, "Hyper-V Virtual Network Adapter", pdh.InstancesAll)
c.perfDataCollectorVirtualNetworkAdapter, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapter](pdh.CounterTypeRaw, "Hyper-V Virtual Network Adapter", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter collector: %w", err)
}

View File

@@ -167,7 +167,7 @@ type perfDataCounterValuesVirtualNetworkAdapterDropReasons struct {
func (c *Collector) buildVirtualNetworkAdapterDropReasons() error {
var err error
c.perfDataCollectorVirtualNetworkAdapterDropReasons, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapterDropReasons](c.logger, pdh.CounterTypeRaw, "Hyper-V Virtual Network Adapter Drop Reasons", pdh.InstancesAll)
c.perfDataCollectorVirtualNetworkAdapterDropReasons, err = pdh.NewCollector[perfDataCounterValuesVirtualNetworkAdapterDropReasons](pdh.CounterTypeRaw, "Hyper-V Virtual Network Adapter Drop Reasons", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Network Adapter Drop Reasons collector: %w", err)
}

View File

@@ -74,7 +74,7 @@ type perfDataCounterValuesVirtualSMB struct {
func (c *Collector) buildVirtualSMB() error {
var err error
c.perfDataCollectorVirtualSMB, err = pdh.NewCollector[perfDataCounterValuesVirtualSMB](c.logger, pdh.CounterTypeRaw, "Hyper-V Virtual SMB", pdh.InstancesAll)
c.perfDataCollectorVirtualSMB, err = pdh.NewCollector[perfDataCounterValuesVirtualSMB](pdh.CounterTypeRaw, "Hyper-V Virtual SMB", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual SMB collector: %w", err)
}

View File

@@ -64,7 +64,7 @@ type perfDataCounterValuesVirtualStorageDevice struct {
func (c *Collector) buildVirtualStorageDevice() error {
var err error
c.perfDataCollectorVirtualStorageDevice, err = pdh.NewCollector[perfDataCounterValuesVirtualStorageDevice](c.logger, pdh.CounterTypeRaw, "Hyper-V Virtual Storage Device", pdh.InstancesAll)
c.perfDataCollectorVirtualStorageDevice, err = pdh.NewCollector[perfDataCounterValuesVirtualStorageDevice](pdh.CounterTypeRaw, "Hyper-V Virtual Storage Device", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Storage Device collector: %w", err)
}
@@ -112,8 +112,8 @@ func (c *Collector) buildVirtualStorageDevice() error {
nil,
)
c.virtualStorageDeviceThroughput = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_throughput_total"),
"Represents the total number of 8KB IO transfers completed by this virtual device.",
prometheus.BuildFQName(types.Namespace, Name, "virtual_storage_device_throughput"),
"Represents the average number of 8KB IO transfers completed by this virtual device.",
[]string{"device"},
nil,
)
@@ -203,7 +203,7 @@ func (c *Collector) collectVirtualStorageDevice(ch chan<- prometheus.Metric) err
ch <- prometheus.MustNewConstMetric(
c.virtualStorageDeviceThroughput,
prometheus.CounterValue,
prometheus.GaugeValue,
data.VirtualStorageDeviceThroughput,
data.Name,
)

View File

@@ -82,7 +82,7 @@ type perfDataCounterValuesVirtualSwitch struct {
func (c *Collector) buildVirtualSwitch() error {
var err error
c.perfDataCollectorVirtualSwitch, err = pdh.NewCollector[perfDataCounterValuesVirtualSwitch](c.logger, pdh.CounterTypeRaw, "Hyper-V Virtual Switch", pdh.InstancesAll)
c.perfDataCollectorVirtualSwitch, err = pdh.NewCollector[perfDataCounterValuesVirtualSwitch](pdh.CounterTypeRaw, "Hyper-V Virtual Switch", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Hyper-V Virtual Switch collector: %w", err)
}

View File

@@ -79,7 +79,7 @@ var applicationStates = map[uint32]string{
func (c *Collector) buildAppPoolWAS() error {
var err error
c.perfDataCollectorAppPoolWAS, err = pdh.NewCollector[perfDataCounterValuesAppPoolWAS](c.logger, pdh.CounterTypeRaw, "APP_POOL_WAS", pdh.InstancesAll)
c.perfDataCollectorAppPoolWAS, err = pdh.NewCollector[perfDataCounterValuesAppPoolWAS](pdh.CounterTypeRaw, "APP_POOL_WAS", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create APP_POOL_WAS collector: %w", err)
}

View File

@@ -54,7 +54,7 @@ func (c *Collector) buildHttpServiceRequestQueues() error {
c.logger.Info("IIS/HttpServiceRequestQueues collector is in an experimental state! The configuration and metrics may change in future. Please report any issues.")
c.perfDataCollectorHttpServiceRequestQueues, err = pdh.NewCollector[perfDataCounterValuesHttpServiceRequestQueues](c.logger, pdh.CounterTypeRaw, "HTTP Service Request Queues", pdh.InstancesAll)
c.perfDataCollectorHttpServiceRequestQueues, err = pdh.NewCollector[perfDataCounterValuesHttpServiceRequestQueues](pdh.CounterTypeRaw, "HTTP Service Request Queues", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Http Service collector: %w", err)
}

View File

@@ -152,13 +152,13 @@ func (p perfDataCounterValuesW3SVCW3WPV8) GetName() string {
func (c *Collector) buildW3SVCW3WP() error {
var err error
c.w3SVCW3WPPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WP](c.logger, pdh.CounterTypeRaw, "W3SVC_W3WP", pdh.InstancesAll)
c.w3SVCW3WPPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WP](pdh.CounterTypeRaw, "W3SVC_W3WP", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create W3SVC_W3WP collector: %w", err)
}
if c.iisVersion.major >= 8 {
c.w3SVCW3WPPerfDataCollectorV8, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WPV8](c.logger, pdh.CounterTypeRaw, "W3SVC_W3WP", pdh.InstancesAll)
c.w3SVCW3WPPerfDataCollectorV8, err = pdh.NewCollector[perfDataCounterValuesW3SVCW3WPV8](pdh.CounterTypeRaw, "W3SVC_W3WP", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create W3SVC_W3WP collector: %w", err)
}

View File

@@ -102,7 +102,7 @@ func (p perfDataCounterValuesWebService) GetName() string {
func (c *Collector) buildWebService() error {
var err error
c.perfDataCollectorWebService, err = pdh.NewCollector[perfDataCounterValuesWebService](c.logger, pdh.CounterTypeRaw, "Web Service", pdh.InstancesAll)
c.perfDataCollectorWebService, err = pdh.NewCollector[perfDataCounterValuesWebService](pdh.CounterTypeRaw, "Web Service", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Web Service collector: %w", err)
}

View File

@@ -103,7 +103,7 @@ type perfDataCounterServiceCache struct {
func (c *Collector) buildWebServiceCache() error {
var err error
c.serviceCachePerfDataCollector, err = pdh.NewCollector[perfDataCounterServiceCache](c.logger, pdh.CounterTypeRaw, "Web Service Cache", pdh.InstancesAll)
c.serviceCachePerfDataCollector, err = pdh.NewCollector[perfDataCounterServiceCache](pdh.CounterTypeRaw, "Web Service Cache", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Web Service Cache collector: %w", err)
}

View File

@@ -332,7 +332,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "LogicalDisk", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "LogicalDisk", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create LogicalDisk collector: %w", err)
}

View File

@@ -111,7 +111,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.availableBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "available_bytes"),
"The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+
@@ -337,7 +337,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "Memory", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Memory", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Memory collector: %w", err)
}

View File

@@ -38,8 +38,6 @@ const (
subCollectorNode = "node"
subCollectorResource = "resource"
subCollectorResourceGroup = "resourcegroup"
subCollectorSharedVolumes = "shared_volumes"
subCollectorVirtualDisk = "virtualdisk"
)
type Config struct {
@@ -54,8 +52,6 @@ var ConfigDefaults = Config{
subCollectorNode,
subCollectorResource,
subCollectorResourceGroup,
subCollectorSharedVolumes,
subCollectorVirtualDisk,
},
}
@@ -66,8 +62,6 @@ type Collector struct {
collectorNode
collectorResource
collectorResourceGroup
collectorSharedVolumes
collectorVirtualDisk
config Config
miSession *mi.Session
@@ -162,18 +156,6 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
}
}
if slices.Contains(c.config.CollectorsEnabled, subCollectorSharedVolumes) {
if err := c.buildSharedVolumes(); err != nil {
errs = append(errs, fmt.Errorf("failed to build shared_volumes collector: %w", err))
}
}
if slices.Contains(c.config.CollectorsEnabled, subCollectorVirtualDisk) {
if err := c.buildVirtualDisk(); err != nil {
errs = append(errs, fmt.Errorf("failed to build virtualdisk collector: %w", err))
}
}
return errors.Join(errs...)
}
@@ -184,10 +166,10 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
return nil
}
errCh := make(chan error, 6)
errCh := make(chan error, 5)
wg := sync.WaitGroup{}
wg.Add(6)
wg.Add(5)
go func() {
defer wg.Done()
@@ -244,22 +226,6 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
}()
}()
go func() {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorSharedVolumes) {
if err := c.collectSharedVolumes(ch); err != nil {
errCh <- fmt.Errorf("failed to collect shared_volumes metrics: %w", err)
}
}
if slices.Contains(c.config.CollectorsEnabled, subCollectorVirtualDisk) {
if err := c.collectVirtualDisk(ch); err != nil {
errCh <- fmt.Errorf("failed to collect virtualdisk metrics: %w", err)
}
}
}()
wg.Wait()
close(errCh)

View File

@@ -1,122 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 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 mscluster
import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
const nameSharedVolumes = Name + "_shared_volumes"
type collectorSharedVolumes struct {
sharedVolumesMIQuery mi.Query
sharedVolumesInfo *prometheus.Desc
sharedVolumesTotalSize *prometheus.Desc
sharedVolumesFreeSpace *prometheus.Desc
}
// msClusterDiskPartition represents the MSCluster_DiskPartition WMI class
type msClusterDiskPartition struct {
Name string `mi:"Name"`
Path string `mi:"Path"`
TotalSize uint64 `mi:"TotalSize"`
FreeSpace uint64 `mi:"FreeSpace"`
Volume string `mi:"VolumeLabel"`
VolumeGuid string `mi:"VolumeGuid"`
}
func (c *Collector) buildSharedVolumes() error {
sharedVolumesMIQuery, err := mi.NewQuery("SELECT Name, Path, TotalSize, FreeSpace, VolumeLabel, VolumeGuid FROM MSCluster_DiskPartition")
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}
c.sharedVolumesMIQuery = sharedVolumesMIQuery
c.sharedVolumesInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameSharedVolumes, "info"),
"Cluster Shared Volumes information (value is always 1)",
[]string{"name", "path", "volume_guid"},
nil,
)
c.sharedVolumesTotalSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameSharedVolumes, "total_bytes"),
"Total size of the Cluster Shared Volume in bytes",
[]string{"name", "volume_guid"},
nil,
)
c.sharedVolumesFreeSpace = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameSharedVolumes, "free_bytes"),
"Free space on the Cluster Shared Volume in bytes",
[]string{"name", "volume_guid"},
nil,
)
var dst []msClusterDiskPartition
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.sharedVolumesMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil
}
func (c *Collector) collectSharedVolumes(ch chan<- prometheus.Metric) error {
var dst []msClusterDiskPartition
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.sharedVolumesMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
for _, partition := range dst {
volume := strings.TrimRight(partition.Volume, " ")
ch <- prometheus.MustNewConstMetric(
c.sharedVolumesInfo,
prometheus.GaugeValue,
1.0,
volume,
partition.Path,
partition.VolumeGuid,
)
ch <- prometheus.MustNewConstMetric(
c.sharedVolumesTotalSize,
prometheus.GaugeValue,
float64(partition.TotalSize)*1024*1024, // Convert from KB to bytes
volume,
partition.VolumeGuid,
)
ch <- prometheus.MustNewConstMetric(
c.sharedVolumesFreeSpace,
prometheus.GaugeValue,
float64(partition.FreeSpace)*1024*1024, // Convert from KB to bytes
volume,
partition.VolumeGuid,
)
}
return nil
}

View File

@@ -1,156 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 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 mscluster
import (
"fmt"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
const nameVirtualDisk = Name + "_virtualdisk"
type collectorVirtualDisk struct {
virtualDiskMIQuery mi.Query
virtualDiskInfo *prometheus.Desc
virtualDiskHealthStatus *prometheus.Desc
virtualDiskSize *prometheus.Desc
virtualDiskFootprintOnPool *prometheus.Desc
virtualDiskStorageEfficiency *prometheus.Desc
}
// msftVirtualDisk represents the MSFT_VirtualDisk WMI class
type msftVirtualDisk struct {
FriendlyName string `mi:"FriendlyName"`
UniqueId string `mi:"UniqueId"`
HealthStatus uint16 `mi:"HealthStatus"`
Size uint64 `mi:"Size"`
FootprintOnPool uint64 `mi:"FootprintOnPool"`
// OperationalStatus []uint16 `mi:"OperationalStatus"` Not supported my mi query: https://github.com/prometheus-community/windows_exporter/pull/2296#issuecomment-3736584632
}
func (c *Collector) buildVirtualDisk() error {
wmiSelect := "FriendlyName,UniqueId,HealthStatus,Size,FootprintOnPool"
virtualDiskMIQuery, err := mi.NewQuery(fmt.Sprintf("SELECT %s FROM MSFT_VirtualDisk", wmiSelect))
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}
c.virtualDiskMIQuery = virtualDiskMIQuery
c.virtualDiskInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "info"),
"Virtual Disk information (value is always 1)",
[]string{"name", "unique_id"},
nil,
)
c.virtualDiskHealthStatus = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "health_status"),
"Health status of the virtual disk. 0: Healthy, 1: Warning, 2: Unhealthy, 5: Unknown",
[]string{"name", "unique_id"},
nil,
)
c.virtualDiskSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "size_bytes"),
"Total size of the virtual disk in bytes",
[]string{"name", "unique_id"},
nil,
)
c.virtualDiskFootprintOnPool = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "footprint_on_pool_bytes"),
"Physical storage consumed by the virtual disk on the storage pool in bytes",
[]string{"name", "unique_id"},
nil,
)
c.virtualDiskStorageEfficiency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameVirtualDisk, "storage_efficiency_percent"),
"Storage efficiency percentage (Size / FootprintOnPool * 100)",
[]string{"name", "unique_id"},
nil,
)
return nil
}
func (c *Collector) collectVirtualDisk(ch chan<- prometheus.Metric) error {
var dst []msftVirtualDisk
if err := c.miSession.Query(&dst, mi.NamespaceRootStorage, c.virtualDiskMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
for _, vdisk := range dst {
ch <- prometheus.MustNewConstMetric(
c.virtualDiskInfo,
prometheus.GaugeValue,
1.0,
vdisk.FriendlyName,
vdisk.UniqueId,
)
ch <- prometheus.MustNewConstMetric(
c.virtualDiskHealthStatus,
prometheus.GaugeValue,
float64(vdisk.HealthStatus),
vdisk.FriendlyName,
vdisk.UniqueId,
)
ch <- prometheus.MustNewConstMetric(
c.virtualDiskSize,
prometheus.GaugeValue,
float64(vdisk.Size),
vdisk.FriendlyName,
vdisk.UniqueId,
)
ch <- prometheus.MustNewConstMetric(
c.virtualDiskFootprintOnPool,
prometheus.GaugeValue,
float64(vdisk.FootprintOnPool),
vdisk.FriendlyName,
vdisk.UniqueId,
)
// Calculate storage efficiency (avoid division by zero)
var storageEfficiency float64
if vdisk.FootprintOnPool > 0 {
storageEfficiency = float64(vdisk.Size) / float64(vdisk.FootprintOnPool) * 100
} else {
storageEfficiency = 0
}
ch <- prometheus.MustNewConstMetric(
c.virtualDiskStorageEfficiency,
prometheus.GaugeValue,
storageEfficiency,
vdisk.FriendlyName,
vdisk.UniqueId,
)
}
return nil
}

View File

@@ -75,7 +75,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.bytesInJournalQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bytes_in_journal_queue"),
"Size of queue journal in bytes",
@@ -103,7 +103,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "MSMQ Queue", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "MSMQ Queue", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create MSMQ Queue collector: %w", err)
}

View File

@@ -130,7 +130,7 @@ func (c *Collector) buildAccessMethods() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.accessMethodsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesAccessMethods](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Access Methods"), nil)
c.accessMethodsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesAccessMethods](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Access Methods"), nil)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create AccessMethods collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -63,7 +63,7 @@ func (c *Collector) buildAvailabilityReplica() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.availabilityReplicaPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesAvailabilityReplica](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), pdh.InstancesAll)
c.availabilityReplicaPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesAvailabilityReplica](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Availability Replica collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -88,7 +88,7 @@ func (c *Collector) buildBufferManager() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.bufManPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesBufMan](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), nil)
c.bufManPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesBufMan](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), nil)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Buffer Manager collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -148,13 +148,13 @@ func (c *Collector) buildDatabases() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.databasesPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesDatabases](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Databases"), pdh.InstancesAll)
c.databasesPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesDatabases](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Databases"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Databases collector for instance %s: %w", sqlInstance.name, err))
}
if sqlInstance.isVersionGreaterOrEqualThan(serverVersion2019) {
c.databasesPerfDataCollectors2019[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesDatabases2019](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Databases"), pdh.InstancesAll)
c.databasesPerfDataCollectors2019[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesDatabases2019](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Databases"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Databases 2019 collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -92,7 +92,7 @@ func (c *Collector) buildDatabaseReplica() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.dbReplicaPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesDBReplica](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), pdh.InstancesAll)
c.dbReplicaPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesDBReplica](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Database Replica collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -90,7 +90,7 @@ func (c *Collector) buildGeneralStatistics() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.genStatsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesGenStats](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), nil)
c.genStatsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesGenStats](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "General Statistics"), nil)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create General Statistics collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -61,7 +61,7 @@ func (c *Collector) buildLocks() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.locksPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesLocks](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Locks"), pdh.InstancesAll)
c.locksPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesLocks](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Locks"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Locks collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -82,7 +82,7 @@ func (c *Collector) buildMemoryManager() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.memMgrPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesMemMgr](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Memory Manager"), pdh.InstancesAll)
c.memMgrPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesMemMgr](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Memory Manager"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Memory Manager collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -47,7 +47,7 @@ func (c *Collector) buildSQLErrors() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.sqlErrorsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesSqlErrors](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), pdh.InstancesAll)
c.sqlErrorsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesSqlErrors](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "SQL Errors"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create SQL Errors collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -64,7 +64,7 @@ func (c *Collector) buildSQLStats() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.sqlStatsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesSqlStats](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), nil)
c.sqlStatsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesSqlStats](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "SQL Statistics"), nil)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create SQL Statistics collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -68,7 +68,7 @@ func (c *Collector) buildTransactions() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.transactionsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesTransactions](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), nil)
c.transactionsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesTransactions](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Transactions"), nil)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Transactions collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -68,7 +68,7 @@ func (c *Collector) buildWaitStats() error {
errs := make([]error, 0, len(c.mssqlInstances))
for _, sqlInstance := range c.mssqlInstances {
c.waitStatsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesWaitStats](c.logger, pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), pdh.InstancesAll)
c.waitStatsPerfDataCollectors[sqlInstance], err = pdh.NewCollector[perfDataCounterValuesWaitStats](pdh.CounterTypeRaw, c.mssqlGetPerfObjectName(sqlInstance, "Wait Statistics"), pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create Wait Statistics collector for instance %s: %w", sqlInstance.name, err))
}

View File

@@ -279,7 +279,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "Network Interface", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Network Interface", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Network Interface collector: %w", err)
}

View File

@@ -19,7 +19,6 @@ package netframework
import (
"fmt"
"strconv"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -31,73 +30,73 @@ func (c *Collector) buildClrMemory() {
c.allocatedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_allocated_bytes_total"),
"Displays the total number of bytes allocated on the garbage collection heap.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.finalizationSurvivors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_finalization_survivors"),
"Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.heapSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_heap_size_bytes"),
"Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated.",
[]string{"process", "process_id", "area"},
[]string{"process", "area"},
nil,
)
c.promotedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_promoted_bytes"),
"Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection.",
[]string{"process", "process_id", "area"},
[]string{"process", "area"},
nil,
)
c.numberGCHandles = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_number_gc_handles"),
"Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.numberCollections = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_collections_total"),
"Displays the number of times the generation objects are garbage collected since the application started.",
[]string{"process", "process_id", "area"},
[]string{"process", "area"},
nil,
)
c.numberInducedGC = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_induced_gc_total"),
"Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.numberOfPinnedObjects = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_number_pinned_objects"),
"Displays the number of pinned objects encountered in the last garbage collection.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.numberOfSinkBlocksInUse = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_number_sink_blocksinuse"),
"Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.numberTotalCommittedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_committed_bytes"),
"Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.numberTotalReservedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_reserved_bytes"),
"Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
c.timeInGC = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, collectorClrMemory+"_gc_time_percent"),
"Displays the percentage of time that was spent performing a garbage collection in the last sample.",
[]string{"process", "process_id"},
[]string{"process"},
nil,
)
}
@@ -152,7 +151,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.CounterValue,
float64(process.AllocatedBytesPersec),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -160,7 +158,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.FinalizationSurvivors),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -168,7 +165,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.Gen0heapsize),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen0",
)
@@ -177,7 +173,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.Gen0PromotedBytesPerSec),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen0",
)
@@ -186,7 +181,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.Gen1heapsize),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen1",
)
@@ -195,7 +189,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.Gen1PromotedBytesPerSec),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen1",
)
@@ -204,7 +197,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.Gen2heapsize),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen2",
)
@@ -213,7 +205,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.LargeObjectHeapsize),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"LOH",
)
@@ -222,7 +213,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.NumberGCHandles),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -230,7 +220,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.CounterValue,
float64(process.NumberGen0Collections),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen0",
)
@@ -239,7 +228,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.CounterValue,
float64(process.NumberGen1Collections),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen1",
)
@@ -248,7 +236,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.CounterValue,
float64(process.NumberGen2Collections),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
"Gen2",
)
@@ -257,7 +244,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.CounterValue,
float64(process.NumberInducedGC),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -265,7 +251,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.NumberofPinnedObjects),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -273,7 +258,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.NumberofSinkBlocksinuse),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -281,7 +265,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.NumberTotalcommittedBytes),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -289,7 +272,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(process.NumberTotalreservedBytes),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
ch <- prometheus.MustNewConstMetric(
@@ -297,7 +279,6 @@ func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue,
float64(100*process.PercentTimeinGC)/float64(process.PercentTimeinGC_base),
process.Name,
strconv.FormatUint(process.ProcessID, 10),
)
}

View File

@@ -95,7 +95,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.accessAccepts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_accepts"),
"(AccessAccepts)",
@@ -252,12 +252,12 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
errs := make([]error, 0)
c.accessPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccess](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "NPS Authentication Server", nil)
c.accessPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccess](pdh.CounterTypeRaw, "NPS Authentication Server", nil)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create NPS Authentication Server collector: %w", err))
}
c.accountingPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccounting](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "NPS Accounting Server", nil)
c.accountingPerfDataCollector, err = pdh.NewCollector[perfDataCounterValuesAccounting](pdh.CounterTypeRaw, "NPS Accounting Server", nil)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create NPS Accounting Server collector: %w", err))
}

View File

@@ -44,11 +44,8 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config
installTimeTimestamp float64
hostname *prometheus.Desc
osInformation *prometheus.Desc
installTime *prometheus.Desc
}
func New(config *Config) *Collector {
@@ -76,18 +73,11 @@ func (c *Collector) Close() error {
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
productName, revision, installationType, err := c.getWindowsVersion()
productName, revision, err := c.getWindowsVersion()
if err != nil {
return fmt.Errorf("failed to get Windows version: %w", err)
}
installTimeTimestamp, err := c.getInstallTime()
if err != nil {
return fmt.Errorf("failed to get install time: %w", err)
}
c.installTimeTimestamp = installTimeTimestamp
version := osversion.Get()
// Microsoft has decided to keep the major version as "10" for Windows 11, including the product name.
@@ -100,13 +90,12 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
`Contains full product name & version in labels. Note that the "major_version" for Windows 11 is \"10\"; a build number greater than 22000 represents Windows 11.`,
nil,
prometheus.Labels{
"product": productName,
"version": version.String(),
"major_version": strconv.FormatUint(uint64(version.MajorVersion), 10),
"minor_version": strconv.FormatUint(uint64(version.MinorVersion), 10),
"build_number": strconv.FormatUint(uint64(version.Build), 10),
"revision": revision,
"installation_type": installationType,
"product": productName,
"version": version.String(),
"major_version": strconv.FormatUint(uint64(version.MajorVersion), 10),
"minor_version": strconv.FormatUint(uint64(version.MinorVersion), 10),
"build_number": strconv.FormatUint(uint64(version.Build), 10),
"revision": revision,
},
)
@@ -121,13 +110,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
nil,
)
c.installTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "install_time_timestamp_seconds"),
"Unix timestamp of OS installation time",
nil,
nil,
)
return nil
}
@@ -142,12 +124,6 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
1.0,
)
ch <- prometheus.MustNewConstMetric(
c.installTime,
prometheus.GaugeValue,
c.installTimeTimestamp,
)
if err := c.collectHostname(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect hostname metrics: %w", err))
}
@@ -183,11 +159,11 @@ func (c *Collector) collectHostname(ch chan<- prometheus.Metric) error {
return nil
}
func (c *Collector) getWindowsVersion() (string, string, string, error) {
func (c *Collector) getWindowsVersion() (string, string, error) {
// Get build number and product name from registry
ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
if err != nil {
return "", "", "", fmt.Errorf("failed to open registry key: %w", err)
return "", "", fmt.Errorf("failed to open registry key: %w", err)
}
defer func(ntKey registry.Key) {
@@ -196,40 +172,15 @@ func (c *Collector) getWindowsVersion() (string, string, string, error) {
productName, _, err := ntKey.GetStringValue("ProductName")
if err != nil {
return "", "", "", err
}
installationType, _, err := ntKey.GetStringValue("InstallationType")
if err != nil {
return "", "", "", err
return "", "", err
}
revision, _, err := ntKey.GetIntegerValue("UBR")
if errors.Is(err, registry.ErrNotExist) {
revision = 0
} else if err != nil {
return "", "", "", err
return "", "", err
}
return strings.TrimSpace(productName), strconv.FormatUint(revision, 10), strings.TrimSpace(installationType), nil
}
func (c *Collector) getInstallTime() (float64, error) {
ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
if err != nil {
return 0, fmt.Errorf("failed to open registry key: %w", err)
}
defer func(ntKey registry.Key) {
_ = ntKey.Close()
}(ntKey)
installDate, _, err := ntKey.GetIntegerValue("InstallDate")
if errors.Is(err, registry.ErrNotExist) {
return 0, nil
} else if err != nil {
return 0, err
}
return float64(installDate), nil
return strings.TrimSpace(productName), strconv.FormatUint(revision, 10), nil
}

View File

@@ -75,7 +75,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.pagingLimitBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "limit_bytes"),
"Number of bytes that can be stored in the operating system paging files. 0 (zero) indicates that there are no paging files",
@@ -92,7 +92,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "Paging File", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Paging File", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Paging File collector: %w", err)
}

View File

@@ -216,7 +216,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
object.Type = pdh.CounterTypeRaw
}
collector, err := pdh.NewCollectorWithReflection(c.logger, object.Type, object.Object, object.Instances, valueType)
collector, err := pdh.NewCollectorWithReflection(object.Type, object.Object, object.Instances, valueType)
if err != nil {
errs = append(errs, fmt.Errorf("failed collector for %s: %w", object.Name, err))
}

View File

@@ -128,7 +128,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
c.requestsQueued = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "requests_queued"),
"The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)",
@@ -215,7 +215,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "PhysicalDisk", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "PhysicalDisk", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create PhysicalDisk collector: %w", err)
}

View File

@@ -54,7 +54,7 @@ var ConfigDefaults = Config{
ProcessExclude: types.RegExpEmpty,
EnableWorkerProcess: false,
EnableCMDLine: true,
CounterVersion: 1,
CounterVersion: 0,
}
type Collector struct {
@@ -187,11 +187,11 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
switch c.config.CounterVersion {
case 2:
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](c.logger, pdh.CounterTypeRaw, "Process V2", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Process V2", pdh.InstancesAll)
case 1:
c.perfDataCollector, err = registry.NewCollector[perfDataCounterValues]("Process", pdh.InstancesAll)
default:
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](c.logger, pdh.CounterTypeRaw, "Process V2", pdh.InstancesAll)
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "Process V2", pdh.InstancesAll)
c.config.CounterVersion = 2
if errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) {

View File

@@ -103,7 +103,7 @@ func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Build(*slog.Logger, *mi.Session) error {
// net
c.baseTCPRTT = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "net_base_tcp_rtt_seconds"),
@@ -232,12 +232,12 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
errs := make([]error, 0)
c.perfDataCollectorNetwork, err = pdh.NewCollector[perfDataCounterValuesNetwork](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "RemoteFX Network", pdh.InstancesAll)
c.perfDataCollectorNetwork, err = pdh.NewCollector[perfDataCounterValuesNetwork](pdh.CounterTypeRaw, "RemoteFX Network", pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create RemoteFX Network collector: %w", err))
}
c.perfDataCollectorGraphics, err = pdh.NewCollector[perfDataCounterValuesGraphics](logger.With(slog.String("collector", Name)), pdh.CounterTypeRaw, "RemoteFX Graphics", pdh.InstancesAll)
c.perfDataCollectorGraphics, err = pdh.NewCollector[perfDataCounterValuesGraphics](pdh.CounterTypeRaw, "RemoteFX Graphics", pdh.InstancesAll)
if err != nil {
errs = append(errs, fmt.Errorf("failed to create RemoteFX Graphics collector: %w", err))
}

Some files were not shown because too many files have changed in this diff Show More