Compare commits

...

85 Commits

Author SHA1 Message Date
renovate[bot]
fcf21bb600 fix(deps): update module github.com/prometheus/client_golang to v1.23.1 (#2199)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 21:37:06 +00:00
renovate[bot]
cd5f136079 chore(deps): update module google.golang.org/protobuf to v1.36.8 (#2198)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 18:52:32 +02:00
Jan-Otto Kröpke
4171ec17a5 chore: switch to go.yaml.in/yaml/v3 (#2196) 2025-09-04 23:50:27 +02:00
Karthik Panjaje
6289499dee docs: Fixed HTTP request metrics documentation (#2192) 2025-08-31 14:41:40 +00:00
Jan-Otto Kröpke
79917893d1 installer: set failureflag for Windows service (#2191) 2025-08-29 21:57:28 +02:00
Jan-Otto Kröpke
0b8a257b31 gpu: add device id label (#2186) 2025-08-28 06:36:10 +02:00
Jan-Otto Kröpke
71cedbc4d0 mi: remove callbacks (#2188) 2025-08-26 21:04:56 +02:00
Jan-Otto Kröpke
c8a4cb3806 mssql: expose correct patch level without restart (#2187) 2025-08-26 20:52:09 +02:00
Jan-Otto Kröpke
558629dff5 chore: update to go 1.25 (#2185) 2025-08-24 14:27:00 +02:00
Jan-Otto Kröpke
5a8ebf0c44 collector: support sub-second timeout values. (#2181) 2025-08-15 23:55:24 +02:00
PrometheusBot
acbabb926d Synchronize common files from prometheus/prometheus (#2180) 2025-08-15 20:34:45 +02:00
renovate[bot]
e37392c00b chore(deps): update dependency golangci/golangci-lint to v2.4.0 (#2179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-15 16:43:04 +02:00
renovate[bot]
00d86ba792 chore(deps): update actions/checkout action to v4.3.0 (#2178)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-15 16:42:52 +02:00
renovate[bot]
691f64f5cc fix(deps): update golang.org/x/ (#2170)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-10 15:39:40 +02:00
renovate[bot]
19999dea49 chore(deps): update docker/login-action action to v3.5.0 (#2169)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-10 15:39:24 +02:00
renovate[bot]
c2df4d7514 chore(deps): update actions/download-artifact action to v5 (#2171)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-08 15:48:04 +02:00
renovate[bot]
8937a5ac91 chore(deps): update module google.golang.org/protobuf to v1.36.7 (#2168)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-08 15:30:46 +02:00
Jan-Otto Kröpke
930130f58a collector: Add disable flag (#2165)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-07 08:58:29 +02:00
Jan-Otto Kröpke
0e85959a4d installer: do not fail, if service can't be started. (#2163) 2025-08-03 20:11:57 +02:00
Jan-Otto Kröpke
6253bf812d process: Add flag to control the export of the process cmdline (#2153) 2025-08-03 20:09:03 +02:00
Jan-Otto Kröpke
6c2380bd04 installer: disable config file creation, if CONFIG_FILE is set to a non default location. (#2162) 2025-08-03 20:08:13 +02:00
Jan-Otto Kröpke
5266f9ebfe installer: add quote to avoid argument splitting (#2161) 2025-08-03 19:39:59 +02:00
renovate[bot]
6c9a5b66e2 chore(deps): update dependency golangci/golangci-lint to v2.3.1 (#2158)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>
2025-08-03 04:27:21 +02:00
renovate[bot]
c4ab8cb8a5 chore(deps): update docker/metadata-action action to v5.8.0 (#2159)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-01 21:01:20 +02:00
renovate[bot]
7bcaf81d26 fix(deps): update module github.com/prometheus/client_golang to v1.23.0 (#2160)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-01 20:49:03 +02:00
renovate[bot]
5f6ba2c6e7 fix(deps): update module github.com/bmatcuk/doublestar/v4 to v4.9.1 (#2157)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-01 15:47:11 +02:00
Jan-Otto Kröpke
75c85fbde1 docs: add note about property preferences (#2155) 2025-07-29 20:53:50 +02:00
Jan-Otto Kröpke
120c244313 docs: Update example_config.yml (#2152) 2025-07-28 22:53:13 +02:00
Jan-Otto Kröpke
0e2d78affe docs: allow backport PR title prefix. (#2142) 2025-07-20 02:30:42 +02:00
Jan-Otto Kröpke
f0591d85cd process: fix windows_process_start_time_seconds_timestamp return relative time on Windows Server 2019 (#2137) 2025-07-20 02:14:17 +02:00
Jan-Otto Kröpke
255b01f610 container: fix network metrics (#2136) 2025-07-17 21:07:55 +02:00
Jan-Otto Kröpke
ab7db07836 filetime: support windows paths (#2118) 2025-07-13 02:01:44 +02:00
Jan-Otto Kröpke
52056a5cd9 filetime: support case insensitive matching (#2132) 2025-07-12 23:51:40 +00:00
Jan-Otto Kröpke
524fea08c4 gpu: fix windows_gpu_info metric (#2130) 2025-07-13 01:05:59 +02:00
Jan-Otto Kröpke
6b8c895a68 container: fix memory leaks (#2129) 2025-07-11 20:10:45 +02:00
Jan-Otto Kröpke
eade0da514 config: fix lists (#2124) 2025-07-11 19:50:58 +02:00
renovate[bot]
b07e866b4a chore(deps): update dependency golangci/golangci-lint to v2.2.2 (#2126)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 19:50:19 +02:00
renovate[bot]
98618408ce fix(deps): update golang.org/x/ (#2127)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 18:33:04 +02:00
Jan-Otto Kröpke
56b9f7fd27 docs: strip readme to avoid dockerhub limitations (#2123) 2025-07-09 20:17:26 +02:00
Jan-Otto Kröpke
8d267336c1 Update README.md (#2121) 2025-07-08 18:17:07 +02:00
Jan-Otto Kröpke
fd7070354a cs: remove deprecated cs collector (#2115) 2025-07-05 15:47:57 +02:00
Jan-Otto Kröpke
373d741260 os: remove deprecated metrics (#2116) 2025-07-05 15:44:57 +02:00
Jan-Otto Kröpke
ed15b3c671 system: remove windows_system_boot_time_timestamp_seconds (#2112) 2025-07-05 15:40:09 +02:00
Jan-Otto Kröpke
f8805932b2 logon: remove logon collector. Use terminal_services instead. (#2114) 2025-07-05 15:34:04 +02:00
Jan-Otto Kröpke
4fd26fa0fa update: remove deprecated flags (#2113) 2025-07-05 15:32:59 +02:00
Jan-Otto Kröpke
bf722630d6 mssql: fix ratio based counter (#2096) 2025-07-05 00:20:28 +02:00
renovate[bot]
9320e992cc chore(deps): update dependency golangci/golangci-lint to v2.2.1 (#2110)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>
2025-07-05 00:08:07 +02:00
renovate[bot]
7a4e92a473 chore(deps): update module github.com/prometheus/procfs to v0.17.0 (#2111)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 21:51:47 +02:00
Szymon Sobocki
02b9ab4058 mssql: fix incorrect patch version in windows_mssql_instance_info (#2109) 2025-07-04 09:42:26 +00:00
Jan-Otto Kröpke
c3043693df fix: add missing concurrency lock (#2098) 2025-07-04 11:14:49 +02:00
Jan-Otto Kröpke
7377d48f07 iis: missing metrics if app-include is set. (#2103) 2025-07-02 16:32:29 +02:00
Jan-Otto Kröpke
d64f1316ca os: missing deprecated metric windows_os_processes (#2104) 2025-07-02 00:50:03 +02:00
Jan-Otto Kröpke
492f3af317 diskdrive: fix not exposing state "Pred Fail" (#2101) 2025-06-30 19:55:45 +02:00
nbav12
116203fd19 Update collector.mscluster.md (#2099) 2025-06-30 11:54:41 +02:00
Jan-Otto Kröpke
66751baef6 process: do not fail, if collector.process.iis is enabled and WMI WebAdministration is not present. (#2082) 2025-06-29 14:12:56 +02:00
renovate[bot]
b02bddd38e fix(deps): update module github.com/prometheus/common to v0.65.0 (#2095)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 15:30:59 +00:00
Jan-Otto Kröpke
3dbc19e18b docs: add note about Server 2012 (#2093) 2025-06-21 11:28:58 +02:00
renovate[bot]
be481e8776 chore(deps): update docker/setup-buildx-action action to v3.11.1 (#2088)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-20 15:40:55 +02:00
Jan-Otto Kröpke
aea5c5a2fb docs: Clearify Windows Server 2012R2 support (#2087) 2025-06-20 15:33:34 +02:00
Lapo Luchini
59ac3072b1 feat: increase time resolution when possible (collectors: os, system, time) (#2047) 2025-06-20 13:12:26 +02:00
Jan-Otto Kröpke
66cd489c4a dhcp: fix log level for dhcp server, if not present (#2086) 2025-06-20 10:15:14 +02:00
Jan-Otto Kröpke
4891e23d29 fix: added count checks (#2083) 2025-06-19 16:59:19 +02:00
Nic Jansma
f285c3d1e2 logical_disk: skip unmounted volumes (#2084) 2025-06-18 07:59:50 +02:00
Jan-Otto Kröpke
90dac66bf5 config: fix validation error with empty config files (#2080) 2025-06-16 19:53:14 +02:00
Jan-Otto Kröpke
34cfda306b logical_disk: add bitlocker status sub-collector (#2077) 2025-06-16 12:48:23 +02:00
Sanjeevi Subramani
3e8693f1e3 iis: Add HTTP Service Request Queues (#1948)
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>
2025-06-15 07:40:21 +02:00
renovate[bot]
036c858355 chore(deps): update golang.org/x/ (#2078)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-13 16:38:52 +02:00
Sam DeHaan
a69720ae1d docs: fix typo in dns docs subcollector name (#2073) 2025-06-05 01:14:51 +02:00
Jan-Otto Kröpke
55c877f536 gpu: add info metric about devices (#2070) 2025-06-04 22:49:59 +02:00
小荣
dcf85032ca gpu: add metrics collector and related types (#2052) (#2059) 2025-06-02 19:45:18 +02:00
Jan-Otto Kröpke
e673f192d2 process: add collector.process.counter-version CLI parameter (#2064) 2025-05-31 08:46:30 +02:00
Jan-Otto Kröpke
298d820bd6 time: expose clock source sync (#2058) 2025-05-30 19:52:27 +02:00
Jan-Otto Kröpke
89ac99e6a2 chore: Update renovate.json (#2069) 2025-05-29 22:09:05 +02:00
renovate[bot]
3e58d0e568 chore(deps): update docker/build-push-action action to v6.18.0 (#2067)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-29 22:05:57 +02:00
Jan-Otto Kröpke
5cf1f7e623 chore: Update renovate.json (#2068) 2025-05-29 22:05:47 +02:00
Jan-Otto Kröpke
0580b330a5 fix: Avoid COINIT_MULTITHREADED in CoInitializeEx (#2066) 2025-05-29 21:58:42 +02:00
PrometheusBot
25915bb289 Synchronize common files from prometheus/prometheus (#2061) 2025-05-26 22:23:17 +02:00
Jan-Otto Kröpke
5e1a802237 container: fix collector (#2057) 2025-05-24 11:29:52 +02:00
Jan-Otto Kröpke
6dd21a8e00 update: expose publish date of updates (#2050) 2025-05-23 21:18:29 +02:00
Jan-Otto Kröpke
92f213ca7c chore: fix test (#2055) 2025-05-23 08:12:25 +02:00
Jan-Otto Kröpke
ecd7dcfb0d service: report invalid parameter errors as debug (#2051) 2025-05-22 19:19:19 +02:00
Karl Persson
87d76b18e9 update: export properties so that they can be read from yaml file (#2053) 2025-05-22 16:22:06 +02:00
Jan-Otto Kröpke
068bcb7237 tcp: relax metrics collectos on error (#2041) 2025-05-20 15:37:01 +02:00
Jan-Otto Kröpke
898e16bcb1 container: support hostprocess containers and expose kubernetes labels (#1911) 2025-05-18 09:39:52 +02:00
Martin Costello
6b87441729 docs: Fix typo (#2042) 2025-05-18 07:50:31 +02:00
169 changed files with 5471 additions and 2246 deletions

View File

@@ -4,7 +4,11 @@ labels: [ 🐞 bug ]
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: Thanks for taking the time to fill out this bug report! value: |-
> [!NOTE]
> Windows Server 2012 and Windows Server 2012 R2 are no longer supported by the windows_exporter project.
Thanks for taking the time to fill out this bug report!
- type: markdown - type: markdown
attributes: attributes:

View File

@@ -19,6 +19,8 @@ jobs:
steps: steps:
- name: git checkout - name: git checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set docker hub repo name - name: Set docker hub repo name
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
- name: Push README to Dockerhub - name: Push README to Dockerhub
@@ -41,6 +43,8 @@ jobs:
steps: steps:
- name: git checkout - name: git checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set quay.io org name - name: Set quay.io org name
run: echo "DOCKER_REPO=$(echo quay.io/${GITHUB_REPOSITORY_OWNER} | tr -d '-')" >> $GITHUB_ENV run: echo "DOCKER_REPO=$(echo quay.io/${GITHUB_REPOSITORY_OWNER} | tr -d '-')" >> $GITHUB_ENV
- name: Set quay.io repo name - name: Set quay.io repo name

View File

@@ -20,7 +20,7 @@ jobs:
test: test:
runs-on: windows-2025 runs-on: windows-2025
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
@@ -43,7 +43,7 @@ jobs:
promtool: promtool:
runs-on: windows-2025 runs-on: windows-2025
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
@@ -82,7 +82,7 @@ jobs:
git config --global core.autocrlf false git config --global core.autocrlf false
git config --global core.eol lf git config --global core.eol lf
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
@@ -91,5 +91,5 @@ jobs:
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
with: with:
# renovate: github=golangci/golangci-lint # renovate: github=golangci/golangci-lint
version: v2.1.6 version: v2.4.0
args: "--max-same-issues=0" args: "--max-same-issues=0"

View File

@@ -33,11 +33,11 @@ jobs:
name: check title prefix name: check title prefix
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: check - name: check
run: | run: |
PR_TITLE_PREFIX=$(echo "$PR_TITLE" | cut -d':' -f1) PR_TITLE_PREFIX=$(echo "$PR_TITLE" | cut -d':' -f1)
if [[ -d "internal/collector/$PR_TITLE_PREFIX" ]] || [[ -d "internal/$PR_TITLE_PREFIX" ]] || [[ -d "pkg/$PR_TITLE_PREFIX" ]] || [[ -d "$PR_TITLE_PREFIX" ]] || [[ "$PR_TITLE_PREFIX" == "docs" ]] || [[ "$PR_TITLE_PREFIX" == "ci" ]] || [[ "$PR_TITLE_PREFIX" == "revert" ]] || [[ "$PR_TITLE_PREFIX" == "fix" ]] || [[ "$PR_TITLE_PREFIX" == "fix(deps)" ]] || [[ "$PR_TITLE_PREFIX" == "feat" ]] || [[ "$PR_TITLE_PREFIX" == "chore" ]] || [[ "$PR_TITLE_PREFIX" == "chore(docs)" ]] || [[ "$PR_TITLE_PREFIX" == "chore(deps)" ]] || [[ "$PR_TITLE_PREFIX" == "*" ]] || [[ "$PR_TITLE_PREFIX" == "Release"* ]] || [[ "$PR_TITLE_PREFIX" == "Synchronize common files from prometheus/prometheus" ]]; then if [[ -d "internal/collector/$PR_TITLE_PREFIX" ]] || [[ -d "internal/$PR_TITLE_PREFIX" ]] || [[ -d "pkg/$PR_TITLE_PREFIX" ]] || [[ -d "$PR_TITLE_PREFIX" ]] || [[ "$PR_TITLE_PREFIX" == "docs" ]] || [[ "$PR_TITLE_PREFIX" == "ci" ]] || [[ "$PR_TITLE_PREFIX" == "revert" ]] || [[ "$PR_TITLE_PREFIX" == "fix" ]] || [[ "$PR_TITLE_PREFIX" == "fix(deps)" ]] || [[ "$PR_TITLE_PREFIX" == "feat" ]] || [[ "$PR_TITLE_PREFIX" == "chore" ]] || [[ "$PR_TITLE_PREFIX" == "chore(docs)" ]] || [[ "$PR_TITLE_PREFIX" == "chore(deps)" ]] || [[ "$PR_TITLE_PREFIX" == "*" ]] || [[ "$PR_TITLE_PREFIX" == "Release"* ]] || [[ "$PR_TITLE_PREFIX" == "Synchronize common files from prometheus/prometheus" ]] || [[ "$PR_TITLE_PREFIX" == "[0."* ]] || [[ "$PR_TITLE_PREFIX" == "[1."* ]]; then
exit 0 exit 0
fi fi

View File

@@ -24,7 +24,7 @@ jobs:
runs-on: windows-2025 runs-on: windows-2025
environment: build environment: build
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with: with:
fetch-depth: '0' fetch-depth: '0'
@@ -180,25 +180,25 @@ jobs:
DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false DOCKER_BUILD_RECORD_UPLOAD: false
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with: with:
fetch-depth: '0' fetch-depth: '0'
- name: Download Artifacts - name: Download Artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with: with:
name: windows_exporter_binaries name: windows_exporter_binaries
- name: Login to Docker Hub - name: Login to Docker Hub
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with: with:
username: ${{ secrets.DOCKER_HUB_LOGIN }} username: ${{ secrets.DOCKER_HUB_LOGIN }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }} password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Login to quay.io - name: Login to quay.io
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with: with:
registry: quay.io registry: quay.io
username: ${{ secrets.QUAY_IO_LOGIN }} username: ${{ secrets.QUAY_IO_LOGIN }}
@@ -206,7 +206,7 @@ jobs:
- name: Login to GitHub container registry - name: Login to GitHub container registry
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
@@ -214,7 +214,7 @@ jobs:
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
with: with:
images: | images: |
ghcr.io/prometheus-community/windows-exporter ghcr.io/prometheus-community/windows-exporter
@@ -231,10 +231,10 @@ jobs:
org.opencontainers.image.licenses=MIT org.opencontainers.image.licenses=MIT
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Build and push - name: Build and push
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0 uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with: with:
context: . context: .
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}

View File

@@ -17,7 +17,7 @@ jobs:
name: Check for spelling errors name: Check for spelling errors
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- uses: codespell-project/actions-codespell@master - uses: codespell-project/actions-codespell@master
with: with:
check_filenames: true check_filenames: true

16
.gitignore vendored
View File

@@ -4,9 +4,21 @@ VERSION
*.un~ *.un~
output/ output/
.vscode .vscode
.idea
*.syso *.syso
installer/*.msi installer/*.msi
installer/*.log
installer/*.wixpdb installer/*.wixpdb
local/ local/
!.idea/inspectionProfiles/Project_Default.xml
/.idea/*
!/.idea/inspectionProfiles/
/.idea/inspectionProfiles/*
!/.idea/inspectionProfiles/Project_Default.xml
!/.idea/dictionaries/
/.idea/dictionaries/*
!/.idea/dictionaries/project.xml
/.idea/copyright/*
!/.idea/copyright/profiles_settings.xml
!/.idea/copyright/windows_exporter.xml
!/.idea/vcs.xml
!/.idea/go.imports.xml

View File

@@ -4,6 +4,7 @@ linters:
disable: disable:
- cyclop - cyclop
- depguard - depguard
- dogsled
- dupl - dupl
- err113 - err113
- exhaustive - exhaustive
@@ -18,11 +19,13 @@ linters:
- lll - lll
- maintidx - maintidx
- mnd - mnd
- noinlineerr
- paralleltest - paralleltest
- tagliatelle - tagliatelle
- testpackage - testpackage
- varnamelen - varnamelen
- wrapcheck - wrapcheck
- wsl
settings: settings:
forbidigo: forbidigo:
forbid: forbid:
@@ -56,6 +59,18 @@ linters:
excludes: excludes:
- G101 - G101
- G115 - G115
govet:
enable-all: true
disable:
- fieldalignment
- shadow
revive:
rules:
- name: var-naming
arguments:
- [ ] # AllowList - do not remove as args for the rule are positional and won't work without lists first
- [ ] # DenyList
- - skip-package-name-checks: true
sloglint: sloglint:
no-mixed-args: true no-mixed-args: true
kv-only: false kv-only: false

11
.idea/copyright/profiles_settings.xml generated Normal file
View File

@@ -0,0 +1,11 @@
<component name="CopyrightManager">
<settings default="windows_exporter">
<module2copyright>
<element module="All Changed Files" copyright="windows_exporter" />
</module2copyright>
<LanguageOptions name="Go">
<option name="fileTypeOverride" value="3" />
<option name="block" value="false" />
</LanguageOptions>
</settings>
</component>

7
.idea/copyright/windows_exporter.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<component name="CopyrightManager">
<copyright>
<option name="keyword" value="The Prometheus Authors" />
<option name="notice" value="SPDX-License-Identifier: Apache-2.0&#10;&#10;Copyright The Prometheus Authors&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10;http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License." />
<option name="myName" value="windows_exporter" />
</copyright>
</component>

16
.idea/dictionaries/project.xml generated Normal file
View File

@@ -0,0 +1,16 @@
<component name="ProjectDictionaryState">
<dictionary name="project">
<words>
<w>containerd</w>
<w>endpointstats</w>
<w>gochecknoglobals</w>
<w>lpwstr</w>
<w>luid</w>
<w>operationoptions</w>
<w>setupapi</w>
<w>spdx</w>
<w>textfile</w>
<w>vmcompute</w>
</words>
</dictionary>
</component>

11
.idea/go.imports.xml generated Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GoImports">
<option name="excludedPackages">
<array>
<option value="github.com/pkg/errors" />
<option value="golang.org/x/net/context" />
</array>
</option>
</component>
</project>

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GoLinter" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -19,7 +19,7 @@
<configuration default="false" name="all" type="GoApplicationRunConfiguration" factoryName="Go Application" folderName="run"> <configuration default="false" name="all" type="GoApplicationRunConfiguration" factoryName="Go Application" folderName="run">
<module name="windows_exporter" /> <module name="windows_exporter" />
<working_directory value="$PROJECT_DIR$" /> <working_directory value="$PROJECT_DIR$" />
<parameters value="--web.listen-address=127.0.0.1:9182 --log.level=info --collectors.enabled=ad,adcs,adfs,cache,container,cpu,cpu_info,cs,dfsr,dhcp,diskdrive,dns,exchange,filetime,fsrmquota,hyperv,iis,license,logical_disk,logon,memory,mscluster,msmq,mssql,net,netframework,nps,os,pagefile,performancecounter,physical_disk,printer,process,remote_fx,scheduled_task,service,smb,smbclient,smtp,system,tcp,terminal_services,thermalzone,time,udp,update,vmware,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" /> <sudo value="true" />
<kind value="PACKAGE" /> <kind value="PACKAGE" />
<package value="github.com/prometheus-community/windows_exporter/cmd/windows_exporter" /> <package value="github.com/prometheus-community/windows_exporter/cmd/windows_exporter" />

View File

@@ -29,7 +29,7 @@ test:
go test -v ./... go test -v ./...
bench: bench:
go test -v -bench='benchmarkcollector' ./internal/collectors/{cpu,logical_disk,physical_disk,logon,memory,net,printer,process,service,system,tcp,time} go test -v -bench='benchmarkcollector' ./internal/collectors/{cpu,logical_disk,physical_disk,memory,net,printer,process,service,system,tcp,time}
lint: lint:
golangci-lint -c .golangci.yaml run golangci-lint -c .golangci.yaml run

179
README.md
View File

@@ -1,4 +1,4 @@
config.file# windows_exporter # windows_exporter
[![CI](https://github.com/prometheus-community/windows_exporter/actions/workflows/release.yml/badge.svg)](https://github.com/prometheus-community/windows_exporter) [![CI](https://github.com/prometheus-community/windows_exporter/actions/workflows/release.yml/badge.svg)](https://github.com/prometheus-community/windows_exporter)
[![Linting](https://github.com/prometheus-community/windows_exporter/actions/workflows/lint.yml/badge.svg)](https://github.com/prometheus-community/windows_exporter) [![Linting](https://github.com/prometheus-community/windows_exporter/actions/workflows/lint.yml/badge.svg)](https://github.com/prometheus-community/windows_exporter)
@@ -12,54 +12,54 @@ A Prometheus exporter for Windows machines.
## Collectors ## Collectors
Name | Description | Enabled by default | Name | Description | Enabled by default |
---------|-------------|-------------------- |------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
[ad](docs/collector.ad.md) | Active Directory Domain Services | | [ad](docs/collector.ad.md) | Active Directory Domain Services | |
[adcs](docs/collector.adcs.md) | Active Directory Certificate Services | | [adcs](docs/collector.adcs.md) | Active Directory Certificate Services | |
[adfs](docs/collector.adfs.md) | Active Directory Federation Services | | [adfs](docs/collector.adfs.md) | Active Directory Federation Services | |
[cache](docs/collector.cache.md) | Cache metrics | | [cache](docs/collector.cache.md) | Cache metrics | |
[cpu](docs/collector.cpu.md) | CPU usage | &#10003; | [cpu](docs/collector.cpu.md) | CPU usage | &#10003; |
[cpu_info](docs/collector.cpu_info.md) | CPU Information | | [cpu_info](docs/collector.cpu_info.md) | CPU Information | |
[cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) | | [container](docs/collector.container.md) | Container metrics | |
[container](docs/collector.container.md) | Container metrics | | [diskdrive](docs/collector.diskdrive.md) | Diskdrive metrics | |
[diskdrive](docs/collector.diskdrive.md) | Diskdrive metrics | | [dfsr](docs/collector.dfsr.md) | DFSR metrics | |
[dfsr](docs/collector.dfsr.md) | DFSR metrics | | [dhcp](docs/collector.dhcp.md) | DHCP Server | |
[dhcp](docs/collector.dhcp.md) | DHCP Server | | [dns](docs/collector.dns.md) | DNS Server | |
[dns](docs/collector.dns.md) | DNS Server | | [exchange](docs/collector.exchange.md) | Exchange metrics | |
[exchange](docs/collector.exchange.md) | Exchange metrics | | [filetime](docs/collector.filetime.md) | FileTime metrics | |
[filetime](docs/collector.filetime.md) | FileTime metrics | | [fsrmquota](docs/collector.fsrmquota.md) | Microsoft File Server Resource Manager (FSRM) Quotas collector | |
[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 | | [hyperv](docs/collector.hyperv.md) | Hyper-V hosts | |
[iis](docs/collector.iis.md) | IIS sites and applications | | [iis](docs/collector.iis.md) | IIS sites and applications | |
[license](docs/collector.license.md) | Windows license status | | [license](docs/collector.license.md) | Windows license status | |
[logical_disk](docs/collector.logical_disk.md) | Logical disks, disk I/O | &#10003; | [logical_disk](docs/collector.logical_disk.md) | Logical disks, disk I/O | &#10003; |
[memory](docs/collector.memory.md) | Memory usage metrics | &#10003; | [memory](docs/collector.memory.md) | Memory usage metrics | &#10003; |
[mscluster](docs/collector.mscluster.md) | MSCluster metrics | | [mscluster](docs/collector.mscluster.md) | MSCluster metrics | |
[msmq](docs/collector.msmq.md) | MSMQ queues | | [msmq](docs/collector.msmq.md) | MSMQ queues | |
[mssql](docs/collector.mssql.md) | [SQL Server Performance Objects](https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/use-sql-server-objects#SQLServerPOs) metrics | | [mssql](docs/collector.mssql.md) | [SQL Server Performance Objects](https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/use-sql-server-objects#SQLServerPOs) metrics | |
[netframework](docs/collector.netframework.md) | .NET Framework metrics | | [netframework](docs/collector.netframework.md) | .NET Framework metrics | |
[net](docs/collector.net.md) | Network interface I/O | &#10003; | [net](docs/collector.net.md) | Network interface I/O | &#10003; |
[os](docs/collector.os.md) | OS metrics (memory, processes, users) | &#10003; | [os](docs/collector.os.md) | OS metrics (memory, processes, users) | &#10003; |
[pagefile](docs/collector.pagefile.md) | pagefile metrics | | [pagefile](docs/collector.pagefile.md) | pagefile metrics | |
[performancecounter](docs/collector.performancecounter.md) | Custom performance counter metrics | | [performancecounter](docs/collector.performancecounter.md) | Custom performance counter metrics | |
[physical_disk](docs/collector.physical_disk.md) | physical disk metrics | &#10003; | [physical_disk](docs/collector.physical_disk.md) | physical disk metrics | &#10003; |
[printer](docs/collector.printer.md) | Printer metrics | | [printer](docs/collector.printer.md) | Printer metrics | |
[process](docs/collector.process.md) | Per-process metrics | | [process](docs/collector.process.md) | Per-process metrics | |
[remote_fx](docs/collector.remote_fx.md) | RemoteFX protocol (RDP) metrics | | [remote_fx](docs/collector.remote_fx.md) | RemoteFX protocol (RDP) metrics | |
[scheduled_task](docs/collector.scheduled_task.md) | Scheduled Tasks metrics | | [scheduled_task](docs/collector.scheduled_task.md) | Scheduled Tasks metrics | |
[service](docs/collector.service.md) | Service state metrics | &#10003; | [service](docs/collector.service.md) | Service state metrics | &#10003; |
[smb](docs/collector.smb.md) | SMB Server | | [smb](docs/collector.smb.md) | SMB Server | |
[smbclient](docs/collector.smbclient.md) | SMB Client | | [smbclient](docs/collector.smbclient.md) | SMB Client | |
[smtp](docs/collector.smtp.md) | IIS SMTP Server | | [smtp](docs/collector.smtp.md) | IIS SMTP Server | |
[system](docs/collector.system.md) | System calls | &#10003; | [system](docs/collector.system.md) | System calls | &#10003; |
[tcp](docs/collector.tcp.md) | TCP connections | | [tcp](docs/collector.tcp.md) | TCP connections | |
[terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS) | [terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS) | |
[textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file | | [textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file | |
[thermalzone](docs/collector.thermalzone.md) | Thermal information | | [thermalzone](docs/collector.thermalzone.md) | Thermal information | |
[time](docs/collector.time.md) | Windows Time Service | | [time](docs/collector.time.md) | Windows Time Service | |
[udp](docs/collector.udp.md) | UDP connections | | [udp](docs/collector.udp.md) | UDP connections | |
[update](docs/collector.update.md) | Windows Update Service | | [update](docs/collector.update.md) | Windows Update Service | |
[vmware](docs/collector.vmware.md) | Performance counters installed by the Vmware Guest agent | | [vmware](docs/collector.vmware.md) | Performance counters installed by the Vmware Guest agent | |
See the linked documentation on each collector for more information on reported metrics, configuration settings and usage examples. See the linked documentation on each collector for more information on reported metrics, configuration settings and usage examples.
@@ -82,15 +82,15 @@ This can be useful for having different Prometheus servers collect specific metr
windows_exporter accepts flags to configure certain behaviours. The ones configuring the global behaviour of the exporter are listed below, while collector-specific ones are documented in the respective collector documentation above. windows_exporter accepts flags to configure certain behaviours. The ones configuring the global behaviour of the exporter are listed below, while collector-specific ones are documented in the respective collector documentation above.
| Flag | Description | Default value | | Flag | Description | Default value |
|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------| |---------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| `--web.listen-address` | host:port for exporter. | `:9182` | | `--web.listen-address` | host:port for exporter. | `:9182` |
| `--telemetry.path` | URL path for surfacing collected metrics. | `/metrics` | | `--telemetry.path` | URL path for surfacing collected metrics. | `/metrics` |
| `--collectors.enabled` | Comma-separated list of collectors to use. Use `[defaults]` as a placeholder which gets expanded containing all the collectors enabled by default. | `[defaults]` | | `--collectors.enabled` | Comma-separated list of collectors to use. Use `[defaults]` as a placeholder which gets expanded containing all the collectors enabled by default. | `[defaults]` |
| `--scrape.timeout-margin` | Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads. | `0.5` | | `--scrape.timeout-margin` | Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads. | `0.5` |
| `--web.config.file` | A [web config][web_config] for setting up TLS and Auth | None | | `--web.config.file` | A [web config][web_config] for setting up TLS and Auth | None |
| `--config.file` | [Using a config file](#using-a-configuration-file) from path or URL | None | | `--config.file` | [Using a config file](#using-a-configuration-file) from path | None |
| `--log.file` | Output file of log messages. One of [stdout, stderr, eventlog, \<path to log file>]<br>**NOTE:** The MSI installer will add a default argument to the installed service setting this to eventlog | stderr | | `--log.file` | Output file of log messages. One of [stdout, stderr, eventlog, \<path to log file>]<br>**NOTE:** The MSI installer will add a default argument to the installed service setting this to eventlog | stderr |
## Installation ## Installation
@@ -112,20 +112,22 @@ The configuration file
The following parameters are available: The following parameters are available:
| Name | Description | | Name | Description |
|----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ENABLED_COLLECTORS` | As the `--collectors.enabled` flag, provide a comma-separated list of enabled collectors | | `ENABLED_COLLECTORS` | As the `--collectors.enabled` flag, provide a comma-separated list of enabled collectors |
| `CONFIG_FILE` | Use the `--config.file` flag to specify a config file. If empty, no config file will be set. The special value `config.yaml` set the path to the config.yaml at install dir | | | `CONFIG_FILE` | Use the `--config.file` flag to specify a config file. If empty, default config file at install dir will be used. If set, the config file must be exist before the installation is started. | |
| `LISTEN_ADDR` | The IP address to bind to. Defaults to an empty string. (any local address) | | `LISTEN_ADDR` | The IP address to bind to. Defaults to an empty string. (any local address) |
| `LISTEN_PORT` | The port to bind to. Defaults to `9182`. | | `LISTEN_PORT` | The port to bind to. Defaults to `9182`. |
| `METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics` | | `METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics` |
| `TEXTFILE_DIRS` | Use the `--collector.textfile.directories` flag to specify one or more directories, separated by commas, where the collector should read text files containing metrics | | `TEXTFILE_DIRS` | Use the `--collector.textfile.directories` flag to specify one or more directories, separated by commas, where the collector should read text files containing metrics |
| `REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (allow list). Defaults to an empty string (any remote address). | | `REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (allow list). Defaults to an empty string (any remote address). |
| `EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string. For `--collectors.enabled` and `--config.file`, use the specialized properties `ENABLED_COLLECTORS` and `CONFIG_FILE` | | `EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string. For `--collectors.enabled` and `--config.file`, use the specialized properties `ENABLED_COLLECTORS` and `CONFIG_FILE` |
| `ADDLOCAL` | Enables features within the windows_exporter installer. Supported values: `FirewallException` | | `ADDLOCAL` | Enables features within the windows_exporter installer. Supported values: `FirewallException` |
| `REMOVE` | Disables features within the windows_exporter installer. Supported values: `FirewallException` | | `REMOVE` | Disables features within the windows_exporter installer. Supported values: `FirewallException` |
| `APPLICATIONFOLDER` | Directory to install windows_exporter. Defaults to `C:\Program Files\windows_exporter` | | `APPLICATIONFOLDER` | Directory to install windows_exporter. Defaults to `C:\Program Files\windows_exporter` |
> [!NOTE]
> The installer properties are always preferred over the values defined in the config file. If you prefer to configure via the config file, avoid using any of the properties listed above.
Parameters are sent to the installer via `msiexec`. Parameters are sent to the installer via `msiexec`.
On PowerShell, the `--%` should be passed before defining properties. On PowerShell, the `--%` should be passed before defining properties.
@@ -154,7 +156,7 @@ msiexec /i <path-to-msi-file> --% ADDLOCAL=FirewallException APPLICATIONFOLDER="
On some older versions of Windows, On some older versions of Windows,
you may need to surround parameter values with double quotes to get the installation command parsing properly: you may need to surround parameter values with double quotes to get the installation command parsing properly:
```powershell ```powershell
msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi --% ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,textfile,thermalzone" TEXTFILE_DIRS="C:\custom_metrics\" msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi --% ENABLED_COLLECTORS="ad,iis,memory,process,tcp,textfile,thermalzone" TEXTFILE_DIRS="C:\custom_metrics\"
``` ```
To install the exporter with creating a firewall exception, use the following command: To install the exporter with creating a firewall exception, use the following command:
@@ -182,9 +184,6 @@ The windows_exporter can be run as a Docker container. The Docker image is avail
The Docker image is tagged with the version of the exporter. The `latest` tag is also available and points to the latest release. The Docker image is tagged with the version of the exporter. The `latest` tag is also available and points to the latest release.
Additionally, a flavor `hostprocess` with `-hostprocess` as suffix is based on the https://github.com/microsoft/windows-host-process-containers-base-image
which is designed to run as a Windows host process container. The size of that images is smaller than the default one.
## Kubernetes Implementation ## Kubernetes Implementation
See detailed steps to install on Windows Kubernetes [here](./kubernetes/kubernetes.md). See detailed steps to install on Windows Kubernetes [here](./kubernetes/kubernetes.md).
@@ -193,17 +192,7 @@ See detailed steps to install on Windows Kubernetes [here](./kubernetes/kubernet
`windows_exporter` supports Windows Server versions 2016 and later, and desktop Windows version 10 and 11 (21H2 or later). `windows_exporter` supports Windows Server versions 2016 and later, and desktop Windows version 10 and 11 (21H2 or later).
Windows Server 2012 and 2012R2 are supported as best-effort only, but not guaranteed to work. There are known compatibility issues with Windows Server 2012 R2 and earlier versions.
## Usage
go get -u github.com/prometheus/promu
go get -u github.com/prometheus-community/windows_exporter
cd $env:GOPATH/src/github.com/prometheus-community/windows_exporter
promu build -v
.\windows_exporter.exe
The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182)
### HTTP Endpoints ### HTTP Endpoints
@@ -213,18 +202,6 @@ windows_exporter provides the following HTTP endpoints:
* `/health`: Returns 200 OK when the exporter is running. * `/health`: Returns 200 OK when the exporter is running.
* `/debug/pprof/`: Exposes the [pprof](https://golang.org/pkg/net/http/pprof/) endpoints. Only, if `--debug.enabled` is set. * `/debug/pprof/`: Exposes the [pprof](https://golang.org/pkg/net/http/pprof/) endpoints. Only, if `--debug.enabled` is set.
## Examples
### Enable only service collector and specify a custom query
.\windows_exporter.exe --collectors.enabled "service" --collector.service.include="windows_exporter"
### Enable only process collector and specify a custom query
.\windows_exporter.exe --collectors.enabled "process" --collector.process.include="firefox.+"
When there are multiple processes with the same name, WMI represents those after the first instance as `process-name#index`. So to get them all, rather than just the first one, the [regular expression](https://en.wikipedia.org/wiki/Regular_expression) must use `.+`. See [process](docs/collector.process.md) for more information.
### Using [defaults] with `--collectors.enabled` argument ### Using [defaults] with `--collectors.enabled` argument
Using `[defaults]` with `--collectors.enabled` argument which gets expanded with all default collectors. Using `[defaults]` with `--collectors.enabled` argument which gets expanded with all default collectors.
@@ -237,10 +214,6 @@ This enables the additional process and container collectors on top of the defau
YAML configuration files can be specified with the `--config.file` flag. e.g. `.\windows_exporter.exe --config.file=config.yml`. If you are using the absolute path, make sure to quote the path, e.g. `.\windows_exporter.exe --config.file="C:\Program Files\windows_exporter\config.yml"` YAML configuration files can be specified with the `--config.file` flag. e.g. `.\windows_exporter.exe --config.file=config.yml`. If you are using the absolute path, make sure to quote the path, e.g. `.\windows_exporter.exe --config.file="C:\Program Files\windows_exporter\config.yml"`
It is also possible to load the configuration from a URL. e.g. `.\windows_exporter.exe --config.file="https://example.com/config.yml"`
If you need to skip TLS verification, you can use the `--config.file.insecure-skip-verify` flag. e.g. `.\windows_exporter.exe --config.file="https://example.com/config.yml" --config.file.insecure-skip-verify`
```yaml ```yaml
collectors: collectors:
enabled: cpu,net,service enabled: cpu,net,service
@@ -257,7 +230,7 @@ An example configuration file can be found [here](docs/example_config.yml).
Configuration file values can be mixed with CLI flags. E.G. Configuration file values can be mixed with CLI flags. E.G.
`.\windows_exporter.exe --collectors.enabled=cpu,logon` `.\windows_exporter.exe --collectors.enabled=cpu`
```yaml ```yaml
log: log:

View File

@@ -102,6 +102,7 @@ type windowsExporterService struct{}
// Execute is the entry point for the Windows service manager. // Execute is the entry point for the Windows service manager.
func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) { func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) {
changes <- svc.Status{State: svc.StartPending} changes <- svc.Status{State: svc.StartPending}
// Send a signal to the main function that the service is running.
changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown} changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
for { for {
@@ -179,6 +180,7 @@ func logToFile(msg string) {
// https://github.com/DataDog/datadog-agent/blob/46740e82ef40a04c4be545ed8c16a4b0d1f046cf/pkg/util/winutil/servicemain/servicemain.go#L128 // https://github.com/DataDog/datadog-agent/blob/46740e82ef40a04c4be545ed8c16a4b0d1f046cf/pkg/util/winutil/servicemain/servicemain.go#L128
func isWindowsService() (bool, error) { func isWindowsService() (bool, error) {
var currentProcess windows.PROCESS_BASIC_INFORMATION var currentProcess windows.PROCESS_BASIC_INFORMATION
infoSize := uint32(unsafe.Sizeof(currentProcess)) infoSize := uint32(unsafe.Sizeof(currentProcess))
err := windows.NtQueryInformationProcess(windows.CurrentProcess(), windows.ProcessBasicInformation, unsafe.Pointer(&currentProcess), infoSize, &infoSize) err := windows.NtQueryInformationProcess(windows.CurrentProcess(), windows.ProcessBasicInformation, unsafe.Pointer(&currentProcess), infoSize, &infoSize)

View File

@@ -89,6 +89,10 @@ func run(ctx context.Context, args []string) int {
"collectors.enabled", "collectors.enabled",
"Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default."). "Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default.").
Default(collector.DefaultCollectors).String() Default(collector.DefaultCollectors).String()
disabledCollectors = app.Flag(
"collectors.disabled",
"Comma-separated list of collectors to exclude. Can be used to disable collector from the defaults.").
Default("").String()
timeoutMargin = app.Flag( timeoutMargin = app.Flag(
"scrape.timeout-margin", "scrape.timeout-margin",
"Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.", "Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.",
@@ -166,6 +170,10 @@ func run(ctx context.Context, args []string) int {
return 1 return 1
} }
if *disabledCollectors != "" {
collectors.Disable(slices.Compact(strings.Split(*disabledCollectors, ",")))
}
// Initialize collectors before loading // Initialize collectors before loading
if err = collectors.Build(ctx, logger); err != nil { if err = collectors.Build(ctx, logger); err != nil {
for _, err := range utils.SplitError(err) { for _, err := range utils.SplitError(err) {

View File

@@ -171,8 +171,10 @@ func waitUntilListening(tb testing.TB, network, address string) error {
err error err error
) )
for range 10 { dialer := &net.Dialer{Timeout: 100 * time.Millisecond}
conn, err = net.DialTimeout(network, address, 100*time.Millisecond)
for range 20 {
conn, err = dialer.DialContext(tb.Context(), network, address)
if err == nil { if err == nil {
_ = conn.Close() _ = conn.Close()
@@ -184,6 +186,13 @@ func waitUntilListening(tb testing.TB, network, address string) error {
continue continue
} }
break
}
var winErr windows.Errno
if errors.As(err, &winErr) {
return fmt.Errorf("listener not listening: %w (#%d)", winErr, uint32(winErr))
} }
return fmt.Errorf("listener not listening: %w", err) return fmt.Errorf("listener not listening: %w", err)

View File

@@ -1,8 +1,12 @@
# example configuration file for windows_exporter # example configuration file for windows_exporter
collectors: collectors:
enabled: cpu,cpu_info,exchange,iis,logical_disk,logon,memory,net,os,performancecounter,process,remote_fx,service,system,tcp,time,terminal_services,textfile enabled: cpu,cpu_info,exchange,iis,logical_disk,memory,net,os,performancecounter,process,remote_fx,service,system,tcp,time,terminal_services,textfile
collector: collector:
textfile:
directories:
- 'C:\MyDir1'
- 'C:\MyDir2'
service: service:
include: "windows_exporter" include: "windows_exporter"
performancecounter: performancecounter:

View File

@@ -9,7 +9,6 @@ This directory contains documentation of the collectors in the windows_exporter,
- [`container`](collector.container.md) - [`container`](collector.container.md)
- [`cpu`](collector.cpu.md) - [`cpu`](collector.cpu.md)
- [`cpu_info`](collector.cpu_info.md) - [`cpu_info`](collector.cpu_info.md)
- [`cs`](collector.cs.md)
- [`dfsr`](collector.dfsr.md) - [`dfsr`](collector.dfsr.md)
- [`dhcp`](collector.dhcp.md) - [`dhcp`](collector.dhcp.md)
- [`diskdrive`](collector.diskdrive.md) - [`diskdrive`](collector.diskdrive.md)
@@ -20,7 +19,6 @@ This directory contains documentation of the collectors in the windows_exporter,
- [`iis`](collector.iis.md) - [`iis`](collector.iis.md)
- [`license`](collector.license.md) - [`license`](collector.license.md)
- [`logical_disk`](collector.logical_disk.md) - [`logical_disk`](collector.logical_disk.md)
- [`logon`](collector.logon.md)
- [`memory`](collector.memory.md) - [`memory`](collector.memory.md)
- [`mscluster`](collector.mscluster.md) - [`mscluster`](collector.mscluster.md)
- [`msmq`](collector.msmq.md) - [`msmq`](collector.msmq.md)

View File

@@ -5,7 +5,7 @@ The container collector exposes metrics about containers running on a Hyper-V sy
||| |||
-|- -|-
Metric name prefix | `container` Metric name prefix | `container`
Data source | [hcsshim](https://github.com/Microsoft/hcsshim) Data source | [HCS](https://learn.microsoft.com/en-us/virtualization/api/hcs/overview)
Enabled by default? | No Enabled by default? | No
## Flags ## Flags
@@ -14,26 +14,26 @@ None
## Metrics ## Metrics
Name | Description | Type | Labels | Name | Description | Type | Labels |
-----|-------------|------|------- |------------------------------------------------------------|----------------------------------------|---------|----------------------------------------------------------|
`windows_container_available` | Available | counter | `container_id` | `windows_container_available` | Available | counter | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_count` | Number of containers | gauge | `container_id` | `windows_container_count` | Number of containers | gauge | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_cpu_usage_seconds_kernelmode` | Run time in Kernel mode in Seconds | counter | `container_id` | `windows_container_cpu_usage_seconds_kernelmode` | Run time in Kernel mode in Seconds | counter | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_cpu_usage_seconds_usermode` | Run Time in User mode in Seconds | counter | `container_id` | `windows_container_cpu_usage_seconds_usermode` | Run Time in User mode in Seconds | counter | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_cpu_usage_seconds_total` | Total Run time in Seconds | counter | `container_id` | `windows_container_cpu_usage_seconds_total` | Total Run time in Seconds | counter | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_memory_usage_commit_bytes` | Memory Usage Commit Bytes | gauge | `container_id` | `windows_container_memory_usage_commit_bytes` | Memory Usage Commit Bytes | gauge | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_memory_usage_commit_peak_bytes` | Memory Usage Commit Peak Bytes | gauge | `container_id` | `windows_container_memory_usage_commit_peak_bytes` | Memory Usage Commit Peak Bytes | gauge | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_memory_usage_private_working_set_bytes` | Memory Usage Private Working Set Bytes | gauge | `container_id` | `windows_container_memory_usage_private_working_set_bytes` | Memory Usage Private Working Set Bytes | gauge | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_network_receive_bytes_total` | Bytes Received on Interface | counter | `container_id`, `interface` | `windows_container_network_receive_bytes_total` | Bytes Received on Interface | counter | `container_id`,`namespace`,`pod`,`container`,`interface` |
`windows_container_network_receive_packets_total` | Packets Received on Interface | counter | `container_id`, `interface` | `windows_container_network_receive_packets_total` | Packets Received on Interface | counter | `container_id`,`namespace`,`pod`,`container`,`interface` |
`windows_container_network_receive_packets_dropped_total` | Dropped Incoming Packets on Interface | counter | `container_id`, `interface` | `windows_container_network_receive_packets_dropped_total` | Dropped Incoming Packets on Interface | counter | `container_id`,`namespace`,`pod`,`container`,`interface` |
`windows_container_network_transmit_bytes_total` | Bytes Sent on Interface | counter | `container_id`, `interface` | `windows_container_network_transmit_bytes_total` | Bytes Sent on Interface | counter | `container_id`,`namespace`,`pod`,`container`,`interface` |
`windows_container_network_transmit_packets_total` | Packets Sent on Interface | counter | `container_id`, `interface` | `windows_container_network_transmit_packets_total` | Packets Sent on Interface | counter | `container_id`,`namespace`,`pod`,`container`,`interface` |
`windows_container_network_transmit_packets_dropped_total` | Dropped Outgoing Packets on Interface | counter | `container_id`, `interface` | `windows_container_network_transmit_packets_dropped_total` | Dropped Outgoing Packets on Interface | counter | `container_id`,`namespace`,`pod`,`container`,`interface` |
`windows_container_storage_read_count_normalized_total` | Read Count Normalized | counter | `container_id` | `windows_container_storage_read_count_normalized_total` | Read Count Normalized | counter | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_storage_read_size_bytes_total` | Read Size Bytes | counter | `container_id` | `windows_container_storage_read_size_bytes_total` | Read Size Bytes | counter | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_storage_write_count_normalized_total` | Write Count Normalized | counter | `container_id` | `windows_container_storage_write_count_normalized_total` | Write Count Normalized | counter | `container_id`,`namespace`,`pod`,`container`, |
`windows_container_storage_write_size_bytes_total` | Write Size Bytes | counter | `container_id` | `windows_container_storage_write_size_bytes_total` | Write Size Bytes | counter | `container_id`,`namespace`,`pod`,`container`, |
### Example metric ### Example metric
_windows_container_network_receive_bytes_total{container_id="docker://1bd30e8b8ac28cbd76a9b697b4d7bb9d760267b0733d1bc55c60024e98d1e43e",interface="822179E7-002C-4280-ABBA-28BCFE401826"} 9.3305343e+07_ _windows_container_network_receive_bytes_total{container_id="docker://1bd30e8b8ac28cbd76a9b697b4d7bb9d760267b0733d1bc55c60024e98d1e43e",interface="822179E7-002C-4280-ABBA-28BCFE401826"} 9.3305343e+07_

View File

@@ -1,34 +0,0 @@
# cs collector
> [!CAUTION]
> This collector is deprecated and will be removed in a future release.
> See https://github.com/prometheus-community/windows_exporter/pull/1596 for more information.
The cs collector exposes metrics detailing the hardware of the computer system
|||
-|-
Metric name prefix | `cs`
Classes | [`Win32_ComputerSystem`](https://msdn.microsoft.com/en-us/library/aa394102)
Enabled by default? | Yes
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_cs_logical_processors` | Number of installed logical processors | gauge | None
`windows_cs_physical_memory_bytes` | Total installed physical memory | gauge | None
`windows_cs_hostname` | Labelled system hostname information | gauge | `hostname`, `domain`, `fqdn`
### 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

@@ -15,7 +15,7 @@ Enabled by default (error stats)? | Yes |
Name | Description Name | Description
-----|------------ -----|------------
`collector.dns.enabled` | Comma-separated list of collectors to use. Available collectors: `metrics`, `error_stats`. Defaults to all collectors if not specified. `collector.dns.enabled` | Comma-separated list of collectors to use. Available collectors: `metrics`, `wmi_stats`. Defaults to all collectors if not specified.
## Metrics ## Metrics

149
docs/collector.gpu.md Normal file
View File

@@ -0,0 +1,149 @@
# gpu collector
The gpu collector exposes metrics about GPU usage and memory consumption, both at the adapter (physical GPU) and
per-process level.
| | |
|---------------------|--------------------------------------|
| Metric name prefix | `gpu` |
| Data source | Perflib |
| Counters | GPU Engine, GPU Adapter, GPU Process |
| Enabled by default? | No |
## Flags
None
## Metrics
These metrics are available on supported versions of Windows with compatible GPUs and drivers:
### Adapter-level Metrics
| Name | Description | Type | Labels |
|--------------------------------------------------|------------------------------------------------------------------------------------|-------|-----------------------------------------------------------------|
| `windows_gpu_info` | A metric with a constant '1' value labeled with gpu device information. | gauge | `bus_number`,`device_id`,`function_number`,`luid`,`name`,`phys` |
| `windows_gpu_dedicated_system_memory_size_bytes` | The size, in bytes, of memory that is dedicated from system memory. | gauge | `device_id`,`luid` |
| `windows_gpu_dedicated_video_memory_size_bytes` | The size, in bytes, of memory that is dedicated from video memory. | gauge | `device_id`,`luid` |
| `windows_gpu_shared_system_memory_size_bytes` | The size, in bytes, of memory from system memory that can be shared by many users. | gauge | `device_id`,`luid` |
| `windows_gpu_adapter_memory_committed_bytes` | Total committed GPU memory in bytes per physical GPU | gauge | `device_id`,`luid`,`phys` |
| `windows_gpu_adapter_memory_dedicated_bytes` | Dedicated GPU memory usage in bytes per physical GPU | gauge | `device_id`,`luid`,`phys` |
| `windows_gpu_adapter_memory_shared_bytes` | Shared GPU memory usage in bytes per physical GPU | gauge | `device_id`,`luid`,`phys` |
| `windows_gpu_local_adapter_memory_bytes` | Local adapter memory usage in bytes per physical GPU | gauge | `device_id`,`luid`,`phys`,`part` |
| `windows_gpu_non_local_adapter_memory_bytes` | Non-local adapter memory usage in bytes per physical GPU | gauge | `device_id`,`luid`,`phys`,`part` |
### Per-process Metrics
| Name | Description | Type | Labels |
|----------------------------------------------|-------------------------------------------------|---------|-----------------------------------------------------------|
| `windows_gpu_engine_time_seconds` | Total running time of the GPU engine in seconds | counter | `device_id`,`luid`,`phys`, `eng`, `engtype`, `process_id` |
| `windows_gpu_process_memory_committed_bytes` | Total committed GPU memory in bytes per process | gauge | `device_id`,`luid`,`phys`,`process_id` |
| `windows_gpu_process_memory_dedicated_bytes` | Dedicated GPU memory usage in bytes per process | gauge | `device_id`,`luid`,`phys`,`process_id` |
| `windows_gpu_process_memory_local_bytes` | Local GPU memory usage in bytes per process | gauge | `device_id`,`luid`,`phys`,`process_id` |
| `windows_gpu_process_memory_non_local_bytes` | Non-local GPU memory usage in bytes per process | gauge | `device_id`,`luid`,`phys`,`process_id` |
| `windows_gpu_process_memory_shared_bytes` | Shared GPU memory usage in bytes per process | gauge | `device_id`,`luid`,`phys`,`process_id` |
## Metric Labels
* `luid`,`phys`: Physical GPU index (e.g., "0")
* `eng`: GPU engine index (e.g., "0", "1", ...)
* `engtype`: GPU engine type (e.g., "3D", "Copy", "VideoDecode", etc.)
* `process_id`: Process ID
## Example Metric
These are basic queries to help you get started with GPU monitoring on Windows using Prometheus.
**Show GPU information for a specific physical GPU (0):**
```promql
windows_gpu_info{bus_number="8",device_id="PCI\\VEN_10DE&DEV_1B81&SUBSYS_61733842&REV_A1",function_number="0",luid="0x00000000_0x00010F8A",name="NVIDIA GeForce GTX 1070",phys="0"} 1
```
**Show total dedicated GPU memory (in bytes) usage on GPU 0:**
```promql
windows_gpu_adapter_memory_dedicated_bytes{phys="0"}
```
**Aggregate GPU utilization across all processes for a physical GPU (3D engine):**
```promql
sum by (phys) (
rate(windows_gpu_engine_time_seconds{phys="0", engtype="3D"}[1m])
) * 100
```
**Show GPU utilization for a specific process (3D engine):**
```promql
sum by (phys, process_id) (
rate(windows_gpu_engine_time_seconds{process_id="1234", engtype="3D"}[1m])
) * 100
```
**Show dedicated GPU memory per process:**
```promql
windows_gpu_adapter_memory_dedicated_bytes
```
## Useful Queries
**Show top 5 processes by GPU utilization (all engines):**
```promql
topk(5, sum by (process_id) (
rate(windows_gpu_engine_time_seconds[1m])
) * 100)
```
**Show GPU memory usage per physical GPU:**
```promql
sum by (phys) (
windows_gpu_adapter_memory_dedicated_bytes
)
```
Show GPU engine time with process owner and command line:
```promql
windows_gpu_engine_time_seconds * on(process_id) group_left(owner, cmdline) windows_process_info
```
## Alerting Examples
**prometheus.rules**
```yaml
# Alert on processes using more than 80% of a GPU's capacity over 10 minutes
- alert: HighGpuUtilization
expr: |
sum by (process_id) (
rate(windows_gpu_engine_time_seconds[1m])
) * 100 > 80
for: 10m
labels:
severity: warning
annotations:
summary: "High GPU Utilization (process {{ $labels.process_id }})"
description: "Process is using more than 80% of GPU resources\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
```
## Notes
* Per-process metrics allow you to identify which processes are consuming GPU resources.
* Adapter-level metrics provide an overview of total GPU memory usage.
* For overall GPU utilization, aggregate per-process metrics in Prometheus using queries such as `sum()`.
* The collector relies on Windows performance counters; ensure your system and drivers support these counters.
## Enabling the Collector
To enable the GPU collector, add `gpu` to the list of enabled collectors in your windows_exporter configuration.
Example (command line):
```shell
windows_exporter.exe --collectors.enabled=gpu
```

View File

@@ -130,6 +130,10 @@ If given, an application needs to *not* match the exclude regexp in order for th
| `windows_iis_server_output_cache_hits_total` | Total number of successful lookups in output cache (since service startup) | counter | None | | `windows_iis_server_output_cache_hits_total` | Total number of successful lookups in output cache (since service startup) | counter | None |
| `windows_iis_server_output_cache_items_flushed_total` | Total number of items flushed from output cache (since service startup) | counter | None | | `windows_iis_server_output_cache_items_flushed_total` | Total number of items flushed from output cache (since service startup) | counter | None |
| `windows_iis_server_output_cache_flushes_total` | Total number of flushes of output cache (since service startup) | counter | None | | `windows_iis_server_output_cache_flushes_total` | Total number of flushes of output cache (since service startup) | counter | None |
| `windows_iis_http_requests_current_queue_size` | Http Request Current queue size | counter | None |
| `windows_iis_http_request_total_rejected_request` | Http Request total rejected request | counter | None |
| `windows_iis_http_requests_max_queue_item_age` | Http Request Max queue Item age | counter | None |
| `windows_iis_http_requests_arrival_rate` | Http requests Arrival Rate | counter | None |
### Example metric ### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_ _This collector does not yet have explained examples, we would appreciate your help adding them!_

View File

@@ -2,12 +2,12 @@
The logical_disk collector exposes metrics about logical disks (in contrast to physical disks) The logical_disk collector exposes metrics about logical disks (in contrast to physical disks)
||| | | |
-|- |---------------------|------------------|
Metric name prefix | `logical_disk` | Metric name prefix | `logical_disk` |
Data source | Perflib | Data source | Performance Data |
Counters | `LogicalDisk` ([`Win32_PerfRawData_PerfDisk_LogicalDisk`](https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71))) | Counters | `LogicalDisk` |
Enabled by default? | Yes | Enabled by default? | Yes |
## Flags ## Flags
@@ -19,25 +19,30 @@ If given, a disk needs to match the include regexp in order for the correspondin
If given, a disk needs to *not* match the exclude regexp in order for the corresponding disk metrics to be reported If given, a disk needs to *not* match the exclude regexp in order for the corresponding disk metrics to be reported
### `--collector.logical_disk.enabled`
Comma-separated list of collectors to use. Available collectors: metrics, bitlocker_status. Defaults to metrics, if not specified.
## Metrics ## Metrics
Name | Description | Type | Labels | Name | Description | Type | Labels |
-----|-------------|------|------- |--------------------------------------------------|----------------------------------------------------------------------------------------------------|---------|-------------------------------------------------------------------|
`windows_logical_disk_info` | A metric with a constant '1' value labeled with logical disk information | gauge | `disk`,`filesystem`,`serial_number`,`volume`,`volume_name`,`type` | `windows_logical_disk_info` | A metric with a constant '1' value labeled with logical disk information | gauge | `disk`,`filesystem`,`serial_number`,`volume`,`volume_name`,`type` |
`windows_logical_disk_requests_queued` | Number of requests outstanding on the disk at the time the performance data is collected | gauge | `volume` | `windows_logical_disk_requests_queued` | Number of requests outstanding on the disk at the time the performance data is collected | gauge | `volume` |
`windows_logical_disk_avg_read_requests_queued` | Average number of read requests that were queued for the selected disk during the sample interval | gauge | `volume` | `windows_logical_disk_avg_read_requests_queued` | Average number of read requests that were queued for the selected disk during the sample interval | gauge | `volume` |
`windows_logical_disk_avg_write_requests_queued` | Average number of write requests that were queued for the selected disk during the sample interval | gauge | `volume` | `windows_logical_disk_avg_write_requests_queued` | Average number of write requests that were queued for the selected disk during the sample interval | gauge | `volume` |
`windows_logical_disk_read_bytes_total` | Rate at which bytes are transferred from the disk during read operations | counter | `volume` | `windows_logical_disk_read_bytes_total` | Rate at which bytes are transferred from the disk during read operations | counter | `volume` |
`windows_logical_disk_reads_total` | Rate of read operations on the disk | counter | `volume` | `windows_logical_disk_reads_total` | Rate of read operations on the disk | counter | `volume` |
`windows_logical_disk_write_bytes_total` | Rate at which bytes are transferred to the disk during write operations | counter | `volume` | `windows_logical_disk_write_bytes_total` | Rate at which bytes are transferred to the disk during write operations | counter | `volume` |
`windows_logical_disk_writes_total` | Rate of write operations on the disk | counter | `volume` | `windows_logical_disk_writes_total` | Rate of write operations on the disk | counter | `volume` |
`windows_logical_disk_read_seconds_total` | Seconds the disk was busy servicing read requests | counter | `volume` | `windows_logical_disk_read_seconds_total` | Seconds the disk was busy servicing read requests | counter | `volume` |
`windows_logical_disk_write_seconds_total` | Seconds the disk was busy servicing write requests | counter | `volume` | `windows_logical_disk_write_seconds_total` | Seconds the disk was busy servicing write requests | counter | `volume` |
`windows_logical_disk_free_bytes` | Unused space of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` | `windows_logical_disk_free_bytes` | Unused space of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` |
`windows_logical_disk_size_bytes` | Total size of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` | `windows_logical_disk_size_bytes` | Total size of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` |
`windows_logical_disk_idle_seconds_total` | Seconds the disk was idle (not servicing read/write requests) | counter | `volume` | `windows_logical_disk_idle_seconds_total` | Seconds the disk was idle (not servicing read/write requests) | counter | `volume` |
`windows_logical_disk_split_ios_total` | Number of I/Os to the disk split into multiple I/Os | counter | `volume` | `windows_logical_disk_split_ios_total` | Number of I/Os to the disk split into multiple I/Os | counter | `volume` |
`windows_logical_disk_readonly` | Whether the logical disk is read-only | gauge | `volume` | `windows_logical_disk_readonly` | Whether the logical disk is read-only | gauge | `volume` |
| `windows_logical_disk_bitlocker_status` | BitLocker status for the logical disk | gauge | `volume`,`status` |
### Warning about size metrics ### Warning about size metrics
The `free_bytes` and `size_bytes` metrics are not updated in real time and might have a delay of 10-15min. The `free_bytes` and `size_bytes` metrics are not updated in real time and might have a delay of 10-15min.

View File

@@ -109,7 +109,7 @@ Matching is case-sensitive.
| `mscluster_network_Role` | Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both | gauge | `name` | | `mscluster_network_Role` | Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both | gauge | `name` |
| `mscluster_network_State` | Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up | gauge | `name` | | `mscluster_network_State` | Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up | gauge | `name` |
### Network ### Node
| Name | Description | Type | Labels | | Name | Description | Type | Labels |
|----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|--------| |----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|--------|

View File

@@ -5,7 +5,7 @@ The msmq collector exposes metrics about the queues on a MSMQ server
| | | | | |
|---------------------|----------------------| |---------------------|----------------------|
| Metric name prefix | `msmq` | | Metric name prefix | `msmq` |
| Spource | Performance Counters | | Source | Performance Counters |
| Enabled by default? | No | | Enabled by default? | No |
## Flags ## Flags

View File

@@ -37,6 +37,16 @@ Enables IIS process name queries. IIS process names are combined with their app
Disabled by default, and can be enabled with `--collector.process.iis`. NOTE: Just plain parameter without `true`. Disabled by default, and can be enabled with `--collector.process.iis`. NOTE: Just plain parameter without `true`.
### `--collector.process.counter-version`
Version of the process collector to use. 1 for Process V1, 2 for Process V2.
Defaults to 0 which will use the latest version available.
### `--collector.process.cmdline`
Enables the `cmdline` label for the process metrics.
This label contains the command line used to start the process.
Enabled by default, and can be turned off with `--no-collector.process.cmdline`.
### Example ### Example
To match all firefox processes: `--collector.process.include="firefox.*"`. To match all firefox processes: `--collector.process.include="firefox.*"`.

View File

@@ -10,11 +10,6 @@ Enabled by default? | No
## Flags ## Flags
### `--collector.textfile.directory`
:warning: DEPRECATED Use `--collector.textfile.directories`
<br>
### `--collector.textfile.directories` ### `--collector.textfile.directories`
One or multiple directories containing the files to be ingested. One or multiple directories containing the files to be ingested.

View File

@@ -1,6 +1,6 @@
# time collector # time collector
The time collector exposes the Windows Time Service metrics. Note that the Windows Time Service must be running, else metric collection will fail. The time collector exposes the Windows Time Service and other time related metrics.
If the Windows Time Service is stopped after collection has started, collector metric values will reset to 0. If the Windows Time Service is stopped after collection has started, collector metric values will reset to 0.
Please note the Time Service perflib counters are only available on [Windows Server 2016 or newer](https://docs.microsoft.com/en-us/windows-server/networking/windows-time-service/windows-server-2016-improvements). Please note the Time Service perflib counters are only available on [Windows Server 2016 or newer](https://docs.microsoft.com/en-us/windows-server/networking/windows-time-service/windows-server-2016-improvements).
@@ -30,11 +30,23 @@ Matching is case-sensitive.
| `windows_time_ntp_round_trip_delay_seconds` | Total roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds. This is the time elapsed on the NTP client between transmitting a request to the NTP server and receiving a valid response from the server. | gauge | None | | `windows_time_ntp_round_trip_delay_seconds` | Total roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds. This is the time elapsed on the NTP client between transmitting a request to the NTP server and receiving a valid response from the server. | gauge | None |
| `windows_time_ntp_server_outgoing_responses_total` | Total number of requests responded to by the NTP server. | counter | None | | `windows_time_ntp_server_outgoing_responses_total` | Total number of requests responded to by the NTP server. | counter | None |
| `windows_time_ntp_server_incoming_requests_total` | Total number of requests received by the NTP server. | counter | None | | `windows_time_ntp_server_incoming_requests_total` | Total number of requests received by the NTP server. | counter | None |
| `windows_time_current_timestamp_seconds` | Current time as reported by the operating system, in [Unix time](https://en.wikipedia.org/wiki/Unix_time). See [time.Unix()](https://golang.org/pkg/time/#Unix) for details | gauge | None | | `windows_time_current_timestamp_seconds` | Current time as reported by the operating system, in [Unix time](https://en.wikipedia.org/wiki/Unix_time). See [time.UnixMicro()](https://golang.org/pkg/time/#UnixMicro) for details | gauge | None |
| `windows_time_timezone` | Current timezone as reported by the operating system. | gauge | `timezone` | | `windows_time_timezone` | Current timezone as reported by the operating system. | gauge | `timezone` |
| `windows_time_clock_sync_source` | This value reflects the sync source of the system clock. | gauge | `type` |
### Example metric ### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_ ```
# HELP windows_time_clock_sync_source This value reflects the sync source of the system clock.
# TYPE windows_time_clock_sync_source gauge
windows_time_clock_sync_source{type="AllSync"} 0
windows_time_clock_sync_source{type="Local CMOS Clock"} 0
windows_time_clock_sync_source{type="NT5DS"} 0
windows_time_clock_sync_source{type="NTP"} 1
windows_time_clock_sync_source{type="NoSync"} 0
# HELP windows_time_current_timestamp_seconds OperatingSystem.LocalDateTime
# TYPE windows_time_current_timestamp_seconds gauge
windows_time_current_timestamp_seconds 1.74862554e+09
```
## Useful queries ## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_ _This collector does not yet have any useful queries added, we would appreciate your help adding them!_

View File

@@ -26,17 +26,23 @@ Define the interval of scraping Windows Update information
## Metrics ## Metrics
| Name | Description | Type | Labels | | Name | Description | Type | Labels |
|--------------------------------|-------------------------------------------------------------|-------|-------------------------------| |------------------------------------------------|------------------------------------------------------------------|-------|-------------------------------|
| `windows_update_pending_info` | Expose information for a single pending update item | gauge | `category`,`severity`,`title` | | `windows_update_pending_info` | Expose information for a single pending update item | gauge | `category`,`severity`,`title` |
| `windows_update_scrape_query_duration_seconds` | Duration of the last scrape query to the Windows Update API | gauge | | | `windows_update_pending_published_timestamp` | Expose last published timestamp for a single pending update item | gauge | `title` |
| `windows_update_scrape_timestamp_seconds` | Timestamp of the last scrape | gauge | | | `windows_update_scrape_query_duration_seconds` | Duration of the last scrape query to the Windows Update API | gauge | |
| `windows_update_scrape_timestamp_seconds` | Timestamp of the last scrape | gauge | |
### Example metrics ### Example metrics
``` ```
# HELP windows_update_pending Pending Windows Updates # HELP windows_update_pending_info Expose information for a single pending update item
# TYPE windows_update_pending gauge # TYPE windows_update_pending_info gauge
windows_update_pending{category="Drivers",severity="",title="Intel Corporation - Bluetooth - 23.60.5.10"} 1 windows_update_pending_info{category="Definition Updates",id="a32ca1d0-ddd4-486b-b708-d941db4f1051",revision="204",severity="",title="Update for Windows Security platform - KB5007651 (Version 10.0.27840.1000)"} 1
windows_update_pending_info{category="Definition Updates",id="b50a64de-a0bb-465b-9842-9963b6eee21e",revision="200",severity="",title="Security Intelligence Update for Microsoft Defender Antivirus - KB2267602 (Version 1.429.146.0) - Current Channel (Broad)"} 1
# HELP windows_update_pending_published_timestamp Expose last published timestamp for a single pending update item
# TYPE windows_update_pending_published_timestamp gauge
windows_update_pending_published_timestamp{id="a32ca1d0-ddd4-486b-b708-d941db4f1051",revision="204"} 1.747872e+09
windows_update_pending_published_timestamp{id="b50a64de-a0bb-465b-9842-9963b6eee21e",revision="200"} 1.7479584e+09
# HELP windows_update_scrape_query_duration_seconds Duration of the last scrape query to the Windows Update API # HELP windows_update_scrape_query_duration_seconds Duration of the last scrape query to the Windows Update API
# TYPE windows_update_scrape_query_duration_seconds gauge # TYPE windows_update_scrape_query_duration_seconds gauge
windows_update_scrape_query_duration_seconds 2.8161838 windows_update_scrape_query_duration_seconds 2.8161838
@@ -46,7 +52,12 @@ windows_update_scrape_timestamp_seconds 1.727539734e+09
``` ```
## Useful queries ## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
Add extended information like cmdline or owner to other process metrics.
```
windows_update_pending_published_timestamp * on(id, revision) group_left(severity, title) windows_update_pending_info
```
## Alerting examples ## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_ _This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -1,7 +1,7 @@
--- ---
# Note this is not an exhaustive list of all configuration values # Note this is not an exhaustive list of all configuration values
collectors: collectors:
enabled: cpu,cs,logical_disk,net,os,service,system enabled: cpu,logical_disk,net,os,service,system
collector: collector:
service: service:
include: "windows_exporter" include: "windows_exporter"
@@ -13,6 +13,5 @@ scrape:
timeout-margin: 0.5 timeout-margin: 0.5
telemetry: telemetry:
path: /metrics path: /metrics
max-requests: 5
web: web:
listen-address: ":9182" listen-address: ":9182"

41
go.mod
View File

@@ -1,53 +1,42 @@
module github.com/prometheus-community/windows_exporter module github.com/prometheus-community/windows_exporter
go 1.24 go 1.25
require ( require (
github.com/Microsoft/hcsshim v0.13.0
github.com/alecthomas/kingpin/v2 v2.4.0 github.com/alecthomas/kingpin/v2 v2.4.0
github.com/bmatcuk/doublestar/v4 v4.8.1 github.com/bmatcuk/doublestar/v4 v4.9.1
github.com/dimchansky/utfbom v1.1.1 github.com/dimchansky/utfbom v1.1.1
github.com/go-ole/go-ole v1.3.0 github.com/go-ole/go-ole v1.3.0
github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_golang v1.23.2
github.com/prometheus/client_model v0.6.2 github.com/prometheus/client_model v0.6.2
github.com/prometheus/common v0.64.0 github.com/prometheus/common v0.66.1
github.com/prometheus/exporter-toolkit v0.14.0 github.com/prometheus/exporter-toolkit v0.14.0
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.11.1
golang.org/x/sys v0.33.0 go.yaml.in/yaml/v3 v3.0.4
gopkg.in/yaml.v3 v3.0.1 golang.org/x/sys v0.35.0
) )
require ( require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/cgroups/v3 v3.0.5 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/jpillora/backoff v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect
github.com/mdlayher/socket v0.5.1 // indirect github.com/mdlayher/socket v0.5.1 // indirect
github.com/mdlayher/vsock v1.2.1 // indirect github.com/mdlayher/vsock v1.2.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/procfs v0.16.1 // indirect github.com/prometheus/procfs v0.17.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
go.opencensus.io v0.24.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/crypto v0.38.0 // indirect golang.org/x/crypto v0.41.0 // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.43.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.14.0 // indirect golang.org/x/sync v0.16.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.28.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect google.golang.org/protobuf v1.36.8 // indirect
google.golang.org/grpc v1.72.1 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )

177
go.sum
View File

@@ -1,30 +1,13 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -32,44 +15,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -86,125 +38,54 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4= github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg= github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA= github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 h1:IkAfh6J/yllPtpYFU0zZN1hUPYdT0ogkBT/9hMxHjvg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -213,5 +94,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -21,6 +21,14 @@
<DirectoryRef Id="APPLICATIONFOLDER"> <DirectoryRef Id="APPLICATIONFOLDER">
<Component Transitive="yes"> <Component Transitive="yes">
<File Id="windows_exporter.exe" Name="windows_exporter.exe" Source="Work\windows_exporter.exe" KeyPath="yes" Vital="yes" Checksum="yes"/> <File Id="windows_exporter.exe" Name="windows_exporter.exe" Source="Work\windows_exporter.exe" KeyPath="yes" Vital="yes" Checksum="yes"/>
<!-- The "Name" field must match the argument to eventlog.Open() -->
<util:EventSource Log="Application" Name="windows_exporter"
EventMessageFile="%SystemRoot%\System32\EventCreate.exe"
SupportsErrors="yes"
SupportsInformationals="yes"
SupportsWarnings="yes"/>
<ServiceInstall <ServiceInstall
Id="InstallExporterService" Id="InstallExporterService"
Name="windows_exporter" Name="windows_exporter"
@@ -45,13 +53,8 @@
/> />
<ServiceDependency Id="wmiApSrv" /> <ServiceDependency Id="wmiApSrv" />
</ServiceInstall> </ServiceInstall>
<ServiceControl Id="ServiceStateControl" Name="windows_exporter" Remove="uninstall" Start="install" Stop="both"/> <ServiceControl Id="StartService" Name="windows_exporter" Start="install" Wait="no" />
<!-- The "Name" field must match the argument to eventlog.Open() --> <ServiceControl Id="StopService" Name="windows_exporter" Remove="uninstall" Stop="both" Wait="yes" />
<util:EventSource Log="Application" Name="windows_exporter"
EventMessageFile="%SystemRoot%\System32\EventCreate.exe"
SupportsErrors="yes"
SupportsInformationals="yes"
SupportsWarnings="yes"/>
</Component> </Component>
<Component Id="CreateTextfileDirectory" Directory="textfile_inputs" Guid="d03ef58a-9cbf-4165-ad39-d143e9b27e14"> <Component Id="CreateTextfileDirectory" Directory="textfile_inputs" Guid="d03ef58a-9cbf-4165-ad39-d143e9b27e14">
<CreateFolder /> <CreateFolder />

View File

@@ -45,6 +45,40 @@
Property="OLDERVERSIONBEINGUPGRADED" /> Property="OLDERVERSIONBEINGUPGRADED" />
</Upgrade> </Upgrade>
<Media Id="1" Cabinet="windows_exporter.cab" EmbedCab="yes" />
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." AllowSameVersionUpgrades="yes" />
<Property Id="ENABLED_COLLECTORS" Secure="yes" />
<SetProperty Id="CollectorsFlag" After="InstallFiles" Sequence="execute" Value="--collectors.enabled [ENABLED_COLLECTORS]" Condition="ENABLED_COLLECTORS" />
<Property Id="EXTRA_FLAGS" Secure="yes" />
<SetProperty Id="ExtraFlags" After="InstallFiles" Sequence="execute" Value="[EXTRA_FLAGS]" Condition="EXTRA_FLAGS" />
<Property Id="CONFIG_FILE" Secure="yes" Value="config.yaml" />
<SetProperty Id="ConfigFile_NonDefault" After="InstallFiles" Sequence="execute" Value="[CONFIG_FILE]" Condition="CONFIG_FILE AND CONFIG_FILE&lt;&gt;&quot;config.yaml&quot;" />
<SetProperty Id="ConfigFile_Default" After="InstallFiles" Sequence="execute" Value="[APPLICATIONFOLDER]config.yaml" Condition="CONFIG_FILE=&quot;config.yaml&quot;" />
<SetProperty Id="ConfigFileFlag" After="InstallFiles" Sequence="execute" Value="--config.file=&quot;[ConfigFile_NonDefault][ConfigFile_Default]&quot;" Condition="ConfigFile_NonDefault OR ConfigFile_Default" />
<Property Id="LISTEN_PORT" Secure="yes" Value="9182" />
<SetProperty Id="ListenFlag" After="InstallFiles" Sequence="execute" Value="--web.listen-address=&quot;[LISTEN_ADDR]:[LISTEN_PORT]&quot;" Condition="LISTEN_ADDR&lt;&gt;&quot;&quot; OR LISTEN_PORT&lt;&gt;9182" />
<Property Id="METRICS_PATH" Secure="yes" />
<SetProperty Id="MetricsPathFlag" After="InstallFiles" Sequence="execute" Value="--telemetry.path=&quot;[METRICS_PATH]&quot;" Condition="METRICS_PATH" />
<Property Id="REMOTE_ADDR" Secure="yes" />
<SetProperty Id="RemoteAddressFlag" After="InstallFiles" Sequence="execute" Value="[REMOTE_ADDR]" Condition="REMOTE_ADDR" />
<Property Id="TEXTFILE_DIRS" Secure="yes" />
<SetProperty Id="TextfileDirsFlag" After="InstallFiles" Sequence="execute" Value="--collector.textfile.directories=&quot;[TEXTFILE_DIRS]&quot;" Condition="TEXTFILE_DIRS" />
<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="ARPNOMODIFY" Value="0" />-->
<!--<Property Id="ARPNOREPAIR" Value="1" />-->
<Property Id="START_MENU_FOLDER" Value="0" />
<Property Id="NOSTART" Value="0" />
<CustomAction Id="CheckExtraFlags" <CustomAction Id="CheckExtraFlags"
Error="The parameter '--config.file' must not be included in EXTRA_FLAGS. Use CONFIG_FILE instead. Please remove it and try again." /> Error="The parameter '--config.file' must not be included in EXTRA_FLAGS. Use CONFIG_FILE instead. Please remove it and try again." />
@@ -93,6 +127,23 @@
/> />
<!-- END CUSTOM ACTION FOR KILLING THE PROCESS --> <!-- END CUSTOM ACTION FOR KILLING THE PROCESS -->
<!-- START CUSTOM ACTION FOR SET SERVICE FAILUREFLAG -->
<SetProperty
Id="ConfigureServiceRecovery"
Value="&quot;[WindowsFolder]System32\sc.exe&quot; failureflag &quot;windows_exporter&quot; 1"
Before="ConfigureServiceRecovery"
Sequence="execute"
/>
<CustomAction
Id="ConfigureServiceRecovery"
BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)"
DllEntry="WixQuietExec"
Execute="deferred"
Return="ignore"
Impersonate="no"
/>
<!-- END CUSTOM ACTION FFOR SET SERVICE FAILUREFLAG -->
<InstallExecuteSequence> <InstallExecuteSequence>
<!-- Set REINSTALL=all and REINSTALLMODE=amus if the user reruns the <!-- Set REINSTALL=all and REINSTALLMODE=amus if the user reruns the
MSI, which will force reinstalling all files and services. --> MSI, which will force reinstalling all files and services. -->
@@ -100,47 +151,14 @@
Condition="Installed AND (NOT REMOVE) AND (NOT UPGRADINGPRODUCTCODE)"/> Condition="Installed AND (NOT REMOVE) AND (NOT UPGRADINGPRODUCTCODE)"/>
<Custom Action="set_reinstall_all_property" Before="set_reinstallmode_property" Condition="MAINTENANCE"/> <Custom Action="set_reinstall_all_property" Before="set_reinstallmode_property" Condition="MAINTENANCE"/>
<Custom Action="set_reinstallmode_property" Before="LaunchConditions" Condition="MAINTENANCE"/> <Custom Action="set_reinstallmode_property" Before="LaunchConditions" Condition="MAINTENANCE"/>
<Custom Action="CreateConfigFile" Before="InstallServices" Condition="ConfigFile_NonDefault OR ConfigFile_Default" /> <Custom Action="CreateConfigFile" Before="InstallServices" Condition="ConfigFile_Default" />
<Custom Action="ConfigureServiceRecovery" After="InstallServices" Condition="NOT REMOVE" />
<Custom Action="KillProcess" Before="RemoveFiles" /> <Custom Action="KillProcess" Before="RemoveFiles" />
<Custom Action="CheckExtraFlags" Before="InstallInitialize" <Custom Action="CheckExtraFlags" Before="InstallInitialize"
Condition="EXTRA_FLAGS AND (EXTRA_FLAGS&gt;&lt;&quot;--config.file&quot;)" /> Condition="EXTRA_FLAGS AND (EXTRA_FLAGS&gt;&lt;&quot;--config.file&quot;)" />
</InstallExecuteSequence> </InstallExecuteSequence>
<Media Id="1" Cabinet="windows_exporter.cab" EmbedCab="yes" />
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." AllowSameVersionUpgrades="yes" />
<Property Id="ENABLED_COLLECTORS" Secure="yes" />
<SetProperty Id="CollectorsFlag" After="InstallFiles" Sequence="execute" Value="--collectors.enabled [ENABLED_COLLECTORS]" Condition="ENABLED_COLLECTORS" />
<Property Id="EXTRA_FLAGS" Secure="yes" />
<SetProperty Id="ExtraFlags" After="InstallFiles" Sequence="execute" Value="[EXTRA_FLAGS]" Condition="EXTRA_FLAGS" />
<Property Id="CONFIG_FILE" Secure="yes" Value="config.yaml" />
<SetProperty Id="ConfigFile_NonDefault" After="InstallFiles" Sequence="execute" Value="[CONFIG_FILE]" Condition="CONFIG_FILE AND CONFIG_FILE&lt;&gt;&quot;config.yaml&quot;" />
<SetProperty Id="ConfigFile_Default" After="InstallFiles" Sequence="execute" Value="[APPLICATIONFOLDER]config.yaml" Condition="CONFIG_FILE=&quot;config.yaml&quot;" />
<SetProperty Id="ConfigFileFlag" After="InstallFiles" Sequence="execute" Value="--config.file=&quot;[ConfigFile_NonDefault][ConfigFile_Default]&quot;" Condition="ConfigFile_NonDefault OR ConfigFile_Default" />
<Property Id="LISTEN_PORT" Secure="yes" Value="9182" />
<SetProperty Id="ListenFlag" After="InstallFiles" Sequence="execute" Value="--web.listen-address [LISTEN_ADDR]:[LISTEN_PORT]" Condition="LISTEN_ADDR&lt;&gt;&quot;&quot; OR LISTEN_PORT&lt;&gt;9182" />
<Property Id="METRICS_PATH" Secure="yes" />
<SetProperty Id="MetricsPathFlag" After="InstallFiles" Sequence="execute" Value="--telemetry.path [METRICS_PATH]" Condition="METRICS_PATH" />
<Property Id="REMOTE_ADDR" Secure="yes" />
<SetProperty Id="RemoteAddressFlag" After="InstallFiles" Sequence="execute" Value="[REMOTE_ADDR]" Condition="REMOTE_ADDR" />
<Property Id="TEXTFILE_DIRS" Secure="yes" />
<SetProperty Id="TextfileDirsFlag" After="InstallFiles" Sequence="execute" Value="--collector.textfile.directories [TEXTFILE_DIRS]" Condition="TEXTFILE_DIRS" />
<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="ARPNOMODIFY" Value="0" />-->
<!--<Property Id="ARPNOREPAIR" Value="1" />-->
<Property Id="START_MENU_FOLDER" Value="0" />
<Property Id="NOSTART" Value="0" />
<Feature <Feature
Id="DefaultFeature" Id="DefaultFeature"
Level="1" Level="1"
@@ -178,7 +196,7 @@
<Control Id="Title" Type="Text" X="15" Y="6" Width="210" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}windows_exporter configuration" /> <Control Id="Title" Type="Text" X="15" Y="6" Width="210" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}windows_exporter configuration" />
<!-- Edit box for property input --> <!-- Edit box for property input -->
<!-- cpu,cs,logical_disk,physical_disk,net,os,service,system --> <!-- cpu,logical_disk,physical_disk,net,os,service,system -->
<Control Id="PropertyEdit_ENABLED_COLLECTORS_Title1" Type="Text" X="25" Y="55" Width="300" Height="15" Transparent="yes" NoPrefix="yes" Text="Comma-separated list of collectors to use. Use '[\[]defaults[\]]' as a placeholder for all" /> <Control Id="PropertyEdit_ENABLED_COLLECTORS_Title1" Type="Text" X="25" Y="55" Width="300" Height="15" Transparent="yes" NoPrefix="yes" Text="Comma-separated list of collectors to use. Use '[\[]defaults[\]]' as a placeholder for all" />
<Control Id="PropertyEdit_ENABLED_COLLECTORS_Title2" Type="Text" X="25" Y="65" Width="300" Height="15" Transparent="yes" NoPrefix="yes" Text="the collectors enabled by default. If value is empty, the exporter default will be used." /> <Control Id="PropertyEdit_ENABLED_COLLECTORS_Title2" Type="Text" X="25" Y="65" Width="300" Height="15" Transparent="yes" NoPrefix="yes" Text="the collectors enabled by default. If value is empty, the exporter default will be used." />
<Control Id="PropertyEdit_ENABLED_COLLECTORS" Type="Edit" X="24" Y="77" Width="300" Height="18" Property="ENABLED_COLLECTORS" Text="[ENABLED_COLLECTORS]" Indirect="no" /> <Control Id="PropertyEdit_ENABLED_COLLECTORS" Type="Edit" X="24" Y="77" Width="300" Height="18" Property="ENABLED_COLLECTORS" Text="[ENABLED_COLLECTORS]" Indirect="no" />

View File

@@ -522,6 +522,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", err) return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", types.ErrNoDataUnexpected)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -530,30 +532,35 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].AbANRPerSec, c.perfDataObject[0].AbANRPerSec,
"ambiguous_name_resolution", "ambiguous_name_resolution",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.addressBookOperationsTotal, c.addressBookOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].AbBrowsesPerSec, c.perfDataObject[0].AbBrowsesPerSec,
"browse", "browse",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.addressBookOperationsTotal, c.addressBookOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].AbMatchesPerSec, c.perfDataObject[0].AbMatchesPerSec,
"find", "find",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.addressBookOperationsTotal, c.addressBookOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].AbPropertyReadsPerSec, c.perfDataObject[0].AbPropertyReadsPerSec,
"property_read", "property_read",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.addressBookOperationsTotal, c.addressBookOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].AbSearchesPerSec, c.perfDataObject[0].AbSearchesPerSec,
"search", "search",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.addressBookOperationsTotal, c.addressBookOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -578,22 +585,26 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].AtqEstimatedQueueDelay/1000, c.perfDataObject[0].AtqEstimatedQueueDelay/1000,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.atqOutstandingRequests, c.atqOutstandingRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].AtqOutstandingQueuedRequests, c.perfDataObject[0].AtqOutstandingQueuedRequests,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.atqAverageRequestLatency, c.atqAverageRequestLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].AtqRequestLatency, c.perfDataObject[0].AtqRequestLatency,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.atqCurrentThreads, c.atqCurrentThreads,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].AtqThreadsLDAP, c.perfDataObject[0].AtqThreadsLDAP,
"ldap", "ldap",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.atqCurrentThreads, c.atqCurrentThreads,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -607,12 +618,14 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].BaseSearchesPerSec, c.perfDataObject[0].BaseSearchesPerSec,
"base", "base",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.searchesTotal, c.searchesTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SubtreeSearchesPerSec, c.perfDataObject[0].SubtreeSearchesPerSec,
"subtree", "subtree",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.searchesTotal, c.searchesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -626,18 +639,21 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].DatabaseAddsPerSec, c.perfDataObject[0].DatabaseAddsPerSec,
"add", "add",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.databaseOperationsTotal, c.databaseOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DatabaseDeletesPerSec, c.perfDataObject[0].DatabaseDeletesPerSec,
"delete", "delete",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.databaseOperationsTotal, c.databaseOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DatabaseModifiesPerSec, c.perfDataObject[0].DatabaseModifiesPerSec,
"modify", "modify",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.databaseOperationsTotal, c.databaseOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -651,48 +667,56 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].DigestBindsPerSec, c.perfDataObject[0].DigestBindsPerSec,
"digest", "digest",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DsClientBindsPerSec, c.perfDataObject[0].DsClientBindsPerSec,
"ds_client", "ds_client",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DsServerBindsPerSec, c.perfDataObject[0].DsServerBindsPerSec,
"ds_server", "ds_server",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].ExternalBindsPerSec, c.perfDataObject[0].ExternalBindsPerSec,
"external", "external",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].FastBindsPerSec, c.perfDataObject[0].FastBindsPerSec,
"fast", "fast",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].NegotiatedBindsPerSec, c.perfDataObject[0].NegotiatedBindsPerSec,
"negotiate", "negotiate",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].NTLMBindsPerSec, c.perfDataObject[0].NTLMBindsPerSec,
"ntlm", "ntlm",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SimpleBindsPerSec, c.perfDataObject[0].SimpleBindsPerSec,
"simple", "simple",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bindsTotal, c.bindsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -706,6 +730,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
float64(uint64(c.perfDataObject[0].DRAHighestUSNCommittedHighPart)<<32)+c.perfDataObject[0].DRAHighestUSNCommittedLowPart, float64(uint64(c.perfDataObject[0].DRAHighestUSNCommittedHighPart)<<32)+c.perfDataObject[0].DRAHighestUSNCommittedLowPart,
"committed", "committed",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.replicationHighestUsn, c.replicationHighestUsn,
prometheus.CounterValue, prometheus.CounterValue,
@@ -744,6 +769,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].DRAInboundBytesNotCompressedWithinSitePerSec, c.perfDataObject[0].DRAInboundBytesNotCompressedWithinSitePerSec,
"inbound", "inbound",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.intraSiteReplicationDataBytesTotal, c.intraSiteReplicationDataBytesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -768,6 +794,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DRAInboundObjectsAppliedPerSec, c.perfDataObject[0].DRAInboundObjectsAppliedPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.replicationInboundObjectsFilteredTotal, c.replicationInboundObjectsFilteredTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -779,6 +806,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DRAInboundPropertiesAppliedPerSec, c.perfDataObject[0].DRAInboundPropertiesAppliedPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.replicationInboundPropertiesFilteredTotal, c.replicationInboundPropertiesFilteredTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -790,6 +818,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].DRAPendingReplicationOperations, c.perfDataObject[0].DRAPendingReplicationOperations,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.replicationPendingSynchronizations, c.replicationPendingSynchronizations,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -801,11 +830,13 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DRASyncRequestsMade, c.perfDataObject[0].DRASyncRequestsMade,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.replicationSyncRequestsSuccessTotal, c.replicationSyncRequestsSuccessTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DRASyncRequestsSuccessful, c.perfDataObject[0].DRASyncRequestsSuccessful,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.replicationSyncRequestsSchemaMismatchFailureTotal, c.replicationSyncRequestsSchemaMismatchFailureTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -818,6 +849,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].DsClientNameTranslationsPerSec, c.perfDataObject[0].DsClientNameTranslationsPerSec,
"client", "client",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.nameTranslationsTotal, c.nameTranslationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -830,6 +862,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].DsMonitorListSize, c.perfDataObject[0].DsMonitorListSize,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.changeMonitorUpdatesPending, c.changeMonitorUpdatesPending,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -841,6 +874,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DsNameCacheHitRate, c.perfDataObject[0].DsNameCacheHitRate,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.nameCacheLookupsTotal, c.nameCacheLookupsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -854,6 +888,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"read", "read",
"replication_agent", "replication_agent",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -861,6 +896,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"read", "read",
"knowledge_consistency_checker", "knowledge_consistency_checker",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -868,6 +904,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"read", "read",
"local_security_authority", "local_security_authority",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -875,6 +912,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"read", "read",
"name_service_provider_interface", "name_service_provider_interface",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -882,6 +920,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"read", "read",
"directory_service_api", "directory_service_api",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -889,6 +928,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"read", "read",
"security_account_manager", "security_account_manager",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -896,6 +936,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"read", "read",
"other", "other",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -903,6 +944,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"replication_agent", "replication_agent",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -910,6 +952,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"knowledge_consistency_checker", "knowledge_consistency_checker",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -917,6 +960,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"ldap", "ldap",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -924,6 +968,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"local_security_authority", "local_security_authority",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -931,6 +976,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"name_service_provider_interface", "name_service_provider_interface",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -938,6 +984,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"directory_service_api", "directory_service_api",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -945,6 +992,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"security_account_manager", "security_account_manager",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -952,6 +1000,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"search", "search",
"other", "other",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -959,6 +1008,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"write", "write",
"replication_agent", "replication_agent",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -966,6 +1016,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"write", "write",
"knowledge_consistency_checker", "knowledge_consistency_checker",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -973,6 +1024,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"write", "write",
"ldap", "ldap",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -980,6 +1032,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"write", "write",
"local_security_authority", "local_security_authority",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -987,6 +1040,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"write", "write",
"name_service_provider_interface", "name_service_provider_interface",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -994,6 +1048,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"write", "write",
"directory_service_api", "directory_service_api",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1001,6 +1056,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
"write", "write",
"security_account_manager", "security_account_manager",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.directoryOperationsTotal, c.directoryOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1020,16 +1076,19 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DsSecurityDescriptorSubOperationsPerSec, c.perfDataObject[0].DsSecurityDescriptorSubOperationsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.securityDescriptorPropagationEventsQueued, c.securityDescriptorPropagationEventsQueued,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].DsSecurityDescriptorPropagationsEvents, c.perfDataObject[0].DsSecurityDescriptorPropagationsEvents,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.securityDescriptorPropagationAccessWaitTotalSeconds, c.securityDescriptorPropagationAccessWaitTotalSeconds,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].DsSecurityDescriptorPropagatorAverageExclusionTime, c.perfDataObject[0].DsSecurityDescriptorPropagatorAverageExclusionTime,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.securityDescriptorPropagationItemsQueuedTotal, c.securityDescriptorPropagationItemsQueuedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1047,12 +1106,14 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].LdapClosedConnectionsPerSec, c.perfDataObject[0].LdapClosedConnectionsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ldapOpenedConnectionsTotal, c.ldapOpenedConnectionsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].LdapNewConnectionsPerSec, c.perfDataObject[0].LdapNewConnectionsPerSec,
"ldap", "ldap",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ldapOpenedConnectionsTotal, c.ldapOpenedConnectionsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1083,11 +1144,13 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].LdapUDPOperationsPerSec, c.perfDataObject[0].LdapUDPOperationsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ldapWritesTotal, c.ldapWritesTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].LdapWritesPerSec, c.perfDataObject[0].LdapWritesPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ldapClientSessions, c.ldapClientSessions,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -1105,6 +1168,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].PhantomsCleanedPerSec, c.perfDataObject[0].PhantomsCleanedPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.phantomObjectsVisitedTotal, c.phantomObjectsVisitedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1117,18 +1181,21 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].SamGlobalGroupMembershipEvaluationsPerSec, c.perfDataObject[0].SamGlobalGroupMembershipEvaluationsPerSec,
"global", "global",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samGroupMembershipEvaluationsTotal, c.samGroupMembershipEvaluationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SamDomainLocalGroupMembershipEvaluationsPerSec, c.perfDataObject[0].SamDomainLocalGroupMembershipEvaluationsPerSec,
"domain_local", "domain_local",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samGroupMembershipEvaluationsTotal, c.samGroupMembershipEvaluationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SamUniversalGroupMembershipEvaluationsPerSec, c.perfDataObject[0].SamUniversalGroupMembershipEvaluationsPerSec,
"universal", "universal",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samGroupMembershipGlobalCatalogEvaluationsTotal, c.samGroupMembershipGlobalCatalogEvaluationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1140,6 +1207,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SamNonTransitiveMembershipEvaluationsPerSec, c.perfDataObject[0].SamNonTransitiveMembershipEvaluationsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samGroupMembershipEvaluationsTransitiveTotal, c.samGroupMembershipEvaluationsTransitiveTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1152,6 +1220,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].SamAccountGroupEvaluationLatency, c.perfDataObject[0].SamAccountGroupEvaluationLatency,
"account_group", "account_group",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samGroupEvaluationLatency, c.samGroupEvaluationLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -1164,6 +1233,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SamSuccessfulComputerCreationsPerSecIncludesAllRequests, c.perfDataObject[0].SamSuccessfulComputerCreationsPerSecIncludesAllRequests,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samComputerCreationSuccessfulRequestsTotal, c.samComputerCreationSuccessfulRequestsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1175,6 +1245,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SamUserCreationAttemptsPerSec, c.perfDataObject[0].SamUserCreationAttemptsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samUserCreationSuccessfulRequestsTotal, c.samUserCreationSuccessfulRequestsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1186,6 +1257,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SamDisplayInformationQueriesPerSec, c.perfDataObject[0].SamDisplayInformationQueriesPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.samEnumerationsTotal, c.samEnumerationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -1209,6 +1281,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].TombstonesGarbageCollectedPerSec, c.perfDataObject[0].TombstonesGarbageCollectedPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.tombstonesObjectsVisitedTotal, c.tombstonesObjectsVisitedTotal,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -186,72 +186,84 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
data.RequestsPerSecond, data.RequestsPerSecond,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestProcessingTime, c.requestProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.RequestProcessingTime), utils.MilliSecToSec(data.RequestProcessingTime),
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.retrievalsPerSecond, c.retrievalsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.RetrievalsPerSecond, data.RetrievalsPerSecond,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.retrievalProcessingTime, c.retrievalProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.RetrievalProcessingTime), utils.MilliSecToSec(data.RetrievalProcessingTime),
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.failedRequestsPerSecond, c.failedRequestsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.FailedRequestsPerSecond, data.FailedRequestsPerSecond,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.issuedRequestsPerSecond, c.issuedRequestsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.IssuedRequestsPerSecond, data.IssuedRequestsPerSecond,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.pendingRequestsPerSecond, c.pendingRequestsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.PendingRequestsPerSecond, data.PendingRequestsPerSecond,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestCryptographicSigningTime, c.requestCryptographicSigningTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.RequestCryptographicSigningTime), utils.MilliSecToSec(data.RequestCryptographicSigningTime),
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.requestPolicyModuleProcessingTime, c.requestPolicyModuleProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.RequestPolicyModuleProcessingTime), utils.MilliSecToSec(data.RequestPolicyModuleProcessingTime),
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.challengeResponsesPerSecond, c.challengeResponsesPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.ChallengeResponsesPerSecond, data.ChallengeResponsesPerSecond,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.challengeResponseProcessingTime, c.challengeResponseProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.ChallengeResponseProcessingTime), utils.MilliSecToSec(data.ChallengeResponseProcessingTime),
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.signedCertificateTimestampListsPerSecond, c.signedCertificateTimestampListsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.SignedCertificateTimestampListsPerSecond, data.SignedCertificateTimestampListsPerSecond,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.signedCertificateTimestampListProcessingTime, c.signedCertificateTimestampListProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -387,6 +387,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect ADFS metrics: %w", err) return fmt.Errorf("failed to collect ADFS metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect ADFS metrics: %w", types.ErrNoDataUnexpected)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -290,6 +290,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect Cache metrics: %w", err) return fmt.Errorf("failed to collect Cache metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect Cache metrics: %w", types.ErrNoDataUnexpected)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -18,25 +18,49 @@
package container package container
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/fs"
"log/slog" "log/slog"
"os"
"slices"
"strings" "strings"
"unsafe"
"github.com/Microsoft/hcsshim"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/hcn"
"github.com/prometheus-community/windows_exporter/internal/headers/hcs"
"github.com/prometheus-community/windows_exporter/internal/headers/kernel32"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows"
) )
const Name = "container" const (
Name = "container"
type Config struct{} subCollectorHCS = "hcs"
subCollectorHostprocess = "hostprocess"
JobObjectMemoryUsageInformation = 28
)
type Config struct {
CollectorsEnabled []string `yaml:"enabled"`
ContainerDStateDir string `yaml:"containerd-state-dir"`
}
//nolint:gochecknoglobals //nolint:gochecknoglobals
var ConfigDefaults = Config{} var ConfigDefaults = Config{
CollectorsEnabled: []string{
subCollectorHCS,
subCollectorHostprocess,
},
ContainerDStateDir: `C:\ProgramData\containerd\state\io.containerd.runtime.v2.task\k8s.io\`,
}
// A Collector is a Prometheus Collector for containers metrics. // A Collector is a Prometheus Collector for containers metrics.
type Collector struct { type Collector struct {
@@ -44,6 +68,9 @@ type Collector struct {
logger *slog.Logger logger *slog.Logger
annotationsCacheHCS map[string]containerInfo
annotationsCacheJob map[string]containerInfo
// Presence // Presence
containerAvailable *prometheus.Desc containerAvailable *prometheus.Desc
@@ -75,12 +102,27 @@ type Collector struct {
writeSizeBytes *prometheus.Desc writeSizeBytes *prometheus.Desc
} }
type containerInfo struct {
id string
namespace string
pod string
container string
}
type ociSpec struct {
Annotations map[string]string `json:"annotations"`
}
// New constructs a new Collector. // New constructs a new Collector.
func New(config *Config) *Collector { func New(config *Config) *Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
} }
if config.CollectorsEnabled == nil {
config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
}
c := &Collector{ c := &Collector{
config: *config, config: *config,
} }
@@ -88,8 +130,31 @@ func New(config *Config) *Collector {
return c return c
} }
func NewWithFlags(_ *kingpin.Application) *Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &Collector{} c := &Collector{
config: ConfigDefaults,
}
c.config.CollectorsEnabled = make([]string, 0)
var collectorsEnabled string
app.Flag(
"collector.container.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringVar(&collectorsEnabled)
app.Flag(
"collector.container.containerd-state-dir",
"Path to the containerd state directory. Defaults to C:\\ProgramData\\containerd\\state\\io.containerd.runtime.v2.task\\k8s.io\\",
).Default(ConfigDefaults.ContainerDStateDir).StringVar(&c.config.ContainerDStateDir)
app.Action(func(*kingpin.ParseContext) error {
c.config.CollectorsEnabled = strings.Split(collectorsEnabled, ",")
return nil
})
return c
} }
func (c *Collector) GetName() string { func (c *Collector) GetName() string {
@@ -103,10 +168,19 @@ func (c *Collector) Close() error {
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name)) c.logger = logger.With(slog.String("collector", Name))
for _, collector := range c.config.CollectorsEnabled {
if !slices.Contains([]string{subCollectorHCS, subCollectorHostprocess}, collector) {
return fmt.Errorf("unknown collector: %s", collector)
}
}
c.annotationsCacheHCS = make(map[string]containerInfo)
c.annotationsCacheJob = make(map[string]containerInfo)
c.containerAvailable = prometheus.NewDesc( c.containerAvailable = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "available"), prometheus.BuildFQName(types.Namespace, Name, "available"),
"Available", "Available",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container", "hostprocess"},
nil, nil,
) )
c.containersCount = prometheus.NewDesc( c.containersCount = prometheus.NewDesc(
@@ -118,97 +192,97 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.usageCommitBytes = prometheus.NewDesc( c.usageCommitBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_bytes"), prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_bytes"),
"Memory Usage Commit Bytes", "Memory Usage Commit Bytes",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.usageCommitPeakBytes = prometheus.NewDesc( c.usageCommitPeakBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_peak_bytes"), prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_peak_bytes"),
"Memory Usage Commit Peak Bytes", "Memory Usage Commit Peak Bytes",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.usagePrivateWorkingSetBytes = prometheus.NewDesc( c.usagePrivateWorkingSetBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "memory_usage_private_working_set_bytes"), prometheus.BuildFQName(types.Namespace, Name, "memory_usage_private_working_set_bytes"),
"Memory Usage Private Working Set Bytes", "Memory Usage Private Working Set Bytes",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.runtimeTotal = prometheus.NewDesc( c.runtimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_total"),
"Total Run time in Seconds", "Total Run time in Seconds",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.runtimeUser = prometheus.NewDesc( c.runtimeUser = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_usermode"), prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_usermode"),
"Run Time in User mode in Seconds", "Run Time in User mode in Seconds",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.runtimeKernel = prometheus.NewDesc( c.runtimeKernel = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_kernelmode"), prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_kernelmode"),
"Run time in Kernel mode in Seconds", "Run time in Kernel mode in Seconds",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.bytesReceived = prometheus.NewDesc( c.bytesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_receive_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "network_receive_bytes_total"),
"Bytes Received on Interface", "Bytes Received on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "namespace", "pod", "container", "interface"},
nil, nil,
) )
c.bytesSent = prometheus.NewDesc( c.bytesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_transmit_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "network_transmit_bytes_total"),
"Bytes Sent on Interface", "Bytes Sent on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "namespace", "pod", "container", "interface"},
nil, nil,
) )
c.packetsReceived = prometheus.NewDesc( c.packetsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_total"), prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_total"),
"Packets Received on Interface", "Packets Received on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "namespace", "pod", "container", "interface"},
nil, nil,
) )
c.packetsSent = prometheus.NewDesc( c.packetsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_total"), prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_total"),
"Packets Sent on Interface", "Packets Sent on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "namespace", "pod", "container", "interface"},
nil, nil,
) )
c.droppedPacketsIncoming = prometheus.NewDesc( c.droppedPacketsIncoming = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_dropped_total"), prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_dropped_total"),
"Dropped Incoming Packets on Interface", "Dropped Incoming Packets on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "namespace", "pod", "container", "interface"},
nil, nil,
) )
c.droppedPacketsOutgoing = prometheus.NewDesc( c.droppedPacketsOutgoing = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_dropped_total"), prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_dropped_total"),
"Dropped Outgoing Packets on Interface", "Dropped Outgoing Packets on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "namespace", "pod", "container", "interface"},
nil, nil,
) )
c.readCountNormalized = prometheus.NewDesc( c.readCountNormalized = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_read_count_normalized_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_read_count_normalized_total"),
"Read Count Normalized", "Read Count Normalized",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.readSizeBytes = prometheus.NewDesc( c.readSizeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_read_size_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_read_size_bytes_total"),
"Read Size Bytes", "Read Size Bytes",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.writeCountNormalized = prometheus.NewDesc( c.writeCountNormalized = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_write_count_normalized_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_write_count_normalized_total"),
"Write Count Normalized", "Write Count Normalized",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
c.writeSizeBytes = prometheus.NewDesc( c.writeSizeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_write_size_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_write_size_bytes_total"),
"Write Size Bytes", "Write Size Bytes",
[]string{"container_id"}, []string{"container_id", "namespace", "pod", "container"},
nil, nil,
) )
@@ -218,39 +292,91 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorHCS) {
if err := c.collectHCS(ch); err != nil {
errs = append(errs, err)
}
}
if slices.Contains(c.config.CollectorsEnabled, subCollectorHostprocess) {
if err := c.collectJobContainers(ch); err != nil {
errs = append(errs, err)
}
}
return errors.Join(errs...)
}
func (c *Collector) collectHCS(ch chan<- prometheus.Metric) error {
// Types Container is passed to get the containers compute systems only // Types Container is passed to get the containers compute systems only
containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}}) containers, err := hcs.GetContainers()
if err != nil { if err != nil {
return fmt.Errorf("error in fetching containers: %w", err) return fmt.Errorf("error in fetching containers: %w", err)
} }
count := len(containers) count := len(containers)
ch <- prometheus.MustNewConstMetric(
c.containersCount,
prometheus.GaugeValue,
float64(count),
)
if count == 0 { if count == 0 {
ch <- prometheus.MustNewConstMetric(
c.containersCount,
prometheus.GaugeValue,
0,
)
return nil return nil
} }
containerPrefixes := make(map[string]string) var countersCount float64
collectErrors := make([]error, 0, len(containers))
for _, containerDetails := range containers { containerIDs := make([]string, 0, len(containers))
containerIdWithPrefix := getContainerIdWithPrefix(containerDetails) collectErrors := make([]error, 0)
if err = c.collectContainer(ch, containerDetails, containerIdWithPrefix); err != nil { for _, container := range containers {
if hcsshim.IsNotExist(err) { if container.State != "Running" {
continue
}
containerIDs = append(containerIDs, container.ID)
countersCount++
var (
namespace string
podName string
containerName string
)
if _, ok := c.annotationsCacheHCS[container.ID]; !ok {
if spec, err := c.getContainerAnnotations(container.ID); err == nil {
namespace = spec.Annotations["io.kubernetes.cri.sandbox-namespace"]
podName = spec.Annotations["io.kubernetes.cri.sandbox-name"]
containerName = spec.Annotations["io.kubernetes.cri.container-name"]
}
c.annotationsCacheHCS[container.ID] = containerInfo{
id: getContainerIdWithPrefix(container),
namespace: namespace,
pod: podName,
container: containerName,
}
}
if err = c.collectHCSContainer(ch, container, c.annotationsCacheHCS[container.ID]); err != nil {
if errors.Is(err, hcs.ErrIDNotFound) {
c.logger.Debug("err in fetching container statistics", c.logger.Debug("err in fetching container statistics",
slog.String("container_id", containerDetails.ID), slog.String("container_id", container.ID),
slog.String("container_name", c.annotationsCacheHCS[container.ID].container),
slog.String("container_pod_name", c.annotationsCacheHCS[container.ID].pod),
slog.String("container_namespace", c.annotationsCacheHCS[container.ID].namespace),
slog.Any("err", err), slog.Any("err", err),
) )
} else { } else {
c.logger.Error("err in fetching container statistics", c.logger.Error("err in fetching container statistics",
slog.String("container_id", containerDetails.ID), slog.String("container_id", container.ID),
slog.String("container_name", c.annotationsCacheHCS[container.ID].container),
slog.String("container_pod_name", c.annotationsCacheHCS[container.ID].pod),
slog.String("container_namespace", c.annotationsCacheHCS[container.ID].namespace),
slog.Any("err", err), slog.Any("err", err),
) )
@@ -259,14 +385,25 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
continue continue
} }
containerPrefixes[containerDetails.ID] = containerIdWithPrefix
} }
if err = c.collectNetworkMetrics(ch, containerPrefixes); err != nil { ch <- prometheus.MustNewConstMetric(
c.containersCount,
prometheus.GaugeValue,
countersCount,
)
if err = c.collectNetworkMetrics(ch); err != nil {
return fmt.Errorf("error in fetching container network statistics: %w", err) return fmt.Errorf("error in fetching container network statistics: %w", err)
} }
// Remove containers that are no longer running
for _, containerID := range c.annotationsCacheHCS {
if !slices.Contains(containerIDs, containerID.id) {
delete(c.annotationsCacheHCS, containerID.id)
}
}
if len(collectErrors) > 0 { if len(collectErrors) > 0 {
return fmt.Errorf("errors while fetching container statistics: %w", errors.Join(collectErrors...)) return fmt.Errorf("errors while fetching container statistics: %w", errors.Join(collectErrors...))
} }
@@ -274,117 +411,133 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
return nil return nil
} }
func (c *Collector) collectContainer(ch chan<- prometheus.Metric, containerDetails hcsshim.ContainerProperties, containerIdWithPrefix string) error { func (c *Collector) collectHCSContainer(ch chan<- prometheus.Metric, containerDetails hcs.Properties, containerInfo containerInfo) error {
container, err := hcsshim.OpenContainer(containerDetails.ID) // Skip if the container is a pause container
if err != nil { if containerInfo.pod != "" && containerInfo.container == "" {
return fmt.Errorf("error in opening container: %w", err) c.logger.Debug("skipping pause container",
slog.String("container_id", containerDetails.ID),
slog.String("container_name", containerInfo.container),
slog.String("pod_name", containerInfo.pod),
slog.String("namespace", containerInfo.namespace),
)
return nil
} }
defer func() { containerStats, err := hcs.GetContainerStatistics(containerDetails.ID)
if container == nil {
return
}
if err := container.Close(); err != nil {
c.logger.Error("error in closing container",
slog.Any("err", err),
)
}
}()
containerStats, err := container.Statistics()
if err != nil { if err != nil {
return fmt.Errorf("error in fetching container statistics: %w", err) return fmt.Errorf("error fetching container statistics: %w", err)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.containerAvailable, c.containerAvailable,
prometheus.CounterValue, prometheus.GaugeValue,
1, 1,
containerIdWithPrefix, containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, "false",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.usageCommitBytes, c.usageCommitBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(containerStats.Memory.UsageCommitBytes), float64(containerStats.Memory.MemoryUsageCommitBytes),
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.usageCommitPeakBytes, c.usageCommitPeakBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(containerStats.Memory.UsageCommitPeakBytes), float64(containerStats.Memory.MemoryUsageCommitPeakBytes),
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.usagePrivateWorkingSetBytes, c.usagePrivateWorkingSetBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(containerStats.Memory.UsagePrivateWorkingSetBytes), float64(containerStats.Memory.MemoryUsagePrivateWorkingSetBytes),
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.runtimeTotal, c.runtimeTotal,
prometheus.CounterValue, prometheus.CounterValue,
float64(containerStats.Processor.TotalRuntime100ns)*pdh.TicksToSecondScaleFactor, float64(containerStats.Processor.TotalRuntime100ns)*pdh.TicksToSecondScaleFactor,
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.runtimeUser, c.runtimeUser,
prometheus.CounterValue, prometheus.CounterValue,
float64(containerStats.Processor.RuntimeUser100ns)*pdh.TicksToSecondScaleFactor, float64(containerStats.Processor.RuntimeUser100ns)*pdh.TicksToSecondScaleFactor,
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.runtimeKernel, c.runtimeKernel,
prometheus.CounterValue, prometheus.CounterValue,
float64(containerStats.Processor.RuntimeKernel100ns)*pdh.TicksToSecondScaleFactor, float64(containerStats.Processor.RuntimeKernel100ns)*pdh.TicksToSecondScaleFactor,
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.readCountNormalized, c.readCountNormalized,
prometheus.CounterValue, prometheus.CounterValue,
float64(containerStats.Storage.ReadCountNormalized), float64(containerStats.Storage.ReadCountNormalized),
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.readSizeBytes, c.readSizeBytes,
prometheus.CounterValue, prometheus.CounterValue,
float64(containerStats.Storage.ReadSizeBytes), float64(containerStats.Storage.ReadSizeBytes),
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.writeCountNormalized, c.writeCountNormalized,
prometheus.CounterValue, prometheus.CounterValue,
float64(containerStats.Storage.WriteCountNormalized), float64(containerStats.Storage.WriteCountNormalized),
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.writeSizeBytes, c.writeSizeBytes,
prometheus.CounterValue, prometheus.CounterValue,
float64(containerStats.Storage.WriteSizeBytes), float64(containerStats.Storage.WriteSizeBytes),
containerIdWithPrefix,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
) )
return nil return nil
} }
// collectNetworkMetrics collects network metrics for containers. // collectNetworkMetrics collects network metrics for containers.
// With HNSv2, the network stats must be collected from hcsshim.HNSListEndpointRequest. func (c *Collector) collectNetworkMetrics(ch chan<- prometheus.Metric) error {
// Network statistics from the container.Statistics() are providing data only, if HNSv1 is used. endpoints, err := hcn.ListEndpoints()
// Ref: https://github.com/prometheus-community/windows_exporter/pull/1218
func (c *Collector) collectNetworkMetrics(ch chan<- prometheus.Metric, containerPrefixes map[string]string) error {
hnsEndpoints, err := hcsshim.HNSListEndpointRequest()
if err != nil { if err != nil {
return fmt.Errorf("error in fetching HNS endpoints: %w", err) return fmt.Errorf("error in fetching HCN endpoints: %w", err)
} }
if len(hnsEndpoints) == 0 { if len(endpoints) == 0 {
return errors.New("no network stats for containers to collect") return nil
} }
for _, endpoint := range hnsEndpoints { for _, endpoint := range endpoints {
endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id) if len(endpoint.SharedContainers) == 0 {
continue
}
endpointStats, err := hcn.GetHNSEndpointStats(endpoint.ID)
if err != nil { if err != nil {
c.logger.Warn("Failed to collect network stats for interface "+endpoint.Id, c.logger.Warn("Failed to collect network stats for interface "+endpoint.ID,
slog.Any("err", err), slog.Any("err", err),
) )
@@ -392,52 +545,61 @@ func (c *Collector) collectNetworkMetrics(ch chan<- prometheus.Metric, container
} }
for _, containerId := range endpoint.SharedContainers { for _, containerId := range endpoint.SharedContainers {
containerIdWithPrefix, ok := containerPrefixes[containerId] containerInfo, ok := c.annotationsCacheHCS[containerId]
if !ok { if !ok {
c.logger.Debug("Failed to collect network stats for container " + containerId) c.logger.Debug("Unknown container " + containerId + " for endpoint " + endpoint.ID)
continue continue
} }
endpointId := strings.ToUpper(endpoint.Id) // Skip if the container is a pause container
if containerInfo.pod != "" && containerInfo.container == "" {
continue
}
endpointId := strings.ToUpper(endpoint.ID)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesReceived, c.bytesReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.BytesReceived), float64(endpointStats.BytesReceived),
containerIdWithPrefix, endpointId, containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesSent, c.bytesSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.BytesSent), float64(endpointStats.BytesSent),
containerIdWithPrefix, endpointId, containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsReceived, c.packetsReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.PacketsReceived), float64(endpointStats.PacketsReceived),
containerIdWithPrefix, endpointId, containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsSent, c.packetsSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.PacketsSent), float64(endpointStats.PacketsSent),
containerIdWithPrefix, endpointId, containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.droppedPacketsIncoming, c.droppedPacketsIncoming,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.DroppedPacketsIncoming), float64(endpointStats.DroppedPacketsIncoming),
containerIdWithPrefix, endpointId, containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.droppedPacketsOutgoing, c.droppedPacketsOutgoing,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.DroppedPacketsOutgoing), float64(endpointStats.DroppedPacketsOutgoing),
containerIdWithPrefix, endpointId, containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, endpointId,
) )
} }
} }
@@ -445,12 +607,317 @@ func (c *Collector) collectNetworkMetrics(ch chan<- prometheus.Metric, container
return nil return nil
} }
func getContainerIdWithPrefix(containerDetails hcsshim.ContainerProperties) string { // collectJobContainers collects container metrics for job containers.
switch containerDetails.Owner { // Job container based on Win32 Job objects.
// https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects
//
// Job containers are containers that aren't managed by HCS, e.g host process containers.
func (c *Collector) collectJobContainers(ch chan<- prometheus.Metric) error {
containerDStateFS := os.DirFS(c.config.ContainerDStateDir)
allContainerIDs := make([]string, 0, len(c.annotationsCacheJob)+len(c.annotationsCacheHCS))
jobContainerIDs := make([]string, 0, len(allContainerIDs))
if err := fs.WalkDir(containerDStateFS, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
c.logger.Warn("containerd state directory does not exist",
slog.String("path", c.config.ContainerDStateDir),
slog.Any("err", err),
)
return nil
}
return err
}
if path == "." {
return nil
}
if !d.IsDir() {
return nil
}
if _, err := os.Stat(path + "\\config.json"); err != nil {
containerID := strings.TrimPrefix(strings.Replace(path, c.config.ContainerDStateDir, "", 1), `\`)
if spec, err := c.getContainerAnnotations(containerID); err == nil {
isHostProcess, ok := spec.Annotations["microsoft.com/hostprocess-container"]
if ok && isHostProcess == "true" {
allContainerIDs = append(allContainerIDs, containerID)
if _, ok := c.annotationsCacheJob[containerID]; !ok {
var (
namespace string
podName string
containerName string
)
namespace = spec.Annotations["io.kubernetes.cri.sandbox-namespace"]
podName = spec.Annotations["io.kubernetes.cri.sandbox-name"]
containerName = spec.Annotations["io.kubernetes.cri.container-name"]
c.annotationsCacheJob[containerID] = containerInfo{
id: "containerd://" + containerID,
namespace: namespace,
pod: podName,
container: containerName,
}
}
}
}
}
// Skip the directory content
return fs.SkipDir
}); err != nil {
return fmt.Errorf("error in walking containerd state directory: %w", err)
}
errs := make([]error, 0)
for _, containerID := range allContainerIDs {
if err := c.collectJobContainer(ch, containerID); err != nil {
errs = append(errs, err)
} else {
jobContainerIDs = append(jobContainerIDs, containerID)
}
}
// Remove containers that are no longer running
for _, containerID := range c.annotationsCacheJob {
if !slices.Contains(jobContainerIDs, containerID.id) {
delete(c.annotationsCacheJob, containerID.id)
}
}
return errors.Join(errs...)
}
func (c *Collector) collectJobContainer(ch chan<- prometheus.Metric, containerID string) error {
jobObjectHandle, err := kernel32.OpenJobObject("Global\\JobContainer_" + containerID)
if err != nil {
if errors.Is(err, windows.ERROR_FILE_NOT_FOUND) {
return nil
}
return fmt.Errorf("error in opening job object: %w", err)
}
defer func(fd windows.Handle) {
_ = windows.Close(fd)
}(jobObjectHandle)
var jobInfo kernel32.JobObjectBasicAndIOAccountingInformation
if err = windows.QueryInformationJobObject(
jobObjectHandle,
windows.JobObjectBasicAndIoAccountingInformation,
uintptr(unsafe.Pointer(&jobInfo)),
uint32(unsafe.Sizeof(jobInfo)),
nil,
); err != nil {
return fmt.Errorf("error in querying job object information: %w", err)
}
var jobMemoryInfo kernel32.JobObjectMemoryUsageInformation
// https://github.com/microsoft/hcsshim/blob/bfb2a106798d3765666f6e39ec6cf0117275eab4/internal/jobobject/jobobject.go#L410
if err = windows.QueryInformationJobObject(
jobObjectHandle,
JobObjectMemoryUsageInformation,
uintptr(unsafe.Pointer(&jobMemoryInfo)),
uint32(unsafe.Sizeof(jobMemoryInfo)),
nil,
); err != nil {
return fmt.Errorf("error in querying job object memory usage information: %w", err)
}
privateWorkingSetBytes, err := calculatePrivateWorkingSetBytes(jobObjectHandle)
if err != nil {
c.logger.Debug("error in calculating private working set bytes", slog.Any("err", err))
}
containerInfo := c.annotationsCacheJob[containerID]
ch <- prometheus.MustNewConstMetric(
c.containerAvailable,
prometheus.GaugeValue,
1,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container, "true",
)
ch <- prometheus.MustNewConstMetric(
c.usageCommitBytes,
prometheus.GaugeValue,
float64(jobMemoryInfo.JobMemory),
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.usageCommitPeakBytes,
prometheus.GaugeValue,
float64(jobMemoryInfo.PeakJobMemoryUsed),
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.usagePrivateWorkingSetBytes,
prometheus.GaugeValue,
float64(privateWorkingSetBytes),
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.runtimeTotal,
prometheus.CounterValue,
(float64(jobInfo.BasicInfo.ThisPeriodTotalKernelTime)+float64(jobInfo.BasicInfo.ThisPeriodTotalUserTime))*pdh.TicksToSecondScaleFactor,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.runtimeUser,
prometheus.CounterValue,
float64(jobInfo.BasicInfo.ThisPeriodTotalUserTime)*pdh.TicksToSecondScaleFactor,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.runtimeKernel,
prometheus.CounterValue,
float64(jobInfo.BasicInfo.ThisPeriodTotalKernelTime)*pdh.TicksToSecondScaleFactor,
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.readCountNormalized,
prometheus.CounterValue,
float64(jobInfo.IoInfo.ReadOperationCount),
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.readSizeBytes,
prometheus.CounterValue,
float64(jobInfo.IoInfo.ReadTransferCount),
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.writeCountNormalized,
prometheus.CounterValue,
float64(jobInfo.IoInfo.WriteOperationCount),
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
ch <- prometheus.MustNewConstMetric(
c.writeSizeBytes,
prometheus.CounterValue,
float64(jobInfo.IoInfo.WriteTransferCount),
containerInfo.id, containerInfo.namespace, containerInfo.pod, containerInfo.container,
)
return nil
}
func getContainerIdWithPrefix(container hcs.Properties) string {
switch container.Owner {
case "containerd-shim-runhcs-v1.exe": case "containerd-shim-runhcs-v1.exe":
return "containerd://" + containerDetails.ID return "containerd://" + container.ID
default: default:
// default to docker or if owner is not set // default to docker or if owner is not set
return "docker://" + containerDetails.ID return "docker://" + container.ID
} }
} }
func (c *Collector) getContainerAnnotations(containerID string) (ociSpec, error) {
configJSON, err := os.OpenFile(fmt.Sprintf(`%s%s\config.json`, c.config.ContainerDStateDir, containerID), os.O_RDONLY, 0)
if err != nil {
return ociSpec{}, fmt.Errorf("error in opening config.json file: %w", err)
}
var annotations ociSpec
if err = json.NewDecoder(configJSON).Decode(&annotations); err != nil {
return ociSpec{}, fmt.Errorf("error in decoding config.json file: %w", err)
}
return annotations, nil
}
func calculatePrivateWorkingSetBytes(jobObjectHandle windows.Handle) (uint64, error) {
var pidList kernel32.JobObjectBasicProcessIDList
retLen := uint32(unsafe.Sizeof(pidList))
if err := windows.QueryInformationJobObject(
jobObjectHandle,
windows.JobObjectBasicProcessIdList,
uintptr(unsafe.Pointer(&pidList)),
retLen, &retLen); err != nil {
return 0, err
}
var (
privateWorkingSetBytes uint64
vmCounters kernel32.PROCESS_VM_COUNTERS
)
retLen = uint32(unsafe.Sizeof(vmCounters))
getMemoryStats := func(pid uint32) (uint64, error) {
processHandle, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid)
if err != nil {
return 0, fmt.Errorf("error in opening process: %w", err)
}
defer func(fd windows.Handle) {
_ = windows.Close(fd)
}(processHandle)
var isInJob bool
if err := kernel32.IsProcessInJob(processHandle, jobObjectHandle, &isInJob); err != nil {
return 0, fmt.Errorf("error in checking if process is in job: %w", err)
}
if !isInJob {
return 0, nil
}
if err := windows.NtQueryInformationProcess(
processHandle,
windows.ProcessVmCounters,
unsafe.Pointer(&vmCounters),
retLen,
&retLen,
); err != nil {
return 0, fmt.Errorf("error in querying process information: %w", err)
}
return uint64(vmCounters.PrivateWorkingSetSize), nil
}
for _, pid := range pidList.PIDs() {
privateWorkingSetSize, err := getMemoryStats(pid)
if err != nil {
return 0, fmt.Errorf("error in getting private working set bytes: %w", err)
}
privateWorkingSetBytes += privateWorkingSetSize
}
return privateWorkingSetBytes, nil
}

View File

@@ -234,12 +234,14 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
coreData.C1TimeSeconds, coreData.C1TimeSeconds,
core, "c1", core, "c1",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
coreData.C2TimeSeconds, coreData.C2TimeSeconds,
core, "c2", core, "c2",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -253,24 +255,28 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
coreData.IdleTimeSeconds, coreData.IdleTimeSeconds,
core, "idle", core, "idle",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.timeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
coreData.InterruptTimeSeconds, coreData.InterruptTimeSeconds,
core, "interrupt", core, "interrupt",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.timeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
coreData.DpcTimeSeconds, coreData.DpcTimeSeconds,
core, "dpc", core, "dpc",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.timeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
coreData.PrivilegedTimeSeconds, coreData.PrivilegedTimeSeconds,
core, "privileged", core, "privileged",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.timeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -284,18 +290,21 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
coreData.InterruptsTotal, coreData.InterruptsTotal,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.dpcsTotal, c.dpcsTotal,
prometheus.CounterValue, prometheus.CounterValue,
coreData.DpcQueuedPerSecond, coreData.DpcQueuedPerSecond,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.clockInterruptsTotal, c.clockInterruptsTotal,
prometheus.CounterValue, prometheus.CounterValue,
coreData.ClockInterruptsTotal, coreData.ClockInterruptsTotal,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.idleBreakEventsTotal, c.idleBreakEventsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -316,30 +325,35 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
coreData.ProcessorFrequencyMHz, coreData.ProcessorFrequencyMHz,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.processorPerformance, c.processorPerformance,
prometheus.CounterValue, prometheus.CounterValue,
coreData.ProcessorPerformance, coreData.ProcessorPerformance,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.processorMPerf, c.processorMPerf,
prometheus.CounterValue, prometheus.CounterValue,
counterProcessorMPerfValues.Value(), counterProcessorMPerfValues.Value(),
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.processorRTC, c.processorRTC,
prometheus.CounterValue, prometheus.CounterValue,
counterProcessorRTCValues.Value(), counterProcessorRTCValues.Value(),
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.processorUtility, c.processorUtility,
prometheus.CounterValue, prometheus.CounterValue,
coreData.ProcessorUtilityRate, coreData.ProcessorUtilityRate,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.processorPrivilegedUtility, c.processorPrivilegedUtility,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -194,36 +194,42 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
strconv.Itoa(int(processor.Family)), strconv.Itoa(int(processor.Family)),
strings.TrimRight(processor.Name, " "), strings.TrimRight(processor.Name, " "),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cpuCoreCount, c.cpuCoreCount,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(processor.NumberOfCores), float64(processor.NumberOfCores),
strings.TrimRight(processor.DeviceID, " "), strings.TrimRight(processor.DeviceID, " "),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cpuEnabledCoreCount, c.cpuEnabledCoreCount,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(processor.NumberOfEnabledCore), float64(processor.NumberOfEnabledCore),
strings.TrimRight(processor.DeviceID, " "), strings.TrimRight(processor.DeviceID, " "),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cpuLogicalProcessorsCount, c.cpuLogicalProcessorsCount,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(processor.NumberOfLogicalProcessors), float64(processor.NumberOfLogicalProcessors),
strings.TrimRight(processor.DeviceID, " "), strings.TrimRight(processor.DeviceID, " "),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cpuThreadCount, c.cpuThreadCount,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(processor.ThreadCount), float64(processor.ThreadCount),
strings.TrimRight(processor.DeviceID, " "), strings.TrimRight(processor.DeviceID, " "),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cpuL2CacheSize, c.cpuL2CacheSize,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(processor.L2CacheSize), float64(processor.L2CacheSize),
strings.TrimRight(processor.DeviceID, " "), strings.TrimRight(processor.DeviceID, " "),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.cpuL3CacheSize, c.cpuL3CacheSize,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -1,157 +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 cs
import (
"log/slog"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
const Name = "cs"
type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics.
type Collector struct {
config Config
// physicalMemoryBytes
// Deprecated: Use windows_memory_physical_total_bytes instead
physicalMemoryBytes *prometheus.Desc
// logicalProcessors
// Deprecated: Use windows_cpu_logical_processor instead
logicalProcessors *prometheus.Desc
// hostname
// Deprecated: Use windows_os_hostname instead
hostname *prometheus.Desc
}
func New(config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c
}
func NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{}
}
func (c *Collector) GetName() string {
return Name
}
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
logger.Warn("The cs collector is deprecated and will be removed in a future release. " +
"Logical processors has been moved to cpu_info collector. " +
"Physical memory has been moved to memory collector. " +
"Hostname has been moved to os collector.")
c.logicalProcessors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "logical_processors"),
"Deprecated: Use windows_cpu_logical_processor instead",
nil,
nil,
)
c.physicalMemoryBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "physical_memory_bytes"),
"Deprecated: Use windows_memory_physical_total_bytes instead",
nil,
nil,
)
c.hostname = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hostname"),
"Deprecated: Use windows_os_hostname instead",
[]string{
"hostname",
"domain",
"fqdn",
},
nil,
)
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
// Get systeminfo for number of processors
systemInfo := sysinfoapi.GetSystemInfo()
// Get memory status for physical memory
mem, err := sysinfoapi.GlobalMemoryStatusEx()
if err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
c.logicalProcessors,
prometheus.GaugeValue,
float64(systemInfo.NumberOfProcessors),
)
ch <- prometheus.MustNewConstMetric(
c.physicalMemoryBytes,
prometheus.GaugeValue,
float64(mem.TotalPhys),
)
hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname)
if err != nil {
return err
}
domain, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSDomain)
if err != nil {
return err
}
fqdn, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSFullyQualified)
if err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
c.hostname,
prometheus.GaugeValue,
1.0,
hostname,
domain,
fqdn,
)
return nil
}

View File

@@ -56,6 +56,8 @@ var ConfigDefaults = Config{
type Collector struct { type Collector struct {
config Config config Config
logger *slog.Logger
perfDataCollector *pdh.Collector perfDataCollector *pdh.Collector
perfDataObject []perfDataCounterValues perfDataObject []perfDataCounterValues
@@ -147,7 +149,9 @@ func (c *Collector) Close() error {
return nil return nil
} }
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
var err error var err error
if slices.Contains(c.config.CollectorsEnabled, subCollectorScopeMetrics) { if slices.Contains(c.config.CollectorsEnabled, subCollectorScopeMetrics) {
@@ -405,6 +409,8 @@ func (c *Collector) collectServerMetrics(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect DHCP Server metrics: %w", err) return fmt.Errorf("failed to collect DHCP Server metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect DHCP Server metrics: %w", types.ErrNoDataUnexpected)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -38,7 +38,9 @@ var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive. // A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive.
type Collector struct { type Collector struct {
config Config config Config
logger *slog.Logger
miSession *mi.Session miSession *mi.Session
miQuery mi.Query miQuery mi.Query
@@ -73,7 +75,9 @@ func (c *Collector) Close() error {
return nil return nil
} }
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error { func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name))
c.diskInfo = prometheus.NewDesc( c.diskInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"), prometheus.BuildFQName(types.Namespace, Name, "info"),
"General drive information", "General drive information",
@@ -148,7 +152,7 @@ var (
"Error", "Error",
"Degraded", "Degraded",
"Unknown", "Unknown",
"Pred fail", "Pred Fail",
"Starting", "Starting",
"Stopping", "Stopping",
"Service", "Service",
@@ -241,6 +245,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
if availNum == int(disk.Availability) { if availNum == int(disk.Availability) {
isCurrentState = 1.0 isCurrentState = 1.0
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.availability, c.availability,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -347,6 +347,8 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect DNS metrics: %w", err) return fmt.Errorf("failed to collect DNS metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect DNS metrics: %w", types.ErrNoDataUnexpected)
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -355,6 +357,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].AxfrRequestReceived, c.perfDataObject[0].AxfrRequestReceived,
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.zoneTransferRequestsReceived, c.zoneTransferRequestsReceived,
prometheus.CounterValue, prometheus.CounterValue,
@@ -368,12 +371,14 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].AxfrRequestSent, c.perfDataObject[0].AxfrRequestSent,
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.zoneTransferRequestsSent, c.zoneTransferRequestsSent,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].IxfrRequestSent, c.perfDataObject[0].IxfrRequestSent,
"incremental", "incremental",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.zoneTransferRequestsSent, c.zoneTransferRequestsSent,
prometheus.CounterValue, prometheus.CounterValue,
@@ -387,6 +392,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].AxfrResponseReceived, c.perfDataObject[0].AxfrResponseReceived,
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.zoneTransferResponsesReceived, c.zoneTransferResponsesReceived,
prometheus.CounterValue, prometheus.CounterValue,
@@ -401,6 +407,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
"full", "full",
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.zoneTransferSuccessReceived, c.zoneTransferSuccessReceived,
prometheus.CounterValue, prometheus.CounterValue,
@@ -408,6 +415,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
"incremental", "incremental",
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.zoneTransferSuccessReceived, c.zoneTransferSuccessReceived,
prometheus.CounterValue, prometheus.CounterValue,
@@ -422,6 +430,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].AxfrSuccessSent, c.perfDataObject[0].AxfrSuccessSent,
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.zoneTransferSuccessSent, c.zoneTransferSuccessSent,
prometheus.CounterValue, prometheus.CounterValue,
@@ -441,30 +450,35 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].CachingMemory, c.perfDataObject[0].CachingMemory,
"caching", "caching",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.memoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].DatabaseNodeMemory, c.perfDataObject[0].DatabaseNodeMemory,
"database_node", "database_node",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.memoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].NbStatMemory, c.perfDataObject[0].NbStatMemory,
"nbstat", "nbstat",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.memoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].RecordFlowMemory, c.perfDataObject[0].RecordFlowMemory,
"record_flow", "record_flow",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.memoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].TcpMessageMemory, c.perfDataObject[0].TcpMessageMemory,
"tcp_message", "tcp_message",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.memoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -478,23 +492,27 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].DynamicUpdateNoOperation, c.perfDataObject[0].DynamicUpdateNoOperation,
"noop", "noop",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.dynamicUpdatesReceived, c.dynamicUpdatesReceived,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DynamicUpdateWrittenToDatabase, c.perfDataObject[0].DynamicUpdateWrittenToDatabase,
"written", "written",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.dynamicUpdatesQueued, c.dynamicUpdatesQueued,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObject[0].DynamicUpdateQueued, c.perfDataObject[0].DynamicUpdateQueued,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.dynamicUpdatesFailures, c.dynamicUpdatesFailures,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].DynamicUpdateRejected, c.perfDataObject[0].DynamicUpdateRejected,
"rejected", "rejected",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.dynamicUpdatesFailures, c.dynamicUpdatesFailures,
prometheus.CounterValue, prometheus.CounterValue,
@@ -507,6 +525,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].NotifyReceived, c.perfDataObject[0].NotifyReceived,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.notifySent, c.notifySent,
prometheus.CounterValue, prometheus.CounterValue,
@@ -518,11 +537,13 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].RecursiveQueries, c.perfDataObject[0].RecursiveQueries,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.recursiveQueryFailures, c.recursiveQueryFailures,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].RecursiveQueryFailure, c.perfDataObject[0].RecursiveQueryFailure,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.recursiveQuerySendTimeouts, c.recursiveQuerySendTimeouts,
prometheus.CounterValue, prometheus.CounterValue,
@@ -535,6 +556,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].TcpQueryReceived, c.perfDataObject[0].TcpQueryReceived,
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.queries, c.queries,
prometheus.CounterValue, prometheus.CounterValue,
@@ -548,6 +570,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].TcpResponseSent, c.perfDataObject[0].TcpResponseSent,
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.responses, c.responses,
prometheus.CounterValue, prometheus.CounterValue,
@@ -567,6 +590,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].WinsLookupReceived, c.perfDataObject[0].WinsLookupReceived,
"forward", "forward",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.winsQueries, c.winsQueries,
prometheus.CounterValue, prometheus.CounterValue,
@@ -580,6 +604,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
c.perfDataObject[0].WinsResponseSent, c.perfDataObject[0].WinsResponseSent,
"forward", "forward",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.winsResponses, c.winsResponses,
prometheus.CounterValue, prometheus.CounterValue,
@@ -592,6 +617,7 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObject[0].SecureUpdateFailure, c.perfDataObject[0].SecureUpdateFailure,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.secureUpdateReceived, c.secureUpdateReceived,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -66,11 +66,6 @@ var ConfigDefaults = Config{
} }
type Collector struct { type Collector struct {
config Config
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
collectorADAccessProcesses collectorADAccessProcesses
collectorActiveSync collectorActiveSync
collectorAutoDiscover collectorAutoDiscover
@@ -81,6 +76,11 @@ type Collector struct {
collectorRpcClientAccess collectorRpcClientAccess
collectorTransportQueues collectorTransportQueues
collectorWorkloadManagementWorkloads collectorWorkloadManagementWorkloads
config Config
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
} }
func New(config *Config) *Collector { func New(config *Config) *Collector {

View File

@@ -82,11 +82,13 @@ func (c *Collector) collectActiveSync(ch chan<- prometheus.Metric) error {
prometheus.CounterValue, prometheus.CounterValue,
data.RequestsPerSec, data.RequestsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.pingCommandsPending, c.pingCommandsPending,
prometheus.GaugeValue, prometheus.GaugeValue,
data.PingCommandsPending, data.PingCommandsPending,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.syncCommandsPerSec, c.syncCommandsPerSec,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -113,24 +113,28 @@ func (c *Collector) collectADAccessProcesses(ch chan<- prometheus.Metric) error
utils.MilliSecToSec(data.LdapReadTime), utils.MilliSecToSec(data.LdapReadTime),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ldapSearchTime, c.ldapSearchTime,
prometheus.CounterValue, prometheus.CounterValue,
utils.MilliSecToSec(data.LdapSearchTime), utils.MilliSecToSec(data.LdapSearchTime),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ldapWriteTime, c.ldapWriteTime,
prometheus.CounterValue, prometheus.CounterValue,
utils.MilliSecToSec(data.LdapWriteTime), utils.MilliSecToSec(data.LdapWriteTime),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ldapTimeoutErrorsPerSec, c.ldapTimeoutErrorsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
data.LdapTimeoutErrorsPerSec, data.LdapTimeoutErrorsPerSec,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.longRunningLDAPOperationsPerMin, c.longRunningLDAPOperationsPerMin,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -111,30 +111,35 @@ func (c *Collector) collectHTTPProxy(ch chan<- prometheus.Metric) error {
utils.MilliSecToSec(data.MailboxServerLocatorAverageLatency), utils.MilliSecToSec(data.MailboxServerLocatorAverageLatency),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.averageAuthenticationLatency, c.averageAuthenticationLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
data.AverageAuthenticationLatency, data.AverageAuthenticationLatency,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.averageCASProcessingLatency, c.averageCASProcessingLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.AverageCASProcessingLatency), utils.MilliSecToSec(data.AverageCASProcessingLatency),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.mailboxServerProxyFailureRate, c.mailboxServerProxyFailureRate,
prometheus.GaugeValue, prometheus.GaugeValue,
data.MailboxServerProxyFailureRate, data.MailboxServerProxyFailureRate,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outstandingProxyRequests, c.outstandingProxyRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
data.OutstandingProxyRequests, data.OutstandingProxyRequests,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.proxyRequestsPerSec, c.proxyRequestsPerSec,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -74,6 +74,7 @@ func (c *Collector) collectOWA(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue, prometheus.GaugeValue,
data.CurrentUniqueUsers, data.CurrentUniqueUsers,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.owaRequestsPerSec, c.owaRequestsPerSec,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -107,26 +107,31 @@ func (c *Collector) collectRpcClientAccess(ch chan<- prometheus.Metric) error {
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.RpcAveragedLatency), utils.MilliSecToSec(data.RpcAveragedLatency),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.rpcRequests, c.rpcRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
data.RpcRequests, data.RpcRequests,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.activeUserCount, c.activeUserCount,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ActiveUserCount, data.ActiveUserCount,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.connectionCount, c.connectionCount,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ConnectionCount, data.ConnectionCount,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.rpcOperationsPerSec, c.rpcOperationsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
data.RpcOperationsPerSec, data.RpcOperationsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.userCount, c.userCount,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -215,108 +215,126 @@ func (c *Collector) collectTransportQueues(ch chan<- prometheus.Metric) error {
data.ExternalActiveRemoteDeliveryQueueLength, data.ExternalActiveRemoteDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.internalActiveRemoteDeliveryQueueLength, c.internalActiveRemoteDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.InternalActiveRemoteDeliveryQueueLength, data.InternalActiveRemoteDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.activeMailboxDeliveryQueueLength, c.activeMailboxDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ActiveMailboxDeliveryQueueLength, data.ActiveMailboxDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.retryMailboxDeliveryQueueLength, c.retryMailboxDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.RetryMailboxDeliveryQueueLength, data.RetryMailboxDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.unreachableQueueLength, c.unreachableQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.UnreachableQueueLength, data.UnreachableQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.externalLargestDeliveryQueueLength, c.externalLargestDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ExternalLargestDeliveryQueueLength, data.ExternalLargestDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.internalLargestDeliveryQueueLength, c.internalLargestDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.InternalLargestDeliveryQueueLength, data.InternalLargestDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.poisonQueueLength, c.poisonQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.PoisonQueueLength, data.PoisonQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesQueuedForDeliveryTotal, c.messagesQueuedForDeliveryTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.MessagesQueuedForDeliveryTotal, data.MessagesQueuedForDeliveryTotal,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesSubmittedTotal, c.messagesSubmittedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.MessagesSubmittedTotal, data.MessagesSubmittedTotal,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesDelayedTotal, c.messagesDelayedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.MessagesDelayedTotal, data.MessagesDelayedTotal,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.messagesCompletedDeliveryTotal, c.messagesCompletedDeliveryTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.MessagesCompletedDeliveryTotal, data.MessagesCompletedDeliveryTotal,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.aggregateShadowQueueLength, c.aggregateShadowQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.AggregateShadowQueueLength, data.AggregateShadowQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.submissionQueueLength, c.submissionQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.SubmissionQueueLength, data.SubmissionQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.delayQueueLength, c.delayQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.DelayQueueLength, data.DelayQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.itemsCompletedDeliveryTotal, c.itemsCompletedDeliveryTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ItemsCompletedDeliveryTotal, data.ItemsCompletedDeliveryTotal,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.itemsQueuedForDeliveryExpiredTotal, c.itemsQueuedForDeliveryExpiredTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ItemsQueuedForDeliveryExpiredTotal, data.ItemsQueuedForDeliveryExpiredTotal,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.itemsQueuedForDeliveryTotal, c.itemsQueuedForDeliveryTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ItemsQueuedForDeliveryTotal, data.ItemsQueuedForDeliveryTotal,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.itemsResubmittedTotal, c.itemsResubmittedTotal,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -103,24 +103,28 @@ func (c *Collector) collectWorkloadManagementWorkloads(ch chan<- prometheus.Metr
data.ActiveTasks, data.ActiveTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.completedTasks, c.completedTasks,
prometheus.CounterValue, prometheus.CounterValue,
data.CompletedTasks, data.CompletedTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.queuedTasks, c.queuedTasks,
prometheus.CounterValue, prometheus.CounterValue,
data.QueuedTasks, data.QueuedTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.yieldedTasks, c.yieldedTasks,
prometheus.CounterValue, prometheus.CounterValue,
data.YieldedTasks, data.YieldedTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.isActive, c.isActive,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -19,6 +19,7 @@ package filetime
import ( import (
"fmt" "fmt"
"io/fs"
"log/slog" "log/slog"
"os" "os"
"path/filepath" "path/filepath"
@@ -73,19 +74,10 @@ func NewWithFlags(app *kingpin.Application) *Collector {
} }
c.config.FilePatterns = make([]string, 0) c.config.FilePatterns = make([]string, 0)
var filePatterns string
app.Flag( app.Flag(
"collector.filetime.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", "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, ",")).StringVar(&filePatterns) ).Default(strings.Join(ConfigDefaults.FilePatterns, ",")).StringsVar(&c.config.FilePatterns)
app.Action(func(*kingpin.ParseContext) error {
// doublestar.Glob() requires forward slashes
c.config.FilePatterns = strings.Split(filepath.ToSlash(filePatterns), ",")
return nil
})
return c return c
} }
@@ -148,16 +140,11 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
} }
func (c *Collector) collectGlobFilePath(ch chan<- prometheus.Metric, filePattern string) error { func (c *Collector) collectGlobFilePath(ch chan<- prometheus.Metric, filePattern string) error {
basePath, pattern := doublestar.SplitPattern(filePattern) basePath, pattern := doublestar.SplitPattern(filepath.ToSlash(filePattern))
basePathFS := os.DirFS(basePath) basePathFS := os.DirFS(basePath)
matches, err := doublestar.Glob(basePathFS, pattern, doublestar.WithFilesOnly()) err := doublestar.GlobWalk(basePathFS, pattern, func(path string, d fs.DirEntry) error {
if err != nil { filePath := filepath.Join(basePath, path)
return fmt.Errorf("failed to glob: %w", err)
}
for _, match := range matches {
filePath := filepath.Join(basePath, match)
fileInfo, err := os.Stat(filePath) fileInfo, err := os.Stat(filePath)
if err != nil { if err != nil {
@@ -166,15 +153,20 @@ func (c *Collector) collectGlobFilePath(ch chan<- prometheus.Metric, filePattern
slog.Any("err", err), slog.Any("err", err),
) )
continue return nil
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.fileMTime, c.fileMTime,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(fileInfo.ModTime().UTC().Unix()), float64(fileInfo.ModTime().UTC().UnixMicro())/1e6,
filePath, filePath,
) )
return nil
}, doublestar.WithFilesOnly(), doublestar.WithCaseInsensitive())
if err != nil {
return fmt.Errorf("failed to glob: %w", err)
} }
return nil return nil

View File

@@ -190,6 +190,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.size, c.size,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -197,6 +198,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.usage, c.usage,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -204,12 +206,14 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.description, c.description,
prometheus.GaugeValue, prometheus.GaugeValue,
1.0, 1.0,
path, template, Description, path, template, Description,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.disabled, c.disabled,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -217,6 +221,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.matchesTemplate, c.matchesTemplate,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -224,6 +229,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.softLimit, c.softLimit,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -0,0 +1,531 @@
// 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 gpu
import (
"errors"
"fmt"
"log/slog"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/cfgmgr32"
"github.com/prometheus-community/windows_exporter/internal/headers/gdi32"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
const Name = "gpu"
type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{}
type Collector struct {
config Config
gpuDeviceCache map[string]gpuDevice
// GPU Engine
gpuEnginePerfDataCollector *pdh.Collector
gpuEnginePerfDataObject []gpuEnginePerfDataCounterValues
gpuInfo *prometheus.Desc
gpuEngineRunningTime *prometheus.Desc
gpuSharedSystemMemorySize *prometheus.Desc
gpuDedicatedSystemMemorySize *prometheus.Desc
gpuDedicatedVideoMemorySize *prometheus.Desc
// GPU Adapter Memory
gpuAdapterMemoryPerfDataCollector *pdh.Collector
gpuAdapterMemoryPerfDataObject []gpuAdapterMemoryPerfDataCounterValues
gpuAdapterMemoryDedicatedUsage *prometheus.Desc
gpuAdapterMemorySharedUsage *prometheus.Desc
gpuAdapterMemoryTotalCommitted *prometheus.Desc
// GPU Local Adapter Memory
gpuLocalAdapterMemoryPerfDataCollector *pdh.Collector
gpuLocalAdapterMemoryPerfDataObject []gpuLocalAdapterMemoryPerfDataCounterValues
gpuLocalAdapterMemoryUsage *prometheus.Desc
// GPU Non Local Adapter Memory
gpuNonLocalAdapterMemoryPerfDataCollector *pdh.Collector
gpuNonLocalAdapterMemoryPerfDataObject []gpuNonLocalAdapterMemoryPerfDataCounterValues
gpuNonLocalAdapterMemoryUsage *prometheus.Desc
// GPU Process Memory
gpuProcessMemoryPerfDataCollector *pdh.Collector
gpuProcessMemoryPerfDataObject []gpuProcessMemoryPerfDataCounterValues
gpuProcessMemoryDedicatedUsage *prometheus.Desc
gpuProcessMemoryLocalUsage *prometheus.Desc
gpuProcessMemoryNonLocalUsage *prometheus.Desc
gpuProcessMemorySharedUsage *prometheus.Desc
gpuProcessMemoryTotalCommitted *prometheus.Desc
}
type gpuDevice struct {
gdi32 gdi32.GPUDevice
cfgmgr32 cfgmgr32.Device
ID string
}
func New(config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c
}
func NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{}
}
func (c *Collector) GetName() string {
return Name
}
func (c *Collector) Close() error {
c.gpuEnginePerfDataCollector.Close()
c.gpuAdapterMemoryPerfDataCollector.Close()
c.gpuLocalAdapterMemoryPerfDataCollector.Close()
c.gpuNonLocalAdapterMemoryPerfDataCollector.Close()
c.gpuProcessMemoryPerfDataCollector.Close()
return nil
}
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
var err error
c.gpuInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"),
"A metric with a constant '1' value labeled with gpu device information.",
[]string{"luid", "device_id", "name", "bus_number", "phys", "function_number"},
nil,
)
c.gpuSharedSystemMemorySize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "shared_system_memory_size_bytes"),
"The size, in bytes, of memory from system memory that can be shared by many users.",
[]string{"luid", "device_id"},
nil,
)
c.gpuDedicatedSystemMemorySize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dedicated_system_memory_size_bytes"),
"The size, in bytes, of memory that is dedicated from system memory.",
[]string{"luid", "device_id"},
nil,
)
c.gpuDedicatedVideoMemorySize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dedicated_video_memory_size_bytes"),
"The size, in bytes, of memory that is dedicated from video memory.",
[]string{"luid", "device_id"},
nil,
)
c.gpuEngineRunningTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "engine_time_seconds"),
"Total running time of the GPU in seconds.",
[]string{"process_id", "luid", "device_id", "phys", "eng", "engtype"},
nil,
)
c.gpuAdapterMemoryDedicatedUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "adapter_memory_dedicated_bytes"),
"Dedicated GPU memory usage in bytes.",
[]string{"luid", "device_id", "phys"},
nil,
)
c.gpuAdapterMemorySharedUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "adapter_memory_shared_bytes"),
"Shared GPU memory usage in bytes.",
[]string{"luid", "device_id", "phys"},
nil,
)
c.gpuAdapterMemoryTotalCommitted = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "adapter_memory_committed_bytes"),
"Total committed GPU memory in bytes.",
[]string{"luid", "device_id", "phys"},
nil,
)
c.gpuLocalAdapterMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "local_adapter_memory_bytes"),
"Local adapter memory usage in bytes.",
[]string{"luid", "device_id", "phys", "part"},
nil,
)
c.gpuNonLocalAdapterMemoryUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "non_local_adapter_memory_bytes"),
"Non-local adapter memory usage in bytes.",
[]string{"luid", "device_id", "phys", "part"},
nil,
)
c.gpuProcessMemoryDedicatedUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "process_memory_dedicated_bytes"),
"Dedicated process memory usage in bytes.",
[]string{"process_id", "luid", "device_id", "phys"},
nil,
)
c.gpuProcessMemoryLocalUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "process_memory_local_bytes"),
"Local process memory usage in bytes.",
[]string{"process_id", "luid", "device_id", "phys"},
nil,
)
c.gpuProcessMemoryNonLocalUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "process_memory_non_local_bytes"),
"Non-local process memory usage in bytes.",
[]string{"process_id", "luid", "device_id", "phys"},
nil,
)
c.gpuProcessMemorySharedUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "process_memory_shared_bytes"),
"Shared process memory usage in bytes.",
[]string{"process_id", "luid", "device_id", "phys"},
nil,
)
c.gpuProcessMemoryTotalCommitted = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "process_memory_committed_bytes"),
"Total committed process memory in bytes.",
[]string{"process_id", "luid", "device_id", "phys"},
nil,
)
errs := make([]error, 0)
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](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](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](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](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))
}
gpus, err := gdi32.GetGPUDevices()
if err != nil {
errs = append(errs, fmt.Errorf("failed to get GPU devices: %w", err))
}
for _, gpu := range gpus {
if gpu.AdapterString == "" {
continue
}
if c.gpuDeviceCache == nil {
c.gpuDeviceCache = make(map[string]gpuDevice)
}
luidKey := fmt.Sprintf("0x%08X_0x%08X", gpu.LUID.HighPart, gpu.LUID.LowPart)
deviceID := gpu.DeviceID
cfgmgr32Devs, err := cfgmgr32.GetDevicesInstanceIDs(gpu.DeviceID)
if err != nil {
errs = append(errs, fmt.Errorf("failed to get device instance IDs for device ID %s: %w", gpu.DeviceID, err))
}
var cfgmgr32Dev cfgmgr32.Device
for _, dev := range cfgmgr32Devs {
if dev.BusNumber == gpu.BusNumber && dev.DeviceNumber == gpu.DeviceNumber && dev.FunctionNumber == gpu.FunctionNumber {
cfgmgr32Dev = dev
break
}
}
if cfgmgr32Dev.InstanceID == "" {
errs = append(errs, fmt.Errorf("failed to find matching device for device ID %s", gpu.DeviceID))
} else {
deviceID = cfgmgr32Dev.InstanceID
}
c.gpuDeviceCache[luidKey] = gpuDevice{
gdi32: gpu,
cfgmgr32: cfgmgr32Dev,
ID: deviceID,
}
}
return errors.Join(errs...)
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
errs := make([]error, 0)
c.collectGpuInfo(ch)
if err := c.collectGpuEngineMetrics(ch); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuAdapterMemoryMetrics(ch); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuLocalAdapterMemoryMetrics(ch); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuNonLocalAdapterMemoryMetrics(ch); err != nil {
errs = append(errs, err)
}
if err := c.collectGpuProcessMemoryMetrics(ch); err != nil {
errs = append(errs, err)
}
return errors.Join(errs...)
}
func (c *Collector) collectGpuInfo(ch chan<- prometheus.Metric) {
for luid, gpu := range c.gpuDeviceCache {
ch <- prometheus.MustNewConstMetric(
c.gpuInfo,
prometheus.GaugeValue,
1.0,
luid,
gpu.ID,
gpu.gdi32.AdapterString,
gpu.gdi32.BusNumber.String(),
gpu.gdi32.DeviceNumber.String(),
gpu.gdi32.FunctionNumber.String(),
)
ch <- prometheus.MustNewConstMetric(
c.gpuSharedSystemMemorySize,
prometheus.GaugeValue,
float64(gpu.gdi32.SharedSystemMemorySize),
luid, gpu.ID,
)
ch <- prometheus.MustNewConstMetric(
c.gpuDedicatedSystemMemorySize,
prometheus.GaugeValue,
float64(gpu.gdi32.DedicatedSystemMemorySize),
luid, gpu.ID,
)
ch <- prometheus.MustNewConstMetric(
c.gpuDedicatedVideoMemorySize,
prometheus.GaugeValue,
float64(gpu.gdi32.DedicatedVideoMemorySize),
luid, gpu.ID,
)
}
}
func (c *Collector) collectGpuEngineMetrics(ch chan<- prometheus.Metric) error {
// Collect the GPU Engine perf data.
if err := c.gpuEnginePerfDataCollector.Collect(&c.gpuEnginePerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Engine perf data: %w", err)
}
// Iterate over the GPU Engine perf data and aggregate the values.
for _, data := range c.gpuEnginePerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
device, ok := c.gpuDeviceCache[instance.Luid]
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
c.gpuEngineRunningTime,
prometheus.CounterValue,
data.RunningTime/10_000_000,
instance.Pid, instance.Luid, device.ID, instance.Phys, instance.Eng, instance.Engtype,
)
}
return nil
}
func (c *Collector) collectGpuAdapterMemoryMetrics(ch chan<- prometheus.Metric) error {
// Collect the GPU Adapter Memory perf data.
if err := c.gpuAdapterMemoryPerfDataCollector.Collect(&c.gpuAdapterMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Adapter Memory perf data: %w", err)
}
for _, data := range c.gpuAdapterMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
device, ok := c.gpuDeviceCache[instance.Luid]
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
c.gpuAdapterMemoryDedicatedUsage,
prometheus.GaugeValue,
data.DedicatedUsage,
instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
c.gpuAdapterMemorySharedUsage,
prometheus.GaugeValue,
data.SharedUsage,
instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
c.gpuAdapterMemoryTotalCommitted,
prometheus.GaugeValue,
data.TotalCommitted,
instance.Luid, device.ID, instance.Phys,
)
}
return nil
}
func (c *Collector) collectGpuLocalAdapterMemoryMetrics(ch chan<- prometheus.Metric) error {
// Collect the GPU Local Adapter Memory perf data.
if err := c.gpuLocalAdapterMemoryPerfDataCollector.Collect(&c.gpuLocalAdapterMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Local Adapter Memory perf data: %w", err)
}
for _, data := range c.gpuLocalAdapterMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
device, ok := c.gpuDeviceCache[instance.Luid]
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
c.gpuLocalAdapterMemoryUsage,
prometheus.GaugeValue,
data.LocalUsage,
instance.Luid, device.ID, instance.Phys, instance.Part,
)
}
return nil
}
func (c *Collector) collectGpuNonLocalAdapterMemoryMetrics(ch chan<- prometheus.Metric) error {
// Collect the GPU Non Local Adapter Memory perf data.
if err := c.gpuNonLocalAdapterMemoryPerfDataCollector.Collect(&c.gpuNonLocalAdapterMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Non Local Adapter Memory perf data: %w", err)
}
for _, data := range c.gpuNonLocalAdapterMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
device, ok := c.gpuDeviceCache[instance.Luid]
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
c.gpuNonLocalAdapterMemoryUsage,
prometheus.GaugeValue,
data.NonLocalUsage,
instance.Luid, device.ID, instance.Phys, instance.Part,
)
}
return nil
}
func (c *Collector) collectGpuProcessMemoryMetrics(ch chan<- prometheus.Metric) error {
// Collect the GPU Process Memory perf data.
if err := c.gpuProcessMemoryPerfDataCollector.Collect(&c.gpuProcessMemoryPerfDataObject); err != nil {
return fmt.Errorf("failed to collect GPU Process Memory perf data: %w", err)
}
for _, data := range c.gpuProcessMemoryPerfDataObject {
instance := parseGPUCounterInstanceString(data.Name)
device, ok := c.gpuDeviceCache[instance.Luid]
if !ok {
continue
}
ch <- prometheus.MustNewConstMetric(
c.gpuProcessMemoryDedicatedUsage,
prometheus.GaugeValue,
data.DedicatedUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
c.gpuProcessMemoryLocalUsage,
prometheus.GaugeValue,
data.LocalUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
c.gpuProcessMemoryNonLocalUsage,
prometheus.GaugeValue,
data.NonLocalUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
c.gpuProcessMemorySharedUsage,
prometheus.GaugeValue,
data.SharedUsage,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
ch <- prometheus.MustNewConstMetric(
c.gpuProcessMemoryTotalCommitted,
prometheus.GaugeValue,
data.TotalCommitted,
instance.Pid, instance.Luid, device.ID, instance.Phys,
)
}
return nil
}

View File

@@ -15,19 +15,19 @@
//go:build windows //go:build windows
package cs_test package gpu_test
import ( import (
"testing" "testing"
"github.com/prometheus-community/windows_exporter/internal/collector/cs" "github.com/prometheus-community/windows_exporter/internal/collector/gpu"
"github.com/prometheus-community/windows_exporter/internal/utils/testutils" "github.com/prometheus-community/windows_exporter/internal/utils/testutils"
) )
func BenchmarkCollector(b *testing.B) { func BenchmarkCollector(b *testing.B) {
testutils.FuncBenchmarkCollector(b, cs.Name, cs.NewWithFlags) testutils.FuncBenchmarkCollector(b, gpu.Name, gpu.NewWithFlags)
} }
func TestCollector(t *testing.T) { func TestCollector(t *testing.T) {
testutils.TestCollector(t, cs.New, nil) testutils.TestCollector(t, gpu.New, nil)
} }

View File

@@ -0,0 +1,55 @@
// 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 gpu
type gpuEnginePerfDataCounterValues struct {
Name string
RunningTime float64 `perfdata:"Running Time"`
UtilizationPercentage float64 `perfdata:"Utilization Percentage"`
}
type gpuAdapterMemoryPerfDataCounterValues struct {
Name string
DedicatedUsage float64 `perfdata:"Dedicated Usage"`
SharedUsage float64 `perfdata:"Shared Usage"`
TotalCommitted float64 `perfdata:"Total Committed"`
}
type gpuLocalAdapterMemoryPerfDataCounterValues struct {
Name string
LocalUsage float64 `perfdata:"Local Usage"`
}
type gpuNonLocalAdapterMemoryPerfDataCounterValues struct {
Name string
NonLocalUsage float64 `perfdata:"Non Local Usage"`
}
type gpuProcessMemoryPerfDataCounterValues struct {
Name string
DedicatedUsage float64 `perfdata:"Dedicated Usage"`
LocalUsage float64 `perfdata:"Local Usage"`
NonLocalUsage float64 `perfdata:"Non Local Usage"`
SharedUsage float64 `perfdata:"Shared Usage"`
TotalCommitted float64 `perfdata:"Total Committed"`
}

View File

@@ -0,0 +1,89 @@
// 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 gpu
import (
"fmt"
"strings"
)
type Instance struct {
Pid string
Luid string
DeviceID string
Phys string
Eng string
Engtype string
Part string
}
type PidPhys struct {
Pid string
Luid string
DeviceID string
Phys string
}
type PidPhysEngEngType struct {
Pid string
Luid string
DeviceID string
Phys string
Eng string
Engtype string
}
func parseGPUCounterInstanceString(s string) Instance {
// Example: "pid_1234_luid_0x00000000_0x00005678_phys_0_eng_0_engtype_3D"
// Example: "luid_0x00000000_0x00005678_phys_0"
// Example: "luid_0x00000000_0x00005678_phys_0_part_0"
parts := strings.Split(s, "_")
var instance Instance
for i, part := range parts {
switch part {
case "pid":
if i+1 < len(parts) {
instance.Pid = parts[i+1]
}
case "luid":
if i+2 < len(parts) {
instance.Luid = fmt.Sprintf("%s_%s", parts[i+1], parts[i+2])
}
case "phys":
if i+1 < len(parts) {
instance.Phys = parts[i+1]
}
case "eng":
if i+1 < len(parts) {
instance.Eng = parts[i+1]
}
case "engtype":
if i+1 < len(parts) {
instance.Engtype = parts[i+1]
}
case "part":
if i+1 < len(parts) {
instance.Part = parts[i+1]
}
}
}
return instance
}

View File

@@ -25,9 +25,9 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/Microsoft/hcsshim/osversion"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
@@ -78,11 +78,6 @@ var ConfigDefaults = Config{
// Collector is a Prometheus Collector for hyper-v. // Collector is a Prometheus Collector for hyper-v.
type Collector struct { type Collector struct {
config Config
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
collectorDataStore collectorDataStore
collectorDynamicMemoryBalancer collectorDynamicMemoryBalancer
collectorDynamicMemoryVM collectorDynamicMemoryVM
@@ -98,6 +93,11 @@ type Collector struct {
collectorVirtualSMB collectorVirtualSMB
collectorVirtualStorageDevice collectorVirtualStorageDevice
collectorVirtualSwitch collectorVirtualSwitch
config Config
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
} }
func New(config *Config) *Collector { func New(config *Config) *Collector {

View File

@@ -20,7 +20,7 @@ package hyperv
import ( import (
"fmt" "fmt"
"github.com/Microsoft/hcsshim/osversion" "github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils" "github.com/prometheus-community/windows_exporter/internal/utils"

View File

@@ -20,7 +20,7 @@ package hyperv
import ( import (
"fmt" "fmt"
"github.com/Microsoft/hcsshim/osversion" "github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils" "github.com/prometheus-community/windows_exporter/internal/utils"

View File

@@ -310,26 +310,31 @@ func (c *Collector) collectHypervisorRootPartition(ch chan<- prometheus.Metric)
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition2MDevicePages, c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition2MDevicePages,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition2MGPAPages, c.hypervisorRootPartition2MGPAPages,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition2MGPAPages, c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition2MGPAPages,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition4KDevicePages, c.hypervisorRootPartition4KDevicePages,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition4KDevicePages, c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition4KDevicePages,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartition4KGPAPages, c.hypervisorRootPartition4KGPAPages,
prometheus.GaugeValue, prometheus.GaugeValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition4KGPAPages, c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartition4KGPAPages,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionVirtualTLBFlushEntries, c.hypervisorRootPartitionVirtualTLBFlushEntries,
prometheus.CounterValue, prometheus.CounterValue,
c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionVirtualTLBFlushEntries, c.perfDataObjectHypervisorRootPartition[0].HypervisorRootPartitionVirtualTLBFlushEntries,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.hypervisorRootPartitionVirtualTLBPages, c.hypervisorRootPartitionVirtualTLBPages,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -195,294 +195,343 @@ func (c *Collector) collectVirtualNetworkAdapterDropReasons(ch chan<- prometheus
data.VirtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq, data.VirtualNetworkAdapterDropReasonsOutgoingNativeFwdingReq,
data.Name, "NativeFwdingReq", "outgoing", data.Name, "NativeFwdingReq", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingNativeFwdingReq, data.VirtualNetworkAdapterDropReasonsIncomingNativeFwdingReq,
data.Name, "NativeFwdingReq", "incoming", data.Name, "NativeFwdingReq", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingMTUMismatch, data.VirtualNetworkAdapterDropReasonsOutgoingMTUMismatch,
data.Name, "MTUMismatch", "outgoing", data.Name, "MTUMismatch", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingMTUMismatch, data.VirtualNetworkAdapterDropReasonsIncomingMTUMismatch,
data.Name, "MTUMismatch", "incoming", data.Name, "MTUMismatch", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingInvalidConfig, data.VirtualNetworkAdapterDropReasonsOutgoingInvalidConfig,
data.Name, "InvalidConfig", "outgoing", data.Name, "InvalidConfig", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingInvalidConfig, data.VirtualNetworkAdapterDropReasonsIncomingInvalidConfig,
data.Name, "InvalidConfig", "incoming", data.Name, "InvalidConfig", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing, data.VirtualNetworkAdapterDropReasonsOutgoingRequiredExtensionMissing,
data.Name, "RequiredExtensionMissing", "outgoing", data.Name, "RequiredExtensionMissing", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing, data.VirtualNetworkAdapterDropReasonsIncomingRequiredExtensionMissing,
data.Name, "RequiredExtensionMissing", "incoming", data.Name, "RequiredExtensionMissing", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId, data.VirtualNetworkAdapterDropReasonsOutgoingVirtualSubnetId,
data.Name, "VirtualSubnetId", "outgoing", data.Name, "VirtualSubnetId", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingVirtualSubnetId, data.VirtualNetworkAdapterDropReasonsIncomingVirtualSubnetId,
data.Name, "VirtualSubnetId", "incoming", data.Name, "VirtualSubnetId", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingBridgeReserved, data.VirtualNetworkAdapterDropReasonsOutgoingBridgeReserved,
data.Name, "BridgeReserved", "outgoing", data.Name, "BridgeReserved", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingBridgeReserved, data.VirtualNetworkAdapterDropReasonsIncomingBridgeReserved,
data.Name, "BridgeReserved", "incoming", data.Name, "BridgeReserved", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingRouterGuard, data.VirtualNetworkAdapterDropReasonsOutgoingRouterGuard,
data.Name, "RouterGuard", "outgoing", data.Name, "RouterGuard", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingRouterGuard, data.VirtualNetworkAdapterDropReasonsIncomingRouterGuard,
data.Name, "RouterGuard", "incoming", data.Name, "RouterGuard", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingDhcpGuard, data.VirtualNetworkAdapterDropReasonsOutgoingDhcpGuard,
data.Name, "DhcpGuard", "outgoing", data.Name, "DhcpGuard", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingDhcpGuard, data.VirtualNetworkAdapterDropReasonsIncomingDhcpGuard,
data.Name, "DhcpGuard", "incoming", data.Name, "DhcpGuard", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingMacSpoofing, data.VirtualNetworkAdapterDropReasonsOutgoingMacSpoofing,
data.Name, "MacSpoofing", "outgoing", data.Name, "MacSpoofing", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingMacSpoofing, data.VirtualNetworkAdapterDropReasonsIncomingMacSpoofing,
data.Name, "MacSpoofing", "incoming", data.Name, "MacSpoofing", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingIpsec, data.VirtualNetworkAdapterDropReasonsOutgoingIpsec,
data.Name, "Ipsec", "outgoing", data.Name, "Ipsec", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingIpsec, data.VirtualNetworkAdapterDropReasonsIncomingIpsec,
data.Name, "Ipsec", "incoming", data.Name, "Ipsec", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingQos, data.VirtualNetworkAdapterDropReasonsOutgoingQos,
data.Name, "Qos", "outgoing", data.Name, "Qos", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingQos, data.VirtualNetworkAdapterDropReasonsIncomingQos,
data.Name, "Qos", "incoming", data.Name, "Qos", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting, data.VirtualNetworkAdapterDropReasonsOutgoingFailedPvlanSetting,
data.Name, "FailedPvlanSetting", "outgoing", data.Name, "FailedPvlanSetting", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting, data.VirtualNetworkAdapterDropReasonsIncomingFailedPvlanSetting,
data.Name, "FailedPvlanSetting", "incoming", data.Name, "FailedPvlanSetting", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy, data.VirtualNetworkAdapterDropReasonsOutgoingFailedSecurityPolicy,
data.Name, "FailedSecurityPolicy", "outgoing", data.Name, "FailedSecurityPolicy", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy, data.VirtualNetworkAdapterDropReasonsIncomingFailedSecurityPolicy,
data.Name, "FailedSecurityPolicy", "incoming", data.Name, "FailedSecurityPolicy", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC, data.VirtualNetworkAdapterDropReasonsOutgoingUnauthorizedMAC,
data.Name, "UnauthorizedMAC", "outgoing", data.Name, "UnauthorizedMAC", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC, data.VirtualNetworkAdapterDropReasonsIncomingUnauthorizedMAC,
data.Name, "UnauthorizedMAC", "incoming", data.Name, "UnauthorizedMAC", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN, data.VirtualNetworkAdapterDropReasonsOutgoingUnauthorizedVLAN,
data.Name, "UnauthorizedVLAN", "outgoing", data.Name, "UnauthorizedVLAN", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN, data.VirtualNetworkAdapterDropReasonsIncomingUnauthorizedVLAN,
data.Name, "UnauthorizedVLAN", "incoming", data.Name, "UnauthorizedVLAN", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFilteredVLAN, data.VirtualNetworkAdapterDropReasonsOutgoingFilteredVLAN,
data.Name, "FilteredVLAN", "outgoing", data.Name, "FilteredVLAN", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFilteredVLAN, data.VirtualNetworkAdapterDropReasonsIncomingFilteredVLAN,
data.Name, "FilteredVLAN", "incoming", data.Name, "FilteredVLAN", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingFiltered, data.VirtualNetworkAdapterDropReasonsOutgoingFiltered,
data.Name, "Filtered", "outgoing", data.Name, "Filtered", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingFiltered, data.VirtualNetworkAdapterDropReasonsIncomingFiltered,
data.Name, "Filtered", "incoming", data.Name, "Filtered", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingBusy, data.VirtualNetworkAdapterDropReasonsOutgoingBusy,
data.Name, "Busy", "outgoing", data.Name, "Busy", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingBusy, data.VirtualNetworkAdapterDropReasonsIncomingBusy,
data.Name, "Busy", "incoming", data.Name, "Busy", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingNotAccepted, data.VirtualNetworkAdapterDropReasonsOutgoingNotAccepted,
data.Name, "NotAccepted", "outgoing", data.Name, "NotAccepted", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingNotAccepted, data.VirtualNetworkAdapterDropReasonsIncomingNotAccepted,
data.Name, "NotAccepted", "incoming", data.Name, "NotAccepted", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingDisconnected, data.VirtualNetworkAdapterDropReasonsOutgoingDisconnected,
data.Name, "Disconnected", "outgoing", data.Name, "Disconnected", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingDisconnected, data.VirtualNetworkAdapterDropReasonsIncomingDisconnected,
data.Name, "Disconnected", "incoming", data.Name, "Disconnected", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingNotReady, data.VirtualNetworkAdapterDropReasonsOutgoingNotReady,
data.Name, "NotReady", "outgoing", data.Name, "NotReady", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingNotReady, data.VirtualNetworkAdapterDropReasonsIncomingNotReady,
data.Name, "NotReady", "incoming", data.Name, "NotReady", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingResources, data.VirtualNetworkAdapterDropReasonsOutgoingResources,
data.Name, "Resources", "outgoing", data.Name, "Resources", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingResources, data.VirtualNetworkAdapterDropReasonsIncomingResources,
data.Name, "Resources", "incoming", data.Name, "Resources", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingInvalidPacket, data.VirtualNetworkAdapterDropReasonsOutgoingInvalidPacket,
data.Name, "InvalidPacket", "outgoing", data.Name, "InvalidPacket", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingInvalidPacket, data.VirtualNetworkAdapterDropReasonsIncomingInvalidPacket,
data.Name, "InvalidPacket", "incoming", data.Name, "InvalidPacket", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingInvalidData, data.VirtualNetworkAdapterDropReasonsOutgoingInvalidData,
data.Name, "InvalidData", "outgoing", data.Name, "InvalidData", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsIncomingInvalidData, data.VirtualNetworkAdapterDropReasonsIncomingInvalidData,
data.Name, "InvalidData", "incoming", data.Name, "InvalidData", "incoming",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualNetworkAdapterDropReasonsOutgoingUnknown, data.VirtualNetworkAdapterDropReasonsOutgoingUnknown,
data.Name, "Unknown", "outgoing", data.Name, "Unknown", "outgoing",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualNetworkAdapterDropReasons, c.virtualNetworkAdapterDropReasons,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -265,6 +265,7 @@ func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error {
data.VirtualSwitchDirectedPacketsReceived, data.VirtualSwitchDirectedPacketsReceived,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchDirectedPacketsSent, c.virtualSwitchDirectedPacketsSent,
prometheus.CounterValue, prometheus.CounterValue,
@@ -278,18 +279,21 @@ func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error {
data.VirtualSwitchDroppedPacketsIncoming, data.VirtualSwitchDroppedPacketsIncoming,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchDroppedPacketsOutgoing, c.virtualSwitchDroppedPacketsOutgoing,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualSwitchDroppedPacketsOutgoing, data.VirtualSwitchDroppedPacketsOutgoing,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchExtensionsDroppedPacketsIncoming, c.virtualSwitchExtensionsDroppedPacketsIncoming,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualSwitchExtensionsDroppedPacketsIncoming, data.VirtualSwitchExtensionsDroppedPacketsIncoming,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchExtensionsDroppedPacketsOutgoing, c.virtualSwitchExtensionsDroppedPacketsOutgoing,
prometheus.CounterValue, prometheus.CounterValue,
@@ -303,24 +307,28 @@ func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error {
data.VirtualSwitchLearnedMacAddresses, data.VirtualSwitchLearnedMacAddresses,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchMulticastPacketsReceived, c.virtualSwitchMulticastPacketsReceived,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualSwitchMulticastPacketsReceived, data.VirtualSwitchMulticastPacketsReceived,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchMulticastPacketsSent, c.virtualSwitchMulticastPacketsSent,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualSwitchMulticastPacketsSent, data.VirtualSwitchMulticastPacketsSent,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchNumberOfSendChannelMoves, c.virtualSwitchNumberOfSendChannelMoves,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualSwitchNumberOfSendChannelMoves, data.VirtualSwitchNumberOfSendChannelMoves,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchNumberOfVMQMoves, c.virtualSwitchNumberOfVMQMoves,
prometheus.CounterValue, prometheus.CounterValue,
@@ -348,12 +356,14 @@ func (c *Collector) collectVirtualSwitch(ch chan<- prometheus.Metric) error {
data.VirtualSwitchPacketsReceived, data.VirtualSwitchPacketsReceived,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchPacketsSent, c.virtualSwitchPacketsSent,
prometheus.CounterValue, prometheus.CounterValue,
data.VirtualSwitchPacketsSent, data.VirtualSwitchPacketsSent,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.virtualSwitchPurgedMacAddresses, c.virtualSwitchPurgedMacAddresses,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -50,14 +50,18 @@ var ConfigDefaults = Config{
} }
type Collector struct { type Collector struct {
config Config
iisVersion simpleVersion
info *prometheus.Desc
collectorWebService collectorWebService
collectorHttpServiceRequestQueues
collectorAppPoolWAS collectorAppPoolWAS
collectorW3SVCW3WP collectorW3SVCW3WP
collectorWebServiceCache collectorWebServiceCache
config Config
iisVersion simpleVersion
logger *slog.Logger
info *prometheus.Desc
} }
func New(config *Config) *Collector { func New(config *Config) *Collector {
@@ -150,6 +154,7 @@ func (c *Collector) GetName() string {
func (c *Collector) Close() error { func (c *Collector) Close() error {
c.perfDataCollectorWebService.Close() c.perfDataCollectorWebService.Close()
c.perfDataCollectorHttpServiceRequestQueues.Close()
c.perfDataCollectorAppPoolWAS.Close() c.perfDataCollectorAppPoolWAS.Close()
c.w3SVCW3WPPerfDataCollector.Close() c.w3SVCW3WPPerfDataCollector.Close()
c.serviceCachePerfDataCollector.Close() c.serviceCachePerfDataCollector.Close()
@@ -158,9 +163,9 @@ func (c *Collector) Close() error {
} }
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
logger = logger.With(slog.String("collector", Name)) c.logger = logger.With(slog.String("collector", Name))
c.iisVersion = c.getIISVersion(logger) c.iisVersion = c.getIISVersion()
c.info = prometheus.NewDesc( c.info = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"), prometheus.BuildFQName(types.Namespace, Name, "info"),
@@ -175,6 +180,10 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
errs = append(errs, fmt.Errorf("failed to build Web Service collector: %w", err)) errs = append(errs, fmt.Errorf("failed to build Web Service collector: %w", err))
} }
if err := c.buildHttpServiceRequestQueues(); err != nil {
errs = append(errs, fmt.Errorf("failed to build Http Service collector: %w", err))
}
if err := c.buildAppPoolWAS(); err != nil { if err := c.buildAppPoolWAS(); err != nil {
errs = append(errs, fmt.Errorf("failed to build APP_POOL_WAS collector: %w", err)) errs = append(errs, fmt.Errorf("failed to build APP_POOL_WAS collector: %w", err))
} }
@@ -195,10 +204,10 @@ type simpleVersion struct {
minor uint64 minor uint64
} }
func (c *Collector) getIISVersion(logger *slog.Logger) simpleVersion { func (c *Collector) getIISVersion() simpleVersion {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE) k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE)
if err != nil { if err != nil {
logger.Warn("couldn't open registry to determine IIS version", c.logger.Warn("couldn't open registry to determine IIS version",
slog.Any("err", err), slog.Any("err", err),
) )
@@ -208,7 +217,7 @@ func (c *Collector) getIISVersion(logger *slog.Logger) simpleVersion {
defer func() { defer func() {
err = k.Close() err = k.Close()
if err != nil { if err != nil {
logger.Warn("Failed to close registry key", c.logger.Warn("Failed to close registry key",
slog.Any("err", err), slog.Any("err", err),
) )
} }
@@ -216,7 +225,7 @@ func (c *Collector) getIISVersion(logger *slog.Logger) simpleVersion {
major, _, err := k.GetIntegerValue("MajorVersion") major, _, err := k.GetIntegerValue("MajorVersion")
if err != nil { if err != nil {
logger.Warn("Couldn't open registry to determine IIS version", c.logger.Warn("Couldn't open registry to determine IIS version",
slog.Any("err", err), slog.Any("err", err),
) )
@@ -225,14 +234,14 @@ func (c *Collector) getIISVersion(logger *slog.Logger) simpleVersion {
minor, _, err := k.GetIntegerValue("MinorVersion") minor, _, err := k.GetIntegerValue("MinorVersion")
if err != nil { if err != nil {
logger.Warn("Couldn't open registry to determine IIS version", c.logger.Warn("Couldn't open registry to determine IIS version",
slog.Any("err", err), slog.Any("err", err),
) )
return simpleVersion{} return simpleVersion{}
} }
logger.Debug(fmt.Sprintf("Detected IIS %d.%d\n", major, minor)) c.logger.Debug(fmt.Sprintf("Detected IIS %d.%d\n", major, minor))
return simpleVersion{ return simpleVersion{
major: major, major: major,
@@ -255,6 +264,10 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
errs = append(errs, fmt.Errorf("failed to collect Web Service metrics: %w", err)) errs = append(errs, fmt.Errorf("failed to collect Web Service metrics: %w", err))
} }
if err := c.collectHttpServiceRequestQueues(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect Http Service Request Queues metrics: %w", err))
}
if err := c.collectAppPoolWAS(ch); err != nil { if err := c.collectAppPoolWAS(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err)) errs = append(errs, fmt.Errorf("failed to collect APP_POOL_WAS metrics: %w", err))
} }

View File

@@ -201,66 +201,77 @@ func (c *Collector) collectAppPoolWAS(ch chan<- prometheus.Metric) error {
data.CurrentApplicationPoolUptime, data.CurrentApplicationPoolUptime,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentWorkerProcesses, c.currentWorkerProcesses,
prometheus.GaugeValue, prometheus.GaugeValue,
data.CurrentWorkerProcesses, data.CurrentWorkerProcesses,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.maximumWorkerProcesses, c.maximumWorkerProcesses,
prometheus.GaugeValue, prometheus.GaugeValue,
data.MaximumWorkerProcesses, data.MaximumWorkerProcesses,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.recentWorkerProcessFailures, c.recentWorkerProcessFailures,
prometheus.GaugeValue, prometheus.GaugeValue,
data.RecentWorkerProcessFailures, data.RecentWorkerProcessFailures,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.timeSinceLastWorkerProcessFailure, c.timeSinceLastWorkerProcessFailure,
prometheus.GaugeValue, prometheus.GaugeValue,
data.TimeSinceLastWorkerProcessFailure, data.TimeSinceLastWorkerProcessFailure,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalApplicationPoolRecycles, c.totalApplicationPoolRecycles,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalApplicationPoolRecycles, data.TotalApplicationPoolRecycles,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalApplicationPoolUptime, c.totalApplicationPoolUptime,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalApplicationPoolUptime, data.TotalApplicationPoolUptime,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessesCreated, c.totalWorkerProcessesCreated,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalWorkerProcessesCreated, data.TotalWorkerProcessesCreated,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessFailures, c.totalWorkerProcessFailures,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalWorkerProcessFailures, data.TotalWorkerProcessFailures,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessPingFailures, c.totalWorkerProcessPingFailures,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalWorkerProcessPingFailures, data.TotalWorkerProcessPingFailures,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessShutdownFailures, c.totalWorkerProcessShutdownFailures,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalWorkerProcessShutdownFailures, data.TotalWorkerProcessShutdownFailures,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalWorkerProcessStartupFailures, c.totalWorkerProcessStartupFailures,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -0,0 +1,137 @@
// 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 iis
import (
"fmt"
"strings"
"github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
type collectorHttpServiceRequestQueues struct {
perfDataCollectorHttpServiceRequestQueues *pdh.Collector
perfDataObjectHttpServiceRequestQueues []perfDataCounterValuesHttpServiceRequestQueues
httpRequestQueuesCurrentQueueSize *prometheus.Desc
httpRequestQueuesTotalRejectedRequest *prometheus.Desc
httpRequestQueuesMaxQueueItemAge *prometheus.Desc
httpRequestQueuesArrivalRate *prometheus.Desc
}
type perfDataCounterValuesHttpServiceRequestQueues struct {
Name string
HttpRequestQueuesCurrentQueueSize float64 `perfdata:"CurrentQueueSize"`
HttpRequestQueuesTotalRejectedRequests float64 `perfdata:"RejectedRequests"`
HttpRequestQueuesMaxQueueItemAge float64 `perfdata:"MaxQueueItemAge"`
HttpRequestQueuesArrivalRate float64 `perfdata:"ArrivalRate"`
}
func (p perfDataCounterValuesHttpServiceRequestQueues) GetName() string {
return p.Name
}
func (c *Collector) buildHttpServiceRequestQueues() error {
var err 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](pdh.CounterTypeRaw, "HTTP Service Request Queues", pdh.InstancesAll)
if err != nil {
return fmt.Errorf("failed to create Http Service collector: %w", err)
}
c.httpRequestQueuesCurrentQueueSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_requests_current_queue_size"),
"Http Request Current Queue Size",
[]string{"site"},
nil,
)
c.httpRequestQueuesTotalRejectedRequest = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_request_total_rejected_request"),
"Http Request Total Rejected Request",
[]string{"site"},
nil,
)
c.httpRequestQueuesMaxQueueItemAge = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_requests_max_queue_item_age"),
"Http Request Max Queue Item Age. The values might be bogus if the queue is empty.",
[]string{"site"},
nil,
)
c.httpRequestQueuesArrivalRate = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "http_requests_arrival_rate"),
"Http Request Arrival Rate",
[]string{"site"},
nil,
)
return nil
}
func (c *Collector) collectHttpServiceRequestQueues(ch chan<- prometheus.Metric) error {
err := c.perfDataCollectorHttpServiceRequestQueues.Collect(&c.perfDataObjectHttpServiceRequestQueues)
if err != nil {
return fmt.Errorf("failed to collect Http Service Request Queues metrics: %w", err)
}
deduplicateIISNames(c.perfDataObjectHttpServiceRequestQueues)
for _, data := range c.perfDataObjectHttpServiceRequestQueues {
if strings.HasPrefix(data.Name, "---") {
continue
}
if c.config.SiteExclude.MatchString(data.Name) || !c.config.SiteInclude.MatchString(data.Name) {
continue
}
ch <- prometheus.MustNewConstMetric(
c.httpRequestQueuesCurrentQueueSize,
prometheus.GaugeValue,
data.HttpRequestQueuesCurrentQueueSize,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.httpRequestQueuesTotalRejectedRequest,
prometheus.GaugeValue,
data.HttpRequestQueuesTotalRejectedRequests,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.httpRequestQueuesMaxQueueItemAge,
prometheus.GaugeValue,
data.HttpRequestQueuesMaxQueueItemAge,
data.Name,
)
ch <- prometheus.MustNewConstMetric(
c.httpRequestQueuesArrivalRate,
prometheus.GaugeValue,
data.HttpRequestQueuesArrivalRate,
data.Name,
)
}
return nil
}

View File

@@ -441,6 +441,7 @@ func (c *Collector) collectW3SVCW3WPv8(ch chan<- prometheus.Metric) error {
pid, pid,
"401", "401",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPRequestErrorsTotal, c.w3SVCW3WPRequestErrorsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -449,6 +450,7 @@ func (c *Collector) collectW3SVCW3WPv8(ch chan<- prometheus.Metric) error {
pid, pid,
"403", "403",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPRequestErrorsTotal, c.w3SVCW3WPRequestErrorsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -457,6 +459,7 @@ func (c *Collector) collectW3SVCW3WPv8(ch chan<- prometheus.Metric) error {
pid, pid,
"404", "404",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPRequestErrorsTotal, c.w3SVCW3WPRequestErrorsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -465,6 +468,7 @@ func (c *Collector) collectW3SVCW3WPv8(ch chan<- prometheus.Metric) error {
pid, pid,
"500", "500",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPWebSocketRequestsActive, c.w3SVCW3WPWebSocketRequestsActive,
prometheus.CounterValue, prometheus.CounterValue,
@@ -472,6 +476,7 @@ func (c *Collector) collectW3SVCW3WPv8(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPWebSocketConnectionAttempts, c.w3SVCW3WPWebSocketConnectionAttempts,
prometheus.CounterValue, prometheus.CounterValue,
@@ -479,6 +484,7 @@ func (c *Collector) collectW3SVCW3WPv8(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPWebSocketConnectionsAccepted, c.w3SVCW3WPWebSocketConnectionsAccepted,
prometheus.CounterValue, prometheus.CounterValue,
@@ -486,6 +492,7 @@ func (c *Collector) collectW3SVCW3WPv8(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPWebSocketConnectionsRejected, c.w3SVCW3WPWebSocketConnectionsRejected,
prometheus.CounterValue, prometheus.CounterValue,
@@ -507,10 +514,6 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
deduplicateIISNames(c.perfDataObjectW3SVCW3WP) deduplicateIISNames(c.perfDataObjectW3SVCW3WP)
for _, data := range c.perfDataObjectW3SVCW3WP { for _, data := range c.perfDataObjectW3SVCW3WP {
if c.config.AppExclude.MatchString(data.Name) || !c.config.AppInclude.MatchString(data.Name) {
continue
}
// Extract the apppool name from the format <PID>_<NAME> // Extract the apppool name from the format <PID>_<NAME>
pid := workerProcessNameExtractor.ReplaceAllString(data.Name, "$1") pid := workerProcessNameExtractor.ReplaceAllString(data.Name, "$1")
@@ -533,6 +536,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
pid, pid,
"busy", "busy",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMaximumThreads, c.w3SVCW3WPMaximumThreads,
prometheus.CounterValue, prometheus.CounterValue,
@@ -540,6 +544,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPRequestsTotal, c.w3SVCW3WPRequestsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -547,6 +552,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPRequestsActive, c.w3SVCW3WPRequestsActive,
prometheus.CounterValue, prometheus.CounterValue,
@@ -554,6 +560,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPActiveFlushedEntries, c.w3SVCW3WPActiveFlushedEntries,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -561,6 +568,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPCurrentFileCacheMemoryUsage, c.w3SVCW3WPCurrentFileCacheMemoryUsage,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -568,6 +576,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMaximumFileCacheMemoryUsage, c.w3SVCW3WPMaximumFileCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
@@ -575,6 +584,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPFileCacheFlushesTotal, c.w3SVCW3WPFileCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -582,6 +592,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPFileCacheQueriesTotal, c.w3SVCW3WPFileCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -589,6 +600,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPFileCacheHitsTotal, c.w3SVCW3WPFileCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -596,6 +608,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPFilesCached, c.w3SVCW3WPFilesCached,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -603,6 +616,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPFilesCachedTotal, c.w3SVCW3WPFilesCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -610,6 +624,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPFilesFlushedTotal, c.w3SVCW3WPFilesFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -617,6 +632,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPURICacheFlushesTotal, c.w3SVCW3WPURICacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -624,6 +640,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPURICacheQueriesTotal, c.w3SVCW3WPURICacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -631,6 +648,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPURICacheHitsTotal, c.w3SVCW3WPURICacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -638,6 +656,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPURIsCached, c.w3SVCW3WPURIsCached,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -645,6 +664,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPURIsCachedTotal, c.w3SVCW3WPURIsCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -652,6 +672,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPURIsFlushedTotal, c.w3SVCW3WPURIsFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -659,6 +680,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMetadataCached, c.w3SVCW3WPMetadataCached,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -666,6 +688,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMetadataCacheFlushes, c.w3SVCW3WPMetadataCacheFlushes,
prometheus.CounterValue, prometheus.CounterValue,
@@ -673,6 +696,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMetadataCacheQueriesTotal, c.w3SVCW3WPMetadataCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -680,6 +704,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMetadataCacheHitsTotal, c.w3SVCW3WPMetadataCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -687,6 +712,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMetadataCachedTotal, c.w3SVCW3WPMetadataCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -694,6 +720,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPMetadataFlushedTotal, c.w3SVCW3WPMetadataFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -701,6 +728,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPOutputCacheActiveFlushedItems, c.w3SVCW3WPOutputCacheActiveFlushedItems,
prometheus.CounterValue, prometheus.CounterValue,
@@ -708,6 +736,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPOutputCacheItems, c.w3SVCW3WPOutputCacheItems,
prometheus.CounterValue, prometheus.CounterValue,
@@ -715,6 +744,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPOutputCacheMemoryUsage, c.w3SVCW3WPOutputCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
@@ -722,6 +752,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPOutputCacheQueriesTotal, c.w3SVCW3WPOutputCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -729,6 +760,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPOutputCacheHitsTotal, c.w3SVCW3WPOutputCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -736,6 +768,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPOutputCacheFlushedItemsTotal, c.w3SVCW3WPOutputCacheFlushedItemsTotal,
prometheus.CounterValue, prometheus.CounterValue,
@@ -743,6 +776,7 @@ func (c *Collector) collectW3SVCW3WPv7(ch chan<- prometheus.Metric) error {
name, name,
pid, pid,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.w3SVCW3WPOutputCacheFlushesTotal, c.w3SVCW3WPOutputCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -262,126 +262,147 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.WebServiceCurrentAnonymousUsers, data.WebServiceCurrentAnonymousUsers,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceCurrentBlockedAsyncIORequests, c.webServiceCurrentBlockedAsyncIORequests,
prometheus.GaugeValue, prometheus.GaugeValue,
data.WebServiceCurrentBlockedAsyncIORequests, data.WebServiceCurrentBlockedAsyncIORequests,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceCurrentCGIRequests, c.webServiceCurrentCGIRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
data.WebServiceCurrentCGIRequests, data.WebServiceCurrentCGIRequests,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceCurrentConnections, c.webServiceCurrentConnections,
prometheus.GaugeValue, prometheus.GaugeValue,
data.WebServiceCurrentConnections, data.WebServiceCurrentConnections,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceCurrentISAPIExtensionRequests, c.webServiceCurrentISAPIExtensionRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
data.WebServiceCurrentISAPIExtensionRequests, data.WebServiceCurrentISAPIExtensionRequests,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceCurrentNonAnonymousUsers, c.webServiceCurrentNonAnonymousUsers,
prometheus.GaugeValue, prometheus.GaugeValue,
data.WebServiceCurrentNonAnonymousUsers, data.WebServiceCurrentNonAnonymousUsers,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceServiceUptime, c.webServiceServiceUptime,
prometheus.GaugeValue, prometheus.GaugeValue,
data.WebServiceServiceUptime, data.WebServiceServiceUptime,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalBytesReceived, c.webServiceTotalBytesReceived,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalBytesReceived, data.WebServiceTotalBytesReceived,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalBytesSent, c.webServiceTotalBytesSent,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalBytesSent, data.WebServiceTotalBytesSent,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalAnonymousUsers, c.webServiceTotalAnonymousUsers,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalAnonymousUsers, data.WebServiceTotalAnonymousUsers,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalBlockedAsyncIORequests, c.webServiceTotalBlockedAsyncIORequests,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalBlockedAsyncIORequests, data.WebServiceTotalBlockedAsyncIORequests,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalCGIRequests, c.webServiceTotalCGIRequests,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalCGIRequests, data.WebServiceTotalCGIRequests,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalConnectionAttemptsAllInstances, c.webServiceTotalConnectionAttemptsAllInstances,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalConnectionAttemptsAllInstances, data.WebServiceTotalConnectionAttemptsAllInstances,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalFilesReceived, c.webServiceTotalFilesReceived,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalFilesReceived, data.WebServiceTotalFilesReceived,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalFilesSent, c.webServiceTotalFilesSent,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalFilesSent, data.WebServiceTotalFilesSent,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalISAPIExtensionRequests, c.webServiceTotalISAPIExtensionRequests,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalISAPIExtensionRequests, data.WebServiceTotalISAPIExtensionRequests,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalLockedErrors, c.webServiceTotalLockedErrors,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalLockedErrors, data.WebServiceTotalLockedErrors,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalLogonAttempts, c.webServiceTotalLogonAttempts,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalLogonAttempts, data.WebServiceTotalLogonAttempts,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalNonAnonymousUsers, c.webServiceTotalNonAnonymousUsers,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalNonAnonymousUsers, data.WebServiceTotalNonAnonymousUsers,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalNotFoundErrors, c.webServiceTotalNotFoundErrors,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalNotFoundErrors, data.WebServiceTotalNotFoundErrors,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRejectedAsyncIORequests, c.webServiceTotalRejectedAsyncIORequests,
prometheus.CounterValue, prometheus.CounterValue,
data.WebServiceTotalRejectedAsyncIORequests, data.WebServiceTotalRejectedAsyncIORequests,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -389,6 +410,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"other", "other",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -396,6 +418,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"COPY", "COPY",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -403,6 +426,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"DELETE", "DELETE",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -410,6 +434,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"GET", "GET",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -417,6 +442,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"HEAD", "HEAD",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -424,6 +450,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"LOCK", "LOCK",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -431,6 +458,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"MKCOL", "MKCOL",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -438,6 +466,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"MOVE", "MOVE",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -445,6 +474,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"OPTIONS", "OPTIONS",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -452,6 +482,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"POST", "POST",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -459,6 +490,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"PROPFIND", "PROPFIND",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -466,6 +498,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"PROPPATCH", "PROPPATCH",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -473,6 +506,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"PUT", "PUT",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -480,6 +514,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"SEARCH", "SEARCH",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,
@@ -487,6 +522,7 @@ func (c *Collector) collectWebService(ch chan<- prometheus.Metric) error {
data.Name, data.Name,
"TRACE", "TRACE",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.webServiceTotalRequests, c.webServiceTotalRequests,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -64,8 +64,6 @@ type collectorWebServiceCache struct {
} }
type perfDataCounterServiceCache struct { type perfDataCounterServiceCache struct {
Name string
ServiceCacheActiveFlushedEntries float64 `perfdata:"Active Flushed Entries"` ServiceCacheActiveFlushedEntries float64 `perfdata:"Active Flushed Entries"`
ServiceCacheCurrentFileCacheMemoryUsage float64 `perfdata:"Current File Cache Memory Usage"` ServiceCacheCurrentFileCacheMemoryUsage float64 `perfdata:"Current File Cache Memory Usage"`
ServiceCacheMaximumFileCacheMemoryUsage float64 `perfdata:"Maximum File Cache Memory Usage"` ServiceCacheMaximumFileCacheMemoryUsage float64 `perfdata:"Maximum File Cache Memory Usage"`
@@ -102,10 +100,6 @@ type perfDataCounterServiceCache struct {
ServiceCacheOutputCacheFlushesTotal float64 `perfdata:"Output Cache Total Flushes"` ServiceCacheOutputCacheFlushesTotal float64 `perfdata:"Output Cache Total Flushes"`
} }
func (p perfDataCounterServiceCache) GetName() string {
return p.Name
}
func (c *Collector) buildWebServiceCache() error { func (c *Collector) buildWebServiceCache() error {
var err error var err error
@@ -293,190 +287,217 @@ func (c *Collector) collectWebServiceCache(ch chan<- prometheus.Metric) error {
return fmt.Errorf("failed to collect Web Service Cache metrics: %w", err) return fmt.Errorf("failed to collect Web Service Cache metrics: %w", err)
} }
deduplicateIISNames(c.perfDataObjectServiceCache)
for _, data := range c.perfDataObjectServiceCache { for _, data := range c.perfDataObjectServiceCache {
if c.config.SiteExclude.MatchString(data.Name) || !c.config.SiteInclude.MatchString(data.Name) {
continue
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheActiveFlushedEntries, c.serviceCacheActiveFlushedEntries,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ServiceCacheActiveFlushedEntries, data.ServiceCacheActiveFlushedEntries,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheCurrentFileCacheMemoryUsage, c.serviceCacheCurrentFileCacheMemoryUsage,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ServiceCacheCurrentFileCacheMemoryUsage, data.ServiceCacheCurrentFileCacheMemoryUsage,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMaximumFileCacheMemoryUsage, c.serviceCacheMaximumFileCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheMaximumFileCacheMemoryUsage, data.ServiceCacheMaximumFileCacheMemoryUsage,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheFlushesTotal, c.serviceCacheFileCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheFileCacheFlushesTotal, data.ServiceCacheFileCacheFlushesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheQueriesTotal, c.serviceCacheFileCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheFileCacheHitsTotal+data.ServiceCacheFileCacheMissesTotal, data.ServiceCacheFileCacheHitsTotal+data.ServiceCacheFileCacheMissesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFileCacheHitsTotal, c.serviceCacheFileCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheFileCacheHitsTotal, data.ServiceCacheFileCacheHitsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesCached, c.serviceCacheFilesCached,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ServiceCacheFilesCached, data.ServiceCacheFilesCached,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesCachedTotal, c.serviceCacheFilesCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheFilesCachedTotal, data.ServiceCacheFilesCachedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheFilesFlushedTotal, c.serviceCacheFilesFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheFilesFlushedTotal, data.ServiceCacheFilesFlushedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheFlushesTotal, c.serviceCacheURICacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURICacheFlushesTotal, data.ServiceCacheURICacheFlushesTotal,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheFlushesTotal, c.serviceCacheURICacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURICacheFlushesTotalKernel, data.ServiceCacheURICacheFlushesTotalKernel,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheQueriesTotal, c.serviceCacheURICacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURICacheHitsTotal+data.ServiceCacheURICacheMissesTotal, data.ServiceCacheURICacheHitsTotal+data.ServiceCacheURICacheMissesTotal,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheQueriesTotal, c.serviceCacheURICacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURICacheHitsTotalKernel+data.ServiceCacheURICacheMissesTotalKernel, data.ServiceCacheURICacheHitsTotalKernel+data.ServiceCacheURICacheMissesTotalKernel,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheHitsTotal, c.serviceCacheURICacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURICacheHitsTotal, data.ServiceCacheURICacheHitsTotal,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURICacheHitsTotal, c.serviceCacheURICacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURICacheHitsTotalKernel, data.ServiceCacheURICacheHitsTotalKernel,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCached, c.serviceCacheURIsCached,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ServiceCacheURIsCached, data.ServiceCacheURIsCached,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCached, c.serviceCacheURIsCached,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ServiceCacheURIsCachedKernel, data.ServiceCacheURIsCachedKernel,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCachedTotal, c.serviceCacheURIsCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURIsCachedTotal, data.ServiceCacheURIsCachedTotal,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsCachedTotal, c.serviceCacheURIsCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURIsCachedTotalKernel, data.ServiceCacheURIsCachedTotalKernel,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsFlushedTotal, c.serviceCacheURIsFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURIsFlushedTotal, data.ServiceCacheURIsFlushedTotal,
"user", "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheURIsFlushedTotal, c.serviceCacheURIsFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheURIsFlushedTotalKernel, data.ServiceCacheURIsFlushedTotalKernel,
"kernel", "kernel",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCached, c.serviceCacheMetadataCached,
prometheus.GaugeValue, prometheus.GaugeValue,
data.ServiceCacheMetadataCached, data.ServiceCacheMetadataCached,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheFlushes, c.serviceCacheMetadataCacheFlushes,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheMetadataCacheFlushes, data.ServiceCacheMetadataCacheFlushes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheQueriesTotal, c.serviceCacheMetadataCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheMetaDataCacheHits+data.ServiceCacheMetaDataCacheMisses, data.ServiceCacheMetaDataCacheHits+data.ServiceCacheMetaDataCacheMisses,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCacheHitsTotal, c.serviceCacheMetadataCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
0, // data.ServiceCacheMetadataCacheHitsTotal, 0, // data.ServiceCacheMetadataCacheHitsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataCachedTotal, c.serviceCacheMetadataCachedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheMetadataCachedTotal, data.ServiceCacheMetadataCachedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheMetadataFlushedTotal, c.serviceCacheMetadataFlushedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheMetadataFlushedTotal, data.ServiceCacheMetadataFlushedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheActiveFlushedItems, c.serviceCacheOutputCacheActiveFlushedItems,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheOutputCacheActiveFlushedItems, data.ServiceCacheOutputCacheActiveFlushedItems,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheItems, c.serviceCacheOutputCacheItems,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheOutputCacheItems, data.ServiceCacheOutputCacheItems,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheMemoryUsage, c.serviceCacheOutputCacheMemoryUsage,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheOutputCacheMemoryUsage, data.ServiceCacheOutputCacheMemoryUsage,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheQueriesTotal, c.serviceCacheOutputCacheQueriesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheOutputCacheHitsTotal+data.ServiceCacheOutputCacheMissesTotal, data.ServiceCacheOutputCacheHitsTotal+data.ServiceCacheOutputCacheMissesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheHitsTotal, c.serviceCacheOutputCacheHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheOutputCacheHitsTotal, data.ServiceCacheOutputCacheHitsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheFlushedItemsTotal, c.serviceCacheOutputCacheFlushedItemsTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.ServiceCacheOutputCacheFlushedItemsTotal, data.ServiceCacheOutputCacheFlushedItemsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.serviceCacheOutputCacheFlushesTotal, c.serviceCacheOutputCacheFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,

View File

@@ -18,16 +18,22 @@
package logical_disk package logical_disk
import ( import (
"context"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"regexp" "regexp"
"runtime"
"runtime/debug"
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-ole/go-ole"
"github.com/prometheus-community/windows_exporter/internal/headers/propsys"
"github.com/prometheus-community/windows_exporter/internal/headers/shell32"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -35,15 +41,23 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
const Name = "logical_disk" const (
Name = "logical_disk"
subCollectorMetrics = "metrics"
subCollectorBitlocker = "bitlocker_status"
)
type Config struct { type Config struct {
VolumeInclude *regexp.Regexp `yaml:"volume-include"` CollectorsEnabled []string `yaml:"enabled"`
VolumeExclude *regexp.Regexp `yaml:"volume-exclude"` VolumeInclude *regexp.Regexp `yaml:"volume-include"`
VolumeExclude *regexp.Regexp `yaml:"volume-exclude"`
} }
//nolint:gochecknoglobals //nolint:gochecknoglobals
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: []string{
subCollectorMetrics,
},
VolumeInclude: types.RegExpAny, VolumeInclude: types.RegExpAny,
VolumeExclude: types.RegExpEmpty, VolumeExclude: types.RegExpEmpty,
} }
@@ -56,6 +70,14 @@ type Collector struct {
perfDataCollector *pdh.Collector perfDataCollector *pdh.Collector
perfDataObject []perfDataCounterValues perfDataObject []perfDataCounterValues
bitlockerReqCh chan string
bitlockerResCh chan struct {
err error
status int
}
ctxCancelFunc context.CancelFunc
avgReadQueue *prometheus.Desc avgReadQueue *prometheus.Desc
avgWriteQueue *prometheus.Desc avgWriteQueue *prometheus.Desc
freeSpace *prometheus.Desc freeSpace *prometheus.Desc
@@ -74,6 +96,8 @@ type Collector struct {
writeLatency *prometheus.Desc writeLatency *prometheus.Desc
writesTotal *prometheus.Desc writesTotal *prometheus.Desc
writeTime *prometheus.Desc writeTime *prometheus.Desc
bitlockerStatus *prometheus.Desc
} }
type volumeInfo struct { type volumeInfo struct {
@@ -109,8 +133,9 @@ func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{ c := &Collector{
config: ConfigDefaults, config: ConfigDefaults,
} }
c.config.CollectorsEnabled = make([]string, 0)
var volumeExclude, volumeInclude string var collectorsEnabled, volumeExclude, volumeInclude string
app.Flag( app.Flag(
"collector.logical_disk.volume-exclude", "collector.logical_disk.volume-exclude",
@@ -122,7 +147,17 @@ func NewWithFlags(app *kingpin.Application) *Collector {
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.", "Regexp of volumes to include. Volume name must both match include and not match exclude to be included.",
).Default(".+").StringVar(&volumeInclude) ).Default(".+").StringVar(&volumeInclude)
app.Flag(
"collector.logical_disk.enabled",
fmt.Sprintf("Comma-separated list of collectors to use. Available collectors: %s, %s. Defaults to metrics, if not specified.",
subCollectorMetrics,
subCollectorBitlocker,
),
).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringVar(&collectorsEnabled)
app.Action(func(*kingpin.ParseContext) error { app.Action(func(*kingpin.ParseContext) error {
c.config.CollectorsEnabled = strings.Split(collectorsEnabled, ",")
var err error var err error
c.config.VolumeExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeExclude)) c.config.VolumeExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeExclude))
@@ -146,12 +181,24 @@ func (c *Collector) GetName() string {
} }
func (c *Collector) Close() error { func (c *Collector) Close() error {
if slices.Contains(c.config.CollectorsEnabled, subCollectorBitlocker) {
c.ctxCancelFunc()
}
return nil return nil
} }
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name)) c.logger = logger.With(slog.String("collector", Name))
for _, collector := range c.config.CollectorsEnabled {
if !slices.Contains([]string{subCollectorMetrics, subCollectorBitlocker}, collector) {
return fmt.Errorf("unknown sub collector: %s. Possible values: %s", collector,
strings.Join([]string{subCollectorMetrics, subCollectorBitlocker}, ", "),
)
}
}
c.information = prometheus.NewDesc( c.information = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"), prometheus.BuildFQName(types.Namespace, Name, "info"),
"A metric with a constant '1' value labeled with logical disk information", "A metric with a constant '1' value labeled with logical disk information",
@@ -276,6 +323,13 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
nil, nil,
) )
c.bitlockerStatus = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bitlocker_status"),
"BitLocker status for the logical disk",
[]string{"volume", "status"},
nil,
)
var err error var err error
c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "LogicalDisk", pdh.InstancesAll) c.perfDataCollector, err = pdh.NewCollector[perfDataCounterValues](pdh.CounterTypeRaw, "LogicalDisk", pdh.InstancesAll)
@@ -283,6 +337,25 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
return fmt.Errorf("failed to create LogicalDisk collector: %w", err) return fmt.Errorf("failed to create LogicalDisk collector: %w", err)
} }
if slices.Contains(c.config.CollectorsEnabled, subCollectorBitlocker) {
initErrCh := make(chan error)
c.bitlockerReqCh = make(chan string, 1)
c.bitlockerResCh = make(chan struct {
err error
status int
}, 1)
ctx, cancel := context.WithCancel(context.Background())
c.ctxCancelFunc = cancel
go c.workerBitlocker(ctx, initErrCh)
if err = <-initErrCh; err != nil {
return fmt.Errorf("failed to initialize BitLocker worker: %w", err)
}
}
return nil return nil
} }
@@ -325,117 +398,156 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
info.serialNumber, info.serialNumber,
) )
ch <- prometheus.MustNewConstMetric( if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) {
c.requestsQueued, ch <- prometheus.MustNewConstMetric(
prometheus.GaugeValue, c.requestsQueued,
data.CurrentDiskQueueLength, prometheus.GaugeValue,
data.Name, data.CurrentDiskQueueLength,
) data.Name,
)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.avgReadQueue, c.avgReadQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
data.AvgDiskReadQueueLength*pdh.TicksToSecondScaleFactor, data.AvgDiskReadQueueLength*pdh.TicksToSecondScaleFactor,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.avgWriteQueue, c.avgWriteQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
data.AvgDiskWriteQueueLength*pdh.TicksToSecondScaleFactor, data.AvgDiskWriteQueueLength*pdh.TicksToSecondScaleFactor,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.readBytesTotal, c.readBytesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.DiskReadBytesPerSec, data.DiskReadBytesPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.readsTotal, c.readsTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.DiskReadsPerSec, data.DiskReadsPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.writeBytesTotal, c.writeBytesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.DiskWriteBytesPerSec, data.DiskWriteBytesPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.writesTotal, c.writesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.DiskWritesPerSec, data.DiskWritesPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.readTime, c.readTime,
prometheus.CounterValue, prometheus.CounterValue,
data.PercentDiskReadTime, data.PercentDiskReadTime,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.writeTime, c.writeTime,
prometheus.CounterValue, prometheus.CounterValue,
data.PercentDiskWriteTime, data.PercentDiskWriteTime,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.freeSpace, c.freeSpace,
prometheus.GaugeValue, prometheus.GaugeValue,
data.FreeSpace*1024*1024, data.FreeSpace*1024*1024,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalSpace, c.totalSpace,
prometheus.GaugeValue, prometheus.GaugeValue,
data.PercentFreeSpace*1024*1024, data.PercentFreeSpace*1024*1024,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.idleTime, c.idleTime,
prometheus.CounterValue, prometheus.CounterValue,
data.PercentIdleTime, data.PercentIdleTime,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.splitIOs, c.splitIOs,
prometheus.CounterValue, prometheus.CounterValue,
data.SplitIOPerSec, data.SplitIOPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.readLatency, c.readLatency,
prometheus.CounterValue, prometheus.CounterValue,
data.AvgDiskSecPerRead*pdh.TicksToSecondScaleFactor, data.AvgDiskSecPerRead*pdh.TicksToSecondScaleFactor,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.writeLatency, c.writeLatency,
prometheus.CounterValue, prometheus.CounterValue,
data.AvgDiskSecPerWrite*pdh.TicksToSecondScaleFactor, data.AvgDiskSecPerWrite*pdh.TicksToSecondScaleFactor,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.readWriteLatency, c.readWriteLatency,
prometheus.CounterValue, prometheus.CounterValue,
data.AvgDiskSecPerTransfer*pdh.TicksToSecondScaleFactor, data.AvgDiskSecPerTransfer*pdh.TicksToSecondScaleFactor,
data.Name, data.Name,
) )
}
if slices.Contains(c.config.CollectorsEnabled, subCollectorBitlocker) {
c.bitlockerReqCh <- data.Name
bitlockerStatus := <-c.bitlockerResCh
if bitlockerStatus.err != nil {
c.logger.Warn("failed to get BitLocker status for "+data.Name,
slog.Any("err", bitlockerStatus.err),
)
continue
}
if bitlockerStatus.status == -1 {
c.logger.Debug("BitLocker status for "+data.Name+" is unknown",
slog.Int("status", bitlockerStatus.status),
)
continue
}
for i, status := range []string{"disabled", "on", "off", "encrypting", "decrypting", "suspended", "locked", "unknown", "waiting_for_activation"} {
val := 0.0
if bitlockerStatus.status == i {
val = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.bitlockerStatus,
prometheus.GaugeValue,
val,
data.Name,
status,
)
}
}
} }
return nil return nil
@@ -590,6 +702,11 @@ func getAllMountedVolumes() (map[string]string, error) {
break break
} }
if errors.Is(err, windows.ERROR_FILE_NOT_FOUND) {
// the volume is not mounted
break
}
if errors.Is(err, windows.ERROR_NO_MORE_FILES) { if errors.Is(err, windows.ERROR_NO_MORE_FILES) {
rootPathBuf = make([]uint16, (rootPathLen+1)/2) rootPathBuf = make([]uint16, (rootPathLen+1)/2)
@@ -609,3 +726,133 @@ func getAllMountedVolumes() (map[string]string, error) {
volumes[strings.TrimSuffix(mountPoint, `\`)] = strings.TrimSuffix(windows.UTF16ToString(guidBuf), `\`) volumes[strings.TrimSuffix(mountPoint, `\`)] = strings.TrimSuffix(windows.UTF16ToString(guidBuf), `\`)
} }
} }
/*
++ References
| System.Volume. | Control Panel | manage-bde conversion | manage-bde | Get-BitlockerVolume | Get-BitlockerVolume |
| BitLockerProtection | | | protection | VolumeStatus | ProtectionStatus |
| ------------------- | -------------------------------- | ------------------------- | -------------- | ---------------------------- | ------------------- |
| 1 | BitLocker on | Used Space Only Encrypted | Protection On | FullyEncrypted | On |
| 1 | BitLocker on | Fully Encrypted | Protection On | FullyEncrypted | On |
| 1 | BitLocker on | Fully Encrypted | Protection On | FullyEncryptedWipeInProgress | On |
| 2 | BitLocker off | Fully Decrypted | Protection Off | FullyDecrypted | Off |
| 3 | BitLocker Encrypting | Encryption In Progress | Protection Off | EncryptionInProgress | Off |
| 3 | BitLocker Encryption Paused | Encryption Paused | Protection Off | EncryptionSuspended | Off |
| 4 | BitLocker Decrypting | Decryption in progress | Protection Off | DecyptionInProgress | Off |
| 4 | BitLocker Decryption Paused | Decryption Paused | Protection Off | DecryptionSuspended | Off |
| 5 | BitLocker suspended | Used Space Only Encrypted | Protection Off | FullyEncrypted | Off |
| 5 | BitLocker suspended | Fully Encrypted | Protection Off | FullyEncrypted | Off |
| 6 | BitLocker on (Locked) | Unknown | Unknown | $null | Unknown |
| 7 | | | | | |
| 8 | BitLocker waiting for activation | Used Space Only Encrypted | Protection Off | FullyEncrypted | Off |
--
*/
func (c *Collector) workerBitlocker(ctx context.Context, initErrCh chan<- error) {
defer func() {
if r := recover(); r != nil {
c.logger.Error("workerBitlocker panic",
slog.Any("panic", r),
slog.String("stack", string(debug.Stack())),
)
// Restart the workerBitlocker
initErrCh := make(chan error)
go c.workerBitlocker(ctx, initErrCh)
if err := <-initErrCh; err != nil {
c.logger.Error("workerBitlocker restart failed",
slog.Any("err", err),
)
}
}
}()
// The only way to run WMI queries in parallel while being thread-safe is to
// ensure the CoInitialize[Ex]() call is bound to its current OS thread.
// Otherwise, attempting to initialize and run parallel queries across
// goroutines will result in protected memory errors.
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_DISABLE_OLE1DDE); err != nil {
var oleCode *ole.OleError
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != 0x00000001 {
initErrCh <- fmt.Errorf("CoInitializeEx: %w", err)
return
}
}
defer ole.CoUninitialize()
var pkey propsys.PROPERTYKEY
// The ideal solution to check the disk encryption (BitLocker) status is to
// use the WMI APIs (Win32_EncryptableVolume). However, only programs running
// with elevated priledges can access those APIs.
//
// Our alternative solution is based on the value of the undocumented (shell)
// property: "System.Volume.BitLockerProtection". That property is essentially
// an enum containing the current BitLocker status for a given volume. This
// approached was suggested here:
// https://stackoverflow.com/questions/41308245/detect-bitlocker-programmatically-from-c-sharp-without-admin/41310139
//
// Note that the link above doesn't give any explanation / meaning for the
// enum values, it simply says that 1, 3 or 5 means the disk is encrypted.
//
// I directly tested and validated this strategy on a Windows 10 machine.
// The values given in the BitLockerStatus enum contain the relevant values
// for the shell property. I also directly validated them.
if err := propsys.PSGetPropertyKeyFromName("System.Volume.BitLockerProtection", &pkey); err != nil {
initErrCh <- fmt.Errorf("PSGetPropertyKeyFromName failed: %w", err)
return
}
close(initErrCh)
for {
select {
case <-ctx.Done():
return
case path, ok := <-c.bitlockerReqCh:
if !ok {
return
}
if !strings.Contains(path, `:`) {
c.bitlockerResCh <- struct {
err error
status int
}{err: nil, status: -1}
continue
}
status, err := func(path string) (int, error) {
item, err := shell32.SHCreateItemFromParsingName(path)
if err != nil {
return -1, fmt.Errorf("SHCreateItemFromParsingName failed: %w", err)
}
defer item.Release()
var v ole.VARIANT
if err := item.GetProperty(&pkey, &v); err != nil {
return -1, fmt.Errorf("GetProperty failed: %w", err)
}
return int(v.Val), v.Clear()
}(path)
c.bitlockerResCh <- struct {
err error
status int
}{err: err, status: status}
}
}
}

View File

@@ -1,105 +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 logon
import (
"fmt"
"log/slog"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/secur32"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)
const Name = "logon"
type Config struct{}
//nolint:gochecknoglobals
var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI metrics.
// Deprecated: Use windows_terminal_services_session_info instead.
type Collector struct {
config Config
sessionInfo *prometheus.Desc
}
func New(config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c
}
func NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{}
}
func (c *Collector) GetName() string {
return Name
}
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
logger.Warn("The logon collector will be removed mid 2025. Use terminal_service instead."+
" See https://github.com/prometheus-community/windows_exporter/pull/1957 for more information. If you see values in this collector"+
" that you need, please open an issue to discuss how to get them into the new collector.",
slog.String("collector", Name),
)
c.sessionInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "session_logon_timestamp_seconds"),
"Deprecated. Use windows_terminal_services_session_info instead.",
[]string{"id", "username", "domain", "type"},
nil,
)
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
logonSessions, err := secur32.GetLogonSessions()
if err != nil {
return fmt.Errorf("failed to get logon sessions: %w", err)
}
for _, session := range logonSessions {
ch <- prometheus.MustNewConstMetric(
c.sessionInfo,
prometheus.GaugeValue,
float64(session.LogonTime.Unix()),
session.LogonId.String(), session.UserName, session.LogonDomain, session.LogonType.String(),
)
}
return nil
}

View File

@@ -57,14 +57,14 @@ var ConfigDefaults = Config{
// A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics. // A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics.
type Collector struct { type Collector struct {
config Config
miSession *mi.Session
collectorCluster collectorCluster
collectorNetwork collectorNetwork
collectorNode collectorNode
collectorResource collectorResource
collectorResourceGroup collectorResourceGroup
config Config
miSession *mi.Session
} }
func New(config *Config) *Collector { func New(config *Config) *Collector {

View File

@@ -20,8 +20,8 @@ package mscluster
import ( import (
"fmt" "fmt"
"github.com/Microsoft/hcsshim/osversion"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )

View File

@@ -20,8 +20,8 @@ package mscluster
import ( import (
"fmt" "fmt"
"github.com/Microsoft/hcsshim/osversion"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )

View File

@@ -265,6 +265,7 @@ func (c *Collector) collectResource(ch chan<- prometheus.Metric, nodeNames []str
if v.OwnerNode == nodeName { if v.OwnerNode == nodeName {
isCurrentState = 1.0 isCurrentState = 1.0
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.resourceOwnerNode, c.resourceOwnerNode,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -260,6 +260,7 @@ func (c *Collector) collectResourceGroup(ch chan<- prometheus.Metric, nodeNames
if v.OwnerNode == nodeName { if v.OwnerNode == nodeName {
isCurrentState = 1.0 isCurrentState = 1.0
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.resourceGroupOwnerNode, c.resourceGroupOwnerNode,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -78,18 +78,6 @@ var ConfigDefaults = Config{
// A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics. // A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics.
type Collector struct { type Collector struct {
config Config
logger *slog.Logger
mssqlInstances []mssqlInstance
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
// meta
mssqlScrapeDurationDesc *prometheus.Desc
mssqlScrapeSuccessDesc *prometheus.Desc
collectorAccessMethods collectorAccessMethods
collectorAvailabilityReplica collectorAvailabilityReplica
collectorBufferManager collectorBufferManager
@@ -103,6 +91,18 @@ type Collector struct {
collectorSQLStats collectorSQLStats
collectorTransactions collectorTransactions
collectorWaitStats collectorWaitStats
config Config
logger *slog.Logger
mssqlInstances []mssqlInstance
collectorFns []func(ch chan<- prometheus.Metric) error
closeFns []func()
// meta
mssqlScrapeDurationDesc *prometheus.Desc
mssqlScrapeSuccessDesc *prometheus.Desc
} }
func New(config *Config) *Collector { func New(config *Config) *Collector {
@@ -405,6 +405,7 @@ func (c *Collector) collect(
duration.Seconds(), duration.Seconds(),
collector, sqlInstance.name, collector, sqlInstance.name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.mssqlScrapeSuccessDesc, c.mssqlScrapeSuccessDesc,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -120,7 +120,7 @@ type perfDataCounterValuesAccessMethods struct {
AccessMethodsWorkfilesCreatedPerSec float64 `perfdata:"Workfiles Created/sec"` AccessMethodsWorkfilesCreatedPerSec float64 `perfdata:"Workfiles Created/sec"`
AccessMethodsWorktablesCreatedPerSec float64 `perfdata:"Worktables Created/sec"` AccessMethodsWorktablesCreatedPerSec float64 `perfdata:"Worktables Created/sec"`
AccessMethodsWorktablesFromCacheRatio float64 `perfdata:"Worktables From Cache Ratio"` AccessMethodsWorktablesFromCacheRatio float64 `perfdata:"Worktables From Cache Ratio"`
AccessMethodsWorktablesFromCacheRatioBase float64 `perfdata:"Worktables From Cache Base,secondvalue"` AccessMethodsWorktablesFromCacheRatioBase float64 `perfdata:"Worktables From Cache Ratio,secondvalue"`
} }
func (c *Collector) buildAccessMethods() error { func (c *Collector) buildAccessMethods() error {

View File

@@ -58,7 +58,7 @@ type collectorBufferManager struct {
type perfDataCounterValuesBufMan struct { type perfDataCounterValuesBufMan struct {
BufManBackgroundWriterPagesPerSec float64 `perfdata:"Background writer pages/sec"` BufManBackgroundWriterPagesPerSec float64 `perfdata:"Background writer pages/sec"`
BufManBufferCacheHitRatio float64 `perfdata:"Buffer cache hit ratio"` BufManBufferCacheHitRatio float64 `perfdata:"Buffer cache hit ratio"`
BufManBufferCacheHitRatioBase float64 `perfdata:"Buffer cache hit ratio base,secondvalue"` BufManBufferCacheHitRatioBase float64 `perfdata:"Buffer cache hit ratio,secondvalue"`
BufManCheckpointPagesPerSec float64 `perfdata:"Checkpoint pages/sec"` BufManCheckpointPagesPerSec float64 `perfdata:"Checkpoint pages/sec"`
BufManDatabasePages float64 `perfdata:"Database pages"` BufManDatabasePages float64 `perfdata:"Database pages"`
BufManExtensionAllocatedPages float64 `perfdata:"Extension allocated pages"` BufManExtensionAllocatedPages float64 `perfdata:"Extension allocated pages"`

View File

@@ -95,7 +95,7 @@ type perfDataCounterValuesDatabases struct {
DatabasesGroupCommitTimePerSec float64 `perfdata:"Group Commit Time/sec"` DatabasesGroupCommitTimePerSec float64 `perfdata:"Group Commit Time/sec"`
DatabasesLogBytesFlushedPerSec float64 `perfdata:"Log Bytes Flushed/sec"` DatabasesLogBytesFlushedPerSec float64 `perfdata:"Log Bytes Flushed/sec"`
DatabasesLogCacheHitRatio float64 `perfdata:"Log Cache Hit Ratio"` DatabasesLogCacheHitRatio float64 `perfdata:"Log Cache Hit Ratio"`
DatabasesLogCacheHitRatioBase float64 `perfdata:"Log Cache Hit Ratio Base,secondvalue"` DatabasesLogCacheHitRatioBase float64 `perfdata:"Log Cache Hit Ratio,secondvalue"`
DatabasesLogCacheReadsPerSec float64 `perfdata:"Log Cache Reads/sec"` DatabasesLogCacheReadsPerSec float64 `perfdata:"Log Cache Reads/sec"`
DatabasesLogFilesSizeKB float64 `perfdata:"Log File(s) Size (KB)"` DatabasesLogFilesSizeKB float64 `perfdata:"Log File(s) Size (KB)"`
DatabasesLogFilesUsedSizeKB float64 `perfdata:"Log File(s) Used Size (KB)"` DatabasesLogFilesUsedSizeKB float64 `perfdata:"Log File(s) Used Size (KB)"`

View File

@@ -18,34 +18,63 @@
package mssql package mssql
import ( import (
"fmt"
"log/slog"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows/registry"
) )
type collectorInstance struct { type collectorInstance struct {
instances *prometheus.GaugeVec instances *prometheus.Desc
} }
func (c *Collector) buildInstance() error { func (c *Collector) buildInstance() error {
c.instances = prometheus.NewGaugeVec( c.instances = prometheus.NewDesc(
prometheus.GaugeOpts{ prometheus.BuildFQName(types.Namespace, Name, "instance_info"),
Namespace: types.Namespace, "A metric with a constant '1' value labeled with mssql instance information",
Subsystem: Name,
Name: "instance_info",
Help: "A metric with a constant '1' value labeled with mssql instance information",
},
[]string{"edition", "mssql_instance", "patch", "version"}, []string{"edition", "mssql_instance", "patch", "version"},
nil,
) )
for _, instance := range c.mssqlInstances {
c.instances.WithLabelValues(instance.edition, instance.name, instance.patchVersion, instance.majorVersion.String()).Set(1)
}
return nil return nil
} }
func (c *Collector) collectInstance(ch chan<- prometheus.Metric) error { func (c *Collector) collectInstance(ch chan<- prometheus.Metric) error {
c.instances.Collect(ch) for _, instance := range c.mssqlInstances {
regKeyName := fmt.Sprintf(`Software\Microsoft\Microsoft SQL Server\%s\Setup`, instance.instanceName)
regKey, err := registry.OpenKey(registry.LOCAL_MACHINE, regKeyName, registry.QUERY_VALUE)
if err != nil {
c.logger.Debug(fmt.Sprintf("couldn't open registry %s:", regKeyName),
slog.Any("err", err),
)
continue
}
patchVersion, _, err := regKey.GetStringValue("PatchLevel")
_ = regKey.Close()
if err != nil {
c.logger.Debug("couldn't get version from registry",
slog.Any("err", err),
)
continue
}
ch <- prometheus.MustNewConstMetric(
c.instances,
prometheus.GaugeValue,
1,
instance.edition,
instance.name,
patchVersion,
instance.majorVersion.String(),
)
}
return nil return nil
} }

View File

@@ -45,7 +45,7 @@ type perfDataCounterValuesLocks struct {
Name string Name string
LocksAverageWaitTimeMS float64 `perfdata:"Average Wait Time (ms)"` LocksAverageWaitTimeMS float64 `perfdata:"Average Wait Time (ms)"`
LocksAverageWaitTimeMSBase float64 `perfdata:"Average Wait Time Base,secondvalue"` LocksAverageWaitTimeMSBase float64 `perfdata:"Average Wait Time (ms),secondvalue"`
LocksLockRequestsPerSec float64 `perfdata:"Lock Requests/sec"` LocksLockRequestsPerSec float64 `perfdata:"Lock Requests/sec"`
LocksLockTimeoutsPerSec float64 `perfdata:"Lock Timeouts/sec"` LocksLockTimeoutsPerSec float64 `perfdata:"Lock Timeouts/sec"`
LocksLockTimeoutsTimeout0PerSec float64 `perfdata:"Lock Timeouts (timeout > 0)/sec"` LocksLockTimeoutsTimeout0PerSec float64 `perfdata:"Lock Timeouts (timeout > 0)/sec"`

View File

@@ -26,8 +26,8 @@ import (
type mssqlInstance struct { type mssqlInstance struct {
name string name string
instanceName string
majorVersion mssqlServerMajorVersion majorVersion mssqlServerMajorVersion
patchVersion string
edition string edition string
isFirstInstance bool isFirstInstance bool
} }
@@ -44,7 +44,7 @@ func newMssqlInstance(key, name string) (mssqlInstance, error) {
_ = key.Close() _ = key.Close()
}(k) }(k)
patchVersion, _, err := k.GetStringValue("Version") patchVersion, _, err := k.GetStringValue("PatchLevel")
if err != nil { if err != nil {
return mssqlInstance{}, fmt.Errorf("couldn't get version from registry: %w", err) return mssqlInstance{}, fmt.Errorf("couldn't get version from registry: %w", err)
} }
@@ -54,14 +54,15 @@ func newMssqlInstance(key, name string) (mssqlInstance, error) {
return mssqlInstance{}, fmt.Errorf("couldn't get version from registry: %w", err) return mssqlInstance{}, fmt.Errorf("couldn't get version from registry: %w", err)
} }
instanceName := name
_, name, _ = strings.Cut(name, ".") _, name, _ = strings.Cut(name, ".")
return mssqlInstance{ return mssqlInstance{
edition: edition, edition: edition,
name: name, name: name,
majorVersion: newMajorVersion(patchVersion), majorVersion: newMajorVersion(patchVersion),
patchVersion: patchVersion,
isFirstInstance: key == "MSSQLSERVER", isFirstInstance: key == "MSSQLSERVER",
instanceName: instanceName,
}, nil }, nil
} }

View File

@@ -331,72 +331,84 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
data.BytesReceivedPerSec, data.BytesReceivedPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesSentTotal, c.bytesSentTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.BytesSentPerSec, data.BytesSentPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.bytesTotal, c.bytesTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.BytesTotalPerSec, data.BytesTotalPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputQueueLength, c.outputQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
data.OutputQueueLength, data.OutputQueueLength,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsOutboundDiscarded, c.packetsOutboundDiscarded,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsOutboundDiscarded, data.PacketsOutboundDiscarded,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsOutboundErrors, c.packetsOutboundErrors,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsOutboundErrors, data.PacketsOutboundErrors,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsTotal, c.packetsTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsPerSec, data.PacketsPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsReceivedDiscarded, c.packetsReceivedDiscarded,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsReceivedDiscarded, data.PacketsReceivedDiscarded,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsReceivedErrors, c.packetsReceivedErrors,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsReceivedErrors, data.PacketsReceivedErrors,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsReceivedTotal, c.packetsReceivedTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsReceivedPerSec, data.PacketsReceivedPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsReceivedUnknown, c.packetsReceivedUnknown,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsReceivedUnknown, data.PacketsReceivedUnknown,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.packetsSentTotal, c.packetsSentTotal,
prometheus.CounterValue, prometheus.CounterValue,
data.PacketsSentPerSec, data.PacketsSentPerSec,
data.Name, data.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentBandwidth, c.currentBandwidth,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -23,16 +23,13 @@ import (
"log/slog" "log/slog"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/kernel32"
"github.com/prometheus-community/windows_exporter/internal/headers/netapi32"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi" "github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry" "golang.org/x/sys/windows/registry"
) )
@@ -49,38 +46,6 @@ type Collector struct {
hostname *prometheus.Desc hostname *prometheus.Desc
osInformation *prometheus.Desc osInformation *prometheus.Desc
// users
// Deprecated: Use windows_system_process_limit instead.
processesLimit *prometheus.Desc
// users
// Deprecated: Use `sum(windows_terminal_services_session_info{state="active"})` instead.
users *prometheus.Desc
// physicalMemoryFreeBytes
// Deprecated: Use windows_memory_physical_free_bytes instead.
physicalMemoryFreeBytes *prometheus.Desc
// processMemoryLimitBytes
// Deprecated: Use windows_memory_process_memory_limit_bytes instead.
processMemoryLimitBytes *prometheus.Desc
// time
// Deprecated: Use windows_time_current_timestamp_seconds instead.
time *prometheus.Desc
// timezone
// Deprecated: Use windows_time_timezone instead.
timezone *prometheus.Desc
// virtualMemoryBytes
// Deprecated: Use windows_memory_commit_limit instead.
virtualMemoryBytes *prometheus.Desc
// virtualMemoryFreeBytes
// Deprecated: Use windows_memory_commit_limit instead.
virtualMemoryFreeBytes *prometheus.Desc
// visibleMemoryBytes
// Deprecated: Use windows_memory_physical_total_bytes instead.
visibleMemoryBytes *prometheus.Desc
} }
func New(config *Config) *Collector { func New(config *Config) *Collector {
@@ -107,21 +72,16 @@ func (c *Collector) Close() error {
return nil return nil
} }
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
logger.Warn("The os collector holds a number of deprecated metrics and will be removed mid 2025. "+
"See https://github.com/prometheus-community/windows_exporter/pull/1596 for more information.",
slog.String("collector", Name),
)
productName, revision, err := c.getWindowsVersion() productName, revision, err := c.getWindowsVersion()
if err != nil { if err != nil {
return fmt.Errorf("failed to get Windows version: %w", err) return fmt.Errorf("failed to get Windows version: %w", err)
} }
version := windows.RtlGetVersion() version := osversion.Get()
// Microsoft has decided to keep the major version as "10" for Windows 11, including the product name. // Microsoft has decided to keep the major version as "10" for Windows 11, including the product name.
if version.BuildNumber >= 22000 { if version.Build >= osversion.V21H2Win11 {
productName = strings.Replace(productName, " 10 ", " 11 ", 1) productName = strings.Replace(productName, " 10 ", " 11 ", 1)
} }
@@ -131,10 +91,10 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
nil, nil,
prometheus.Labels{ prometheus.Labels{
"product": productName, "product": productName,
"version": fmt.Sprintf("%d.%d.%d", version.MajorVersion, version.MinorVersion, version.BuildNumber), "version": version.String(),
"major_version": strconv.FormatUint(uint64(version.MajorVersion), 10), "major_version": strconv.FormatUint(uint64(version.MajorVersion), 10),
"minor_version": strconv.FormatUint(uint64(version.MinorVersion), 10), "minor_version": strconv.FormatUint(uint64(version.MinorVersion), 10),
"build_number": strconv.FormatUint(uint64(version.BuildNumber), 10), "build_number": strconv.FormatUint(uint64(version.Build), 10),
"revision": revision, "revision": revision,
}, },
) )
@@ -149,61 +109,6 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
}, },
nil, nil,
) )
c.physicalMemoryFreeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "physical_memory_free_bytes"),
"Deprecated: Use `windows_memory_physical_free_bytes` instead.",
nil,
nil,
)
c.time = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "time"),
"Deprecated: Use windows_time_current_timestamp_seconds instead.",
nil,
nil,
)
c.timezone = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "timezone"),
"Deprecated: Use windows_time_timezone instead.",
[]string{"timezone"},
nil,
)
c.processesLimit = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "processes_limit"),
"Deprecated: Use `windows_system_process_limit` instead.",
nil,
nil,
)
c.processMemoryLimitBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "process_memory_limit_bytes"),
"Deprecated: Use `windows_memory_process_memory_limit_bytes` instead.",
nil,
nil,
)
c.users = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "users"),
"Deprecated: Use `sum(windows_terminal_services_session_info{state=\"active\"})` instead.",
nil,
nil,
)
c.virtualMemoryBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_memory_bytes"),
"Deprecated: Use `windows_memory_commit_limit` instead.",
nil,
nil,
)
c.visibleMemoryBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "visible_memory_bytes"),
"Deprecated: Use `windows_memory_physical_total_bytes` instead.",
nil,
nil,
)
c.virtualMemoryFreeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "virtual_memory_free_bytes"),
"Deprecated: Use `windows_memory_commit_limit - windows_memory_committed_bytes` instead.",
nil,
nil,
)
return nil return nil
} }
@@ -213,42 +118,19 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
errs := make([]error, 0) errs := make([]error, 0)
c.collect(ch) ch <- prometheus.MustNewConstMetric(
c.osInformation,
prometheus.GaugeValue,
1.0,
)
if err := c.collectHostname(ch); err != nil { if err := c.collectHostname(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect hostname metrics: %w", err)) errs = append(errs, fmt.Errorf("failed to collect hostname metrics: %w", err))
} }
if err := c.collectLoggedInUserCount(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect user count metrics: %w", err))
}
if err := c.collectMemory(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect memory metrics: %w", err))
}
if err := c.collectTime(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect time metrics: %w", err))
}
return errors.Join(errs...) return errors.Join(errs...)
} }
func (c *Collector) collectLoggedInUserCount(ch chan<- prometheus.Metric) error {
workstationInfo, err := netapi32.GetWorkstationInfo()
if err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
c.users,
prometheus.GaugeValue,
float64(workstationInfo.LoggedOnUsers),
)
return nil
}
func (c *Collector) collectHostname(ch chan<- prometheus.Metric) error { func (c *Collector) collectHostname(ch chan<- prometheus.Metric) error {
hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname) hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname)
if err != nil { if err != nil {
@@ -277,87 +159,6 @@ func (c *Collector) collectHostname(ch chan<- prometheus.Metric) error {
return nil return nil
} }
func (c *Collector) collectTime(ch chan<- prometheus.Metric) error {
timeZoneInfo, err := kernel32.GetDynamicTimeZoneInformation()
if err != nil {
return err
}
// timeZoneKeyName contains the english name of the timezone.
timezoneName := windows.UTF16ToString(timeZoneInfo.TimeZoneKeyName[:])
ch <- prometheus.MustNewConstMetric(
c.time,
prometheus.GaugeValue,
float64(time.Now().Unix()),
)
ch <- prometheus.MustNewConstMetric(
c.timezone,
prometheus.GaugeValue,
1.0,
timezoneName,
)
return nil
}
func (c *Collector) collectMemory(ch chan<- prometheus.Metric) error {
memoryStatusEx, err := sysinfoapi.GlobalMemoryStatusEx()
if err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
c.physicalMemoryFreeBytes,
prometheus.GaugeValue,
float64(memoryStatusEx.AvailPhys),
)
ch <- prometheus.MustNewConstMetric(
c.virtualMemoryFreeBytes,
prometheus.GaugeValue,
float64(memoryStatusEx.AvailPageFile),
)
ch <- prometheus.MustNewConstMetric(
c.virtualMemoryBytes,
prometheus.GaugeValue,
float64(memoryStatusEx.TotalPageFile),
)
ch <- prometheus.MustNewConstMetric(
c.visibleMemoryBytes,
prometheus.GaugeValue,
float64(memoryStatusEx.TotalPhys),
)
ch <- prometheus.MustNewConstMetric(
c.processMemoryLimitBytes,
prometheus.GaugeValue,
float64(memoryStatusEx.TotalVirtual),
)
return nil
}
func (c *Collector) collect(ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(
c.osInformation,
prometheus.GaugeValue,
1.0,
)
// Windows has no defined limit, and is based off available resources. This currently isn't calculated by WMI and is set to default value.
// https://techcommunity.microsoft.com/t5/windows-blog-archive/pushing-the-limits-of-windows-processes-and-threads/ba-p/723824
// https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem
ch <- prometheus.MustNewConstMetric(
c.processesLimit,
prometheus.GaugeValue,
float64(4294967295),
)
}
func (c *Collector) getWindowsVersion() (string, string, error) { func (c *Collector) getWindowsVersion() (string, string, error) {
// Get build number and product name from registry // Get build number and product name from registry
ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
@@ -365,7 +166,9 @@ func (c *Collector) getWindowsVersion() (string, string, error) {
return "", "", fmt.Errorf("failed to open registry key: %w", err) return "", "", fmt.Errorf("failed to open registry key: %w", err)
} }
defer ntKey.Close() defer func(ntKey registry.Key) {
_ = ntKey.Close()
}(ntKey)
productName, _, err := ntKey.GetStringValue("ProductName") productName, _, err := ntKey.GetStringValue("ProductName")
if err != nil { if err != nil {

View File

@@ -32,7 +32,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"gopkg.in/yaml.v3" "go.yaml.in/yaml/v3"
) )
const Name = "performancecounter" const Name = "performancecounter"

View File

@@ -30,7 +30,6 @@ import (
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -208,9 +207,9 @@ windows_performancecounter_processor_information_processor_time\{core="0,0",stat
promhttp.HandlerFor(registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}).ServeHTTP(rw, &http.Request{}) promhttp.HandlerFor(registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}).ServeHTTP(rw, &http.Request{})
got := rw.Body.String() got := rw.Body.String()
assert.NotEmpty(t, got) require.NotEmpty(t, got)
require.NotEmpty(t, tc.expectedMetrics) require.NotEmpty(t, tc.expectedMetrics)
assert.Regexp(t, tc.expectedMetrics, got) require.Regexp(t, tc.expectedMetrics, got)
}) })
} }
} }

View File

@@ -19,7 +19,7 @@ package performancecounter
import ( import (
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"gopkg.in/yaml.v3" "go.yaml.in/yaml/v3"
) )
type Object struct { type Object struct {
@@ -28,7 +28,7 @@ type Object struct {
Type pdh.CounterType `json:"type" yaml:"type"` Type pdh.CounterType `json:"type" yaml:"type"`
Instances []string `json:"instances" yaml:"instances"` Instances []string `json:"instances" yaml:"instances"`
Counters []Counter `json:"counters" yaml:"counters"` Counters []Counter `json:"counters" yaml:"counters"`
InstanceLabel string `json:"instance_label" yaml:"instance_label"` //nolint:tagliatelle InstanceLabel string `json:"instance_label" yaml:"instance_label"`
collector *pdh.Collector collector *pdh.Collector
perfDataObject any perfDataObject any

View File

@@ -18,6 +18,7 @@
package process package process
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
@@ -31,6 +32,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/pdh"
"github.com/prometheus-community/windows_exporter/internal/pdh/registry" "github.com/prometheus-community/windows_exporter/internal/pdh/registry"
pdhtypes "github.com/prometheus-community/windows_exporter/internal/pdh/types"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@@ -42,6 +44,8 @@ type Config struct {
ProcessInclude *regexp.Regexp `yaml:"include"` ProcessInclude *regexp.Regexp `yaml:"include"`
ProcessExclude *regexp.Regexp `yaml:"exclude"` ProcessExclude *regexp.Regexp `yaml:"exclude"`
EnableWorkerProcess bool `yaml:"iis"` EnableWorkerProcess bool `yaml:"iis"`
EnableCMDLine bool `yaml:"cmdline"`
CounterVersion uint8 `yaml:"counter-version"`
} }
//nolint:gochecknoglobals //nolint:gochecknoglobals
@@ -49,6 +53,8 @@ var ConfigDefaults = Config{
ProcessInclude: types.RegExpAny, ProcessInclude: types.RegExpAny,
ProcessExclude: types.RegExpEmpty, ProcessExclude: types.RegExpEmpty,
EnableWorkerProcess: false, EnableWorkerProcess: false,
EnableCMDLine: true,
CounterVersion: 0,
} }
type Collector struct { type Collector struct {
@@ -59,10 +65,9 @@ type Collector struct {
miSession *mi.Session miSession *mi.Session
workerProcessMIQueryQuery mi.Query workerProcessMIQueryQuery mi.Query
collectorVersion int perfDataCollector pdhtypes.Collector
perfDataObject []perfDataCounterValues
collectorV1 workerCh chan processWorkerRequest
collectorV2
lookupCache sync.Map lookupCache sync.Map
@@ -78,8 +83,6 @@ type Collector struct {
poolBytes *prometheus.Desc poolBytes *prometheus.Desc
priorityBase *prometheus.Desc priorityBase *prometheus.Desc
privateBytes *prometheus.Desc privateBytes *prometheus.Desc
// Deprecated: Use start_time_seconds_timestamp instead
startTimeOld *prometheus.Desc
startTime *prometheus.Desc startTime *prometheus.Desc
threadCount *prometheus.Desc threadCount *prometheus.Desc
virtualBytes *prometheus.Desc virtualBytes *prometheus.Desc
@@ -130,6 +133,16 @@ func NewWithFlags(app *kingpin.Application) *Collector {
"Enable IIS collectWorker process name queries. May cause the collector to leak memory.", "Enable IIS collectWorker process name queries. May cause the collector to leak memory.",
).Default(strconv.FormatBool(c.config.EnableWorkerProcess)).BoolVar(&c.config.EnableWorkerProcess) ).Default(strconv.FormatBool(c.config.EnableWorkerProcess)).BoolVar(&c.config.EnableWorkerProcess)
app.Flag(
"collector.process.cmdline",
"If enabled, the full cmdline is exposed to the windows_process_info metrics.",
).Default(strconv.FormatBool(c.config.EnableCMDLine)).BoolVar(&c.config.EnableCMDLine)
app.Flag(
"collector.process.counter-version",
"Version of the process collector to use. 1 for Process V1, 2 for Process V2. Defaults to 0 which will use the latest version available.",
).Default(strconv.FormatUint(uint64(c.config.CounterVersion), 10)).Uint8Var(&c.config.CounterVersion)
app.Action(func(*kingpin.ParseContext) error { app.Action(func(*kingpin.ParseContext) error {
var err error var err error
@@ -157,8 +170,12 @@ func (c *Collector) Close() error {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
c.closeV1() c.perfDataCollector.Close()
c.closeV2()
if c.workerCh != nil {
close(c.workerCh)
c.workerCh = nil
}
return nil return nil
} }
@@ -166,42 +183,33 @@ func (c *Collector) Close() error {
func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error { func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
c.logger = logger.With(slog.String("collector", Name)) c.logger = logger.With(slog.String("collector", Name))
if miSession == nil { var err error
return errors.New("miSession is nil")
}
miQuery, err := mi.NewQuery("SELECT AppPoolName, ProcessId FROM WorkerProcess") switch c.config.CounterVersion {
if err != nil { case 2:
return fmt.Errorf("failed to create WMI query: %w", err) 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](pdh.CounterTypeRaw, "Process V2", pdh.InstancesAll)
c.config.CounterVersion = 2
c.workerProcessMIQueryQuery = miQuery if errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) {
c.miSession = miSession c.perfDataCollector, err = registry.NewCollector[perfDataCounterValues]("Process", pdh.InstancesAll)
c.config.CounterVersion = 1
}
c.collectorVersion = 2 c.logger.LogAttrs(context.Background(), slog.LevelDebug, fmt.Sprintf("Using process collector V%d", c.config.CounterVersion))
c.perfDataCollectorV2, err = pdh.NewCollector[perfDataCounterValuesV2](pdh.CounterTypeRaw, "Process V2", pdh.InstancesAll)
if errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) {
c.collectorVersion = 1
c.perfDataCollectorV1, err = registry.NewCollector[perfDataCounterValuesV1]("Process", pdh.InstancesAll)
} }
if err != nil { if err != nil {
return fmt.Errorf("failed to create Process collector: %w", err) return fmt.Errorf("failed to create Process V%d collector: %w", c.config.CounterVersion, err)
} }
if c.collectorVersion == 1 { c.workerCh = make(chan processWorkerRequest, 32)
c.workerChV1 = make(chan processWorkerRequestV1, 32)
for range 4 { for range 4 {
go c.collectWorkerV1() go c.collectWorker()
}
} else {
c.workerChV2 = make(chan processWorkerRequestV2, 32)
for range 4 {
go c.collectWorkerV2()
}
} }
c.mu = sync.RWMutex{} c.mu = sync.RWMutex{}
@@ -218,13 +226,6 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
nil, nil,
) )
c.startTimeOld = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "start_time"),
"DEPRECATED: Use start_time_seconds_timestamp instead",
[]string{"process", "process_id"},
nil,
)
c.startTime = prometheus.NewDesc( c.startTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "start_time_seconds_timestamp"), prometheus.BuildFQName(types.Namespace, Name, "start_time_seconds_timestamp"),
"Time of process start.", "Time of process start.",
@@ -316,22 +317,33 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
nil, nil,
) )
if c.config.EnableWorkerProcess {
if miSession == nil {
return errors.New("miSession is nil")
}
miQuery, err := mi.NewQuery("SELECT AppPoolName, ProcessId FROM WorkerProcess")
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}
c.workerProcessMIQueryQuery = miQuery
c.miSession = miSession
var workerProcesses []WorkerProcess
if err = c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
c.config.EnableWorkerProcess = false
return fmt.Errorf("WMI query for collector.process.iis failed: %w", err)
}
}
return nil return nil
} }
func (c *Collector) Collect(ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
var workerProcesses []WorkerProcess return c.collect(ch)
if c.config.EnableWorkerProcess {
if err := c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
}
if c.collectorVersion == 1 {
return c.collectV1(ch, workerProcesses)
}
return c.collectV2(ch, workerProcesses)
} }
// ref: https://github.com/microsoft/hcsshim/blob/8beabacfc2d21767a07c20f8dd5f9f3932dbf305/internal/uvm/stats.go#L25 // ref: https://github.com/microsoft/hcsshim/blob/8beabacfc2d21767a07c20f8dd5f9f3932dbf305/internal/uvm/stats.go#L25
@@ -410,19 +422,25 @@ func (c *Collector) getExtendedProcessInformation(hProcess windows.Handle) (stri
return "", 0, fmt.Errorf("failed to read process memory: %w", err) return "", 0, fmt.Errorf("failed to read process memory: %w", err)
} }
cmdLineUTF16 := make([]uint16, processParameters.CommandLine.Length) var cmdLine string
err = windows.ReadProcessMemory(hProcess, if c.config.EnableCMDLine {
uintptr(unsafe.Pointer(processParameters.CommandLine.Buffer)), cmdLineUTF16 := make([]uint16, processParameters.CommandLine.Length)
(*byte)(unsafe.Pointer(&cmdLineUTF16[0])),
uintptr(processParameters.CommandLine.Length), err = windows.ReadProcessMemory(hProcess,
nil, uintptr(unsafe.Pointer(processParameters.CommandLine.Buffer)),
) (*byte)(unsafe.Pointer(&cmdLineUTF16[0])),
if err != nil { uintptr(processParameters.CommandLine.Length),
return "", processParameters.ProcessGroupId, fmt.Errorf("failed to read process memory: %w", err) nil,
)
if err != nil {
return "", processParameters.ProcessGroupId, fmt.Errorf("failed to read process memory: %w", err)
}
cmdLine = strings.TrimSpace(windows.UTF16ToString(cmdLineUTF16))
} }
return strings.TrimSpace(windows.UTF16ToString(cmdLineUTF16)), processParameters.ProcessGroupId, nil return cmdLine, processParameters.ProcessGroupId, nil
} }
func (c *Collector) getProcessOwner(logger *slog.Logger, hProcess windows.Handle) (string, error) { func (c *Collector) getProcessOwner(logger *slog.Logger, hProcess windows.Handle) (string, error) {

View File

@@ -1,294 +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 process
import (
"context"
"fmt"
"log/slog"
"runtime/debug"
"strconv"
"strings"
"sync"
"github.com/prometheus-community/windows_exporter/internal/pdh/registry"
"github.com/prometheus/client_golang/prometheus"
)
type collectorV1 struct {
perfDataCollectorV1 *registry.Collector
perfDataObjectV1 []perfDataCounterValuesV1
workerChV1 chan processWorkerRequestV1
}
type processWorkerRequestV1 struct {
ch chan<- prometheus.Metric
name string
performanceCounterValues perfDataCounterValuesV1
waitGroup *sync.WaitGroup
workerProcesses []WorkerProcess
}
func (c *Collector) closeV1() {
c.perfDataCollectorV1.Close()
if c.workerChV1 != nil {
close(c.workerChV1)
c.workerChV1 = nil
}
}
func (c *Collector) collectV1(ch chan<- prometheus.Metric, workerProcesses []WorkerProcess) error {
err := c.perfDataCollectorV1.Collect(&c.perfDataObjectV1)
if err != nil {
return fmt.Errorf("failed to collect metrics: %w", err)
}
wg := &sync.WaitGroup{}
for _, process := range c.perfDataObjectV1 {
// Duplicate processes are suffixed #, and an index number. Remove those.
name, _, _ := strings.Cut(process.Name, ":") // Process V1
if c.config.ProcessExclude.MatchString(name) || !c.config.ProcessInclude.MatchString(name) {
continue
}
wg.Add(1)
c.workerChV1 <- processWorkerRequestV1{
ch: ch,
name: name,
performanceCounterValues: process,
workerProcesses: workerProcesses,
waitGroup: wg,
}
}
wg.Wait()
return nil
}
func (c *Collector) collectWorkerV1() {
defer func() {
if r := recover(); r != nil {
c.logger.Error("Worker panic",
slog.Any("panic", r),
slog.String("stack", string(debug.Stack())),
)
// Restart the collectWorker
go c.collectWorkerV1()
}
}()
for req := range c.workerChV1 {
(func() {
defer req.waitGroup.Done()
ch := req.ch
name := req.name
data := req.performanceCounterValues
pid := uint64(data.IdProcess)
parentPID := strconv.FormatUint(uint64(data.CreatingProcessID), 10)
if c.config.EnableWorkerProcess {
for _, wp := range req.workerProcesses {
if wp.ProcessId == pid {
name = strings.Join([]string{name, wp.AppPoolName}, "_")
break
}
}
}
cmdLine, processOwner, processGroupID, err := c.getProcessInformation(uint32(pid))
if err != nil {
slog.LogAttrs(context.Background(), slog.LevelDebug, "Failed to get process information",
slog.Uint64("pid", pid),
slog.Any("err", err),
)
}
pidString := strconv.FormatUint(pid, 10)
ch <- prometheus.MustNewConstMetric(
c.info,
prometheus.GaugeValue,
1.0,
name, pidString, parentPID, strconv.Itoa(int(processGroupID)), processOwner, cmdLine,
)
ch <- prometheus.MustNewConstMetric(
c.startTime,
prometheus.GaugeValue,
data.ElapsedTime,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.startTimeOld,
prometheus.GaugeValue,
data.ElapsedTime,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.handleCount,
prometheus.GaugeValue,
data.HandleCount,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
data.PercentPrivilegedTime,
name, pidString, "privileged",
)
ch <- prometheus.MustNewConstMetric(
c.cpuTimeTotal,
prometheus.CounterValue,
data.PercentUserTime,
name, pidString, "user",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
data.IoOtherBytesPerSec,
name, pidString, "other",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
data.IoOtherOperationsPerSec,
name, pidString, "other",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
data.IoReadBytesPerSec,
name, pidString, "read",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
data.IoReadOperationsPerSec,
name, pidString, "read",
)
ch <- prometheus.MustNewConstMetric(
c.ioBytesTotal,
prometheus.CounterValue,
data.IoWriteBytesPerSec,
name, pidString, "write",
)
ch <- prometheus.MustNewConstMetric(
c.ioOperationsTotal,
prometheus.CounterValue,
data.IoWriteOperationsPerSec,
name, pidString, "write",
)
ch <- prometheus.MustNewConstMetric(
c.pageFaultsTotal,
prometheus.CounterValue,
data.PageFaultsPerSec,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.pageFileBytes,
prometheus.GaugeValue,
data.PageFileBytes,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
data.PoolNonPagedBytes,
name, pidString, "nonpaged",
)
ch <- prometheus.MustNewConstMetric(
c.poolBytes,
prometheus.GaugeValue,
data.PoolPagedBytes,
name, pidString, "paged",
)
ch <- prometheus.MustNewConstMetric(
c.priorityBase,
prometheus.GaugeValue,
data.PriorityBase,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.privateBytes,
prometheus.GaugeValue,
data.PrivateBytes,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.threadCount,
prometheus.GaugeValue,
data.ThreadCount,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.virtualBytes,
prometheus.GaugeValue,
data.VirtualBytes,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSetPrivate,
prometheus.GaugeValue,
data.WorkingSetPrivate,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSetPeak,
prometheus.GaugeValue,
data.WorkingSetPeak,
name, pidString,
)
ch <- prometheus.MustNewConstMetric(
c.workingSet,
prometheus.GaugeValue,
data.WorkingSet,
name, pidString,
)
})()
}
}

View File

@@ -27,52 +27,59 @@ import (
"sync" "sync"
"time" "time"
"github.com/prometheus-community/windows_exporter/internal/pdh" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
type collectorV2 struct { type processWorkerRequest struct {
perfDataCollectorV2 *pdh.Collector
perfDataObjectV2 []perfDataCounterValuesV2
workerChV2 chan processWorkerRequestV2
}
type processWorkerRequestV2 struct {
ch chan<- prometheus.Metric ch chan<- prometheus.Metric
name string name string
performanceCounterValues perfDataCounterValuesV2 performanceCounterValues perfDataCounterValues
waitGroup *sync.WaitGroup waitGroup *sync.WaitGroup
workerProcesses []WorkerProcess workerProcesses []WorkerProcess
} }
func (c *Collector) closeV2() { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
c.perfDataCollectorV2.Close() err := c.perfDataCollector.Collect(&c.perfDataObject)
if c.workerChV2 != nil {
close(c.workerChV2)
c.workerChV2 = nil
}
}
func (c *Collector) collectV2(ch chan<- prometheus.Metric, workerProcesses []WorkerProcess) error {
err := c.perfDataCollectorV2.Collect(&c.perfDataObjectV2)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect metrics: %w", err) return fmt.Errorf("failed to collect metrics: %w", err)
} }
err = nil
var workerProcesses []WorkerProcess
if c.config.EnableWorkerProcess {
if err = c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
err = fmt.Errorf("WMI query for collector.process.iis failed: %w", err)
}
}
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
for _, process := range c.perfDataObjectV2 { for _, process := range c.perfDataObject {
// Duplicate processes are suffixed #, and an index number. Remove those. // Duplicate processes are suffixed #, and an index number. Remove those.
name, _, _ := strings.Cut(process.Name, ":") // Process V2 name, _, _ := strings.Cut(process.Name, ":") // Process V2
// Duplicate processes are suffixed #, and an index number. Remove those.
name, _, _ = strings.Cut(name, "#") // Process V1
if c.config.ProcessExclude.MatchString(name) || !c.config.ProcessInclude.MatchString(name) { if c.config.ProcessExclude.MatchString(name) || !c.config.ProcessInclude.MatchString(name) {
continue continue
} }
if process.ProcessID == 0 && name != "Idle" {
c.logger.LogAttrs(context.Background(), slog.LevelDebug, "Skipping process with PID 0",
slog.String("name", name),
slog.String("process_name", process.Name),
slog.Any("process", fmt.Sprintf("%+v", process)),
)
continue
}
wg.Add(1) wg.Add(1)
c.workerChV2 <- processWorkerRequestV2{ c.workerCh <- processWorkerRequest{
ch: ch, ch: ch,
name: name, name: name,
performanceCounterValues: process, performanceCounterValues: process,
@@ -83,10 +90,10 @@ func (c *Collector) collectV2(ch chan<- prometheus.Metric, workerProcesses []Wor
wg.Wait() wg.Wait()
return nil return err
} }
func (c *Collector) collectWorkerV2() { func (c *Collector) collectWorker() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
c.logger.Error("Worker panic", c.logger.Error("Worker panic",
@@ -95,11 +102,11 @@ func (c *Collector) collectWorkerV2() {
) )
// Restart the collectWorker // Restart the collectWorker
go c.collectWorkerV2() go c.collectWorker()
} }
}() }()
for req := range c.workerChV2 { for req := range c.workerCh {
(func() { (func() {
defer req.waitGroup.Done() defer req.waitGroup.Done()
@@ -137,14 +144,12 @@ func (c *Collector) collectWorkerV2() {
name, pidString, parentPID, strconv.Itoa(int(processGroupID)), processOwner, cmdLine, name, pidString, parentPID, strconv.Itoa(int(processGroupID)), processOwner, cmdLine,
) )
startTime := float64(time.Now().Unix() - int64(data.ElapsedTime)) startTime := data.ElapsedTime
if c.config.CounterVersion == 2 {
ch <- prometheus.MustNewConstMetric( // For V2, the ElapsedTime is in seconds, so we need to convert it to a timestamp.
c.startTimeOld, // The start time is the current time minus the elapsed time.
prometheus.GaugeValue, startTime = float64(time.Now().UnixMicro())/1e6 - data.ElapsedTime
startTime, }
name, pidString,
)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.startTime, c.startTime,

View File

@@ -22,7 +22,7 @@ type WorkerProcess struct {
ProcessId uint64 `mi:"ProcessId"` ProcessId uint64 `mi:"ProcessId"`
} }
type perfDataCounterValuesV1 struct { type perfDataCounterValues struct {
Name string Name string
PercentProcessorTime float64 `perfdata:"% Processor Time"` PercentProcessorTime float64 `perfdata:"% Processor Time"`
@@ -52,38 +52,5 @@ type perfDataCounterValuesV1 struct {
WorkingSetPrivate float64 `perfdata:"Working Set - Private"` WorkingSetPrivate float64 `perfdata:"Working Set - Private"`
WorkingSetPeak float64 `perfdata:"Working Set Peak"` WorkingSetPeak float64 `perfdata:"Working Set Peak"`
WorkingSet float64 `perfdata:"Working Set"` WorkingSet float64 `perfdata:"Working Set"`
IdProcess float64 `perfdata:"ID Process"` ProcessID float64 `perfdata:"Process ID" perfdata_v1:"ID Process"`
}
type perfDataCounterValuesV2 struct {
Name string
PercentProcessorTime float64 `perfdata:"% Processor Time"`
PercentPrivilegedTime float64 `perfdata:"% Privileged Time"`
PercentUserTime float64 `perfdata:"% User Time"`
CreatingProcessID float64 `perfdata:"Creating Process ID"`
ElapsedTime float64 `perfdata:"Elapsed Time"`
HandleCount float64 `perfdata:"Handle Count"`
IoDataBytesPerSec float64 `perfdata:"IO Data Bytes/sec"`
IoDataOperationsPerSec float64 `perfdata:"IO Data Operations/sec"`
IoOtherBytesPerSec float64 `perfdata:"IO Other Bytes/sec"`
IoOtherOperationsPerSec float64 `perfdata:"IO Other Operations/sec"`
IoReadBytesPerSec float64 `perfdata:"IO Read Bytes/sec"`
IoReadOperationsPerSec float64 `perfdata:"IO Read Operations/sec"`
IoWriteBytesPerSec float64 `perfdata:"IO Write Bytes/sec"`
IoWriteOperationsPerSec float64 `perfdata:"IO Write Operations/sec"`
PageFaultsPerSec float64 `perfdata:"Page Faults/sec"`
PageFileBytesPeak float64 `perfdata:"Page File Bytes Peak"`
PageFileBytes float64 `perfdata:"Page File Bytes"`
PoolNonPagedBytes float64 `perfdata:"Pool Nonpaged Bytes"`
PoolPagedBytes float64 `perfdata:"Pool Paged Bytes"`
PriorityBase float64 `perfdata:"Priority Base"`
PrivateBytes float64 `perfdata:"Private Bytes"`
ThreadCount float64 `perfdata:"Thread Count"`
VirtualBytesPeak float64 `perfdata:"Virtual Bytes Peak"`
VirtualBytes float64 `perfdata:"Virtual Bytes"`
WorkingSetPrivate float64 `perfdata:"Working Set - Private"`
WorkingSetPeak float64 `perfdata:"Working Set Peak"`
WorkingSet float64 `perfdata:"Working Set"`
ProcessID float64 `perfdata:"Process ID"`
} }

View File

@@ -280,60 +280,70 @@ func (c *Collector) collectRemoteFXNetworkCount(ch chan<- prometheus.Metric) err
utils.MilliSecToSec(data.BaseTCPRTT), utils.MilliSecToSec(data.BaseTCPRTT),
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.baseUDPRTT, c.baseUDPRTT,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.BaseUDPRTT), utils.MilliSecToSec(data.BaseUDPRTT),
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentTCPBandwidth, c.currentTCPBandwidth,
prometheus.GaugeValue, prometheus.GaugeValue,
(data.CurrentTCPBandwidth*1000)/8, (data.CurrentTCPBandwidth*1000)/8,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentTCPRTT, c.currentTCPRTT,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.CurrentTCPRTT), utils.MilliSecToSec(data.CurrentTCPRTT),
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentUDPBandwidth, c.currentUDPBandwidth,
prometheus.GaugeValue, prometheus.GaugeValue,
(data.CurrentUDPBandwidth*1000)/8, (data.CurrentUDPBandwidth*1000)/8,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.currentUDPRTT, c.currentUDPRTT,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(data.CurrentUDPRTT), utils.MilliSecToSec(data.CurrentUDPRTT),
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalReceivedBytes, c.totalReceivedBytes,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalReceivedBytes, data.TotalReceivedBytes,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.totalSentBytes, c.totalSentBytes,
prometheus.CounterValue, prometheus.CounterValue,
data.TotalSentBytes, data.TotalSentBytes,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.udpPacketsReceivedPerSec, c.udpPacketsReceivedPerSec,
prometheus.CounterValue, prometheus.CounterValue,
data.UDPPacketsReceivedPersec, data.UDPPacketsReceivedPersec,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.udpPacketsSentPerSec, c.udpPacketsSentPerSec,
prometheus.CounterValue, prometheus.CounterValue,
data.UDPPacketsSentPersec, data.UDPPacketsSentPersec,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.fecRate, c.fecRate,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -378,12 +388,14 @@ func (c *Collector) collectRemoteFXGraphicsCounters(ch chan<- prometheus.Metric)
utils.MilliSecToSec(data.AverageEncodingTime), utils.MilliSecToSec(data.AverageEncodingTime),
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.frameQuality, c.frameQuality,
prometheus.GaugeValue, prometheus.GaugeValue,
data.FrameQuality, data.FrameQuality,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.framesSkippedPerSecondInsufficientResources, c.framesSkippedPerSecondInsufficientResources,
prometheus.CounterValue, prometheus.CounterValue,
@@ -391,6 +403,7 @@ func (c *Collector) collectRemoteFXGraphicsCounters(ch chan<- prometheus.Metric)
sessionName, sessionName,
"client", "client",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.framesSkippedPerSecondInsufficientResources, c.framesSkippedPerSecondInsufficientResources,
prometheus.CounterValue, prometheus.CounterValue,
@@ -398,6 +411,7 @@ func (c *Collector) collectRemoteFXGraphicsCounters(ch chan<- prometheus.Metric)
sessionName, sessionName,
"network", "network",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.framesSkippedPerSecondInsufficientResources, c.framesSkippedPerSecondInsufficientResources,
prometheus.CounterValue, prometheus.CounterValue,
@@ -405,24 +419,28 @@ func (c *Collector) collectRemoteFXGraphicsCounters(ch chan<- prometheus.Metric)
sessionName, sessionName,
"server", "server",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.graphicsCompressionRatio, c.graphicsCompressionRatio,
prometheus.GaugeValue, prometheus.GaugeValue,
data.GraphicsCompressionratio, data.GraphicsCompressionratio,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.inputFramesPerSecond, c.inputFramesPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.InputFramesPerSecond, data.InputFramesPerSecond,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.outputFramesPerSecond, c.outputFramesPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
data.OutputFramesPerSecond, data.OutputFramesPerSecond,
sessionName, sessionName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.sourceFramesPerSecond, c.sourceFramesPerSecond,
prometheus.CounterValue, prometheus.CounterValue,

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