mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-08 05:56:37 +00:00
Compare commits
478 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05091643c6 | ||
|
|
76e73487e4 | ||
|
|
9a2ec21278 | ||
|
|
44b435e7d4 | ||
|
|
f068cf4523 | ||
|
|
9adefdceeb | ||
|
|
be9d2872a5 | ||
|
|
89cb5439b8 | ||
|
|
b08ce0697c | ||
|
|
279a8fce89 | ||
|
|
11ec45e710 | ||
|
|
6797126e78 | ||
|
|
19794ad2e0 | ||
|
|
9e59bf920f | ||
|
|
11218a95d0 | ||
|
|
9b5bc37a42 | ||
|
|
9ef897e07b | ||
|
|
3a61935273 | ||
|
|
8b9c9a5bd2 | ||
|
|
976e055252 | ||
|
|
9e368d49e7 | ||
|
|
ad1ab35399 | ||
|
|
81745eeedf | ||
|
|
fff737998d | ||
|
|
4ea61a2641 | ||
|
|
750225775b | ||
|
|
80cf16efe8 | ||
|
|
f96c6654be | ||
|
|
10e42d3583 | ||
|
|
95f250ed39 | ||
|
|
7115c9dc22 | ||
|
|
478eaa91d9 | ||
|
|
217b670272 | ||
|
|
d5e8a0ed7e | ||
|
|
8b74c77663 | ||
|
|
4077290659 | ||
|
|
014153a503 | ||
|
|
cfb0111d8c | ||
|
|
5d96a42382 | ||
|
|
6890f391d4 | ||
|
|
4350587141 | ||
|
|
8509bc69a6 | ||
|
|
e0e31254e2 | ||
|
|
c633aadc71 | ||
|
|
809424f851 | ||
|
|
88d518378c | ||
|
|
8cfd6bbcf1 | ||
|
|
4ba2fe7f22 | ||
|
|
a49a0fc612 | ||
|
|
23722ae792 | ||
|
|
731b996767 | ||
|
|
2fe869f1db | ||
|
|
6ba0297aa9 | ||
|
|
dc3e172056 | ||
|
|
4327eb386a | ||
|
|
79f4cf5dec | ||
|
|
5aae5054e6 | ||
|
|
e81231d403 | ||
|
|
0e0d0f8fd8 | ||
|
|
c1e829dbd5 | ||
|
|
434788a90a | ||
|
|
6c06beca1d | ||
|
|
486b4319c7 | ||
|
|
88847204ff | ||
|
|
79781c6d75 | ||
|
|
4cd095798d | ||
|
|
1d3af58305 | ||
|
|
b431ff6ac3 | ||
|
|
579369dbf5 | ||
|
|
f19fa777c3 | ||
|
|
0db55044e8 | ||
|
|
352492ea97 | ||
|
|
76c435d12c | ||
|
|
fab77d9d31 | ||
|
|
3627520559 | ||
|
|
b033ff71ff | ||
|
|
8d781cf540 | ||
|
|
da6898afc4 | ||
|
|
a105e088b3 | ||
|
|
30955eae17 | ||
|
|
d7b08d7ce0 | ||
|
|
05abe04d90 | ||
|
|
bacd040b17 | ||
|
|
1df91ba769 | ||
|
|
4e02053f13 | ||
|
|
535f041423 | ||
|
|
49afc93d93 | ||
|
|
04257a1b25 | ||
|
|
9214a87d0d | ||
|
|
8132083892 | ||
|
|
890fac507e | ||
|
|
b29434c7c0 | ||
|
|
7e293a4230 | ||
|
|
e21407c112 | ||
|
|
bee042d9fa | ||
|
|
6efeace169 | ||
|
|
a5b3926063 | ||
|
|
6306973948 | ||
|
|
84b6f15505 | ||
|
|
0a75d72610 | ||
|
|
549c4d1098 | ||
|
|
ea2b446130 | ||
|
|
6129a528c6 | ||
|
|
13c5bc5c95 | ||
|
|
78b11f9dc0 | ||
|
|
0dc4acac00 | ||
|
|
931c3f78d9 | ||
|
|
6a26df8069 | ||
|
|
a4404fa77a | ||
|
|
e19f80e5c7 | ||
|
|
416ccf1228 | ||
|
|
edbccbdad4 | ||
|
|
aa66719b30 | ||
|
|
b1b8c34361 | ||
|
|
9c08c916e0 | ||
|
|
b6c91bfe8c | ||
|
|
7886cf9e37 | ||
|
|
8d4c38b48e | ||
|
|
0a26661b7d | ||
|
|
864687daed | ||
|
|
c8c3cefecc | ||
|
|
12e5422845 | ||
|
|
a7960872bb | ||
|
|
94aff9fe73 | ||
|
|
9044097f2c | ||
|
|
a52ce30089 | ||
|
|
846263afee | ||
|
|
ba3cffdc79 | ||
|
|
dde839b66d | ||
|
|
ca15e2c70d | ||
|
|
0ea3bfa5c9 | ||
|
|
5331909446 | ||
|
|
e8eb77363e | ||
|
|
da2707c594 | ||
|
|
b0844b9118 | ||
|
|
27977e3730 | ||
|
|
f2f9f624b5 | ||
|
|
586152a4ad | ||
|
|
9a2ef3fca8 | ||
|
|
6912c5b1e7 | ||
|
|
f24fc07ac4 | ||
|
|
653182a90c | ||
|
|
2958e0801d | ||
|
|
f5a3cf7839 | ||
|
|
72995f4bb1 | ||
|
|
1db0dd909b | ||
|
|
cd23833ff2 | ||
|
|
20d7048478 | ||
|
|
a8fad055ac | ||
|
|
484385d387 | ||
|
|
bf181eee38 | ||
|
|
260e34394a | ||
|
|
d0c6d13e3b | ||
|
|
f10a06f908 | ||
|
|
7479946385 | ||
|
|
66a1e18c32 | ||
|
|
10078892c2 | ||
|
|
f6912cc645 | ||
|
|
c791e5212c | ||
|
|
09bc4e9e1b | ||
|
|
015b7c0666 | ||
|
|
5dda46de98 | ||
|
|
25c1449b91 | ||
|
|
29086368ac | ||
|
|
1f9d29470c | ||
|
|
1493a20262 | ||
|
|
f8c98e60db | ||
|
|
f32342400f | ||
|
|
9a73630b48 | ||
|
|
5da47255e2 | ||
|
|
eb102fd37f | ||
|
|
3aa409590f | ||
|
|
e8991095d4 | ||
|
|
3dbb37deb5 | ||
|
|
53b6816612 | ||
|
|
44b63dc23c | ||
|
|
8b8fd2d3a6 | ||
|
|
134f62511f | ||
|
|
09a83cf01f | ||
|
|
46ed47c585 | ||
|
|
187dbfc4ae | ||
|
|
6ddab61fa5 | ||
|
|
e4b8b5718f | ||
|
|
86f12b9e55 | ||
|
|
48cef00491 | ||
|
|
e9c594473c | ||
|
|
63fb570b23 | ||
|
|
cff611b60c | ||
|
|
9a262579ce | ||
|
|
25d23852d4 | ||
|
|
70dcd80f3d | ||
|
|
c3fa0039ba | ||
|
|
7a6e2d7456 | ||
|
|
68f7efec32 | ||
|
|
15b8276cf3 | ||
|
|
e01dd5e334 | ||
|
|
8f8369a356 | ||
|
|
347759933f | ||
|
|
eb73859393 | ||
|
|
3e2357fd68 | ||
|
|
677a7c8d67 | ||
|
|
8f05e77b0a | ||
|
|
8efca83ac4 | ||
|
|
fb38512f38 | ||
|
|
63800b5c6a | ||
|
|
c1b7ca42c5 | ||
|
|
f8abca5292 | ||
|
|
2ef7c5604a | ||
|
|
a0a81c4a9f | ||
|
|
8e27a9983f | ||
|
|
6d506887cd | ||
|
|
15be1c1bd6 | ||
|
|
7bd2ebc6d0 | ||
|
|
690fe8de86 | ||
|
|
46fa84f9b0 | ||
|
|
4b226cde40 | ||
|
|
cdeceaeca5 | ||
|
|
8061c4e5fa | ||
|
|
981d687e60 | ||
|
|
37ea988125 | ||
|
|
a722cee322 | ||
|
|
b43978eeb4 | ||
|
|
f02f51aceb | ||
|
|
a5f22ebb04 | ||
|
|
1c199e6c0e | ||
|
|
306197fe93 | ||
|
|
45fac2a618 | ||
|
|
716707cd06 | ||
|
|
4b0bcb46d0 | ||
|
|
55312ebdca | ||
|
|
3df660799c | ||
|
|
8ef590ee3a | ||
|
|
c9e28c4c00 | ||
|
|
c5ec339750 | ||
|
|
2602ca04f6 | ||
|
|
8fe8e85559 | ||
|
|
38cfae3e66 | ||
|
|
b2ed5f61b4 | ||
|
|
752d467b12 | ||
|
|
1fab2621eb | ||
|
|
739642bd6a | ||
|
|
a4cf96d94d | ||
|
|
1dd7b58bdf | ||
|
|
c696fb40cf | ||
|
|
ae4bc822e8 | ||
|
|
096949c682 | ||
|
|
da15c9659d | ||
|
|
a12b3e0ea0 | ||
|
|
7e7bdc104f | ||
|
|
682e6967b0 | ||
|
|
93dcdf95f7 | ||
|
|
3619d14844 | ||
|
|
9712fa3bad | ||
|
|
fe7730a51b | ||
|
|
61ea9d049c | ||
|
|
a50fe95370 | ||
|
|
33615c8b58 | ||
|
|
313ffb73bd | ||
|
|
48e54e8513 | ||
|
|
bf5177ed12 | ||
|
|
00f79ebaf4 | ||
|
|
3d50cf4309 | ||
|
|
c7cbc48afc | ||
|
|
0f304413b5 | ||
|
|
b6f12aeb9f | ||
|
|
af523f13bc | ||
|
|
8c7dd7fd5f | ||
|
|
6a186f26f0 | ||
|
|
740e277cf6 | ||
|
|
96e081c7d4 | ||
|
|
3cf0fa347f | ||
|
|
ebabddf558 | ||
|
|
4e76e6938a | ||
|
|
5f9759586e | ||
|
|
7f69cc0acf | ||
|
|
820c6bdb93 | ||
|
|
6042ea3e51 | ||
|
|
641f3222c7 | ||
|
|
9241df5528 | ||
|
|
c443eafe2b | ||
|
|
0cd6fd3f3c | ||
|
|
79a3a1ccec | ||
|
|
603cb54e8f | ||
|
|
329a96de44 | ||
|
|
fd36eae54d | ||
|
|
0dc32bf434 | ||
|
|
306e63a240 | ||
|
|
42c05df272 | ||
|
|
f471cc0e4e | ||
|
|
3c4ae95a8d | ||
|
|
21f4757b63 | ||
|
|
4aba3e1222 | ||
|
|
8f6204f960 | ||
|
|
dd494b11bb | ||
|
|
9f384e3db1 | ||
|
|
68c338b479 | ||
|
|
a01f72a8b0 | ||
|
|
09ec6e68ad | ||
|
|
5dc10096f9 | ||
|
|
1aa00ebca8 | ||
|
|
fb11263c3e | ||
|
|
9df59c75cd | ||
|
|
e112446ce9 | ||
|
|
4f82e02d8d | ||
|
|
c3ed036402 | ||
|
|
393546fe01 | ||
|
|
ca645edde1 | ||
|
|
69d4043ce4 | ||
|
|
fd5135f5ff | ||
|
|
8f08f55cf2 | ||
|
|
92d53d07b2 | ||
|
|
02e2e257c9 | ||
|
|
791df8009c | ||
|
|
aaf202236d | ||
|
|
e9ba751c82 | ||
|
|
ed83cb1c3e | ||
|
|
ac447e5b15 | ||
|
|
4d2a247e50 | ||
|
|
54f86001ad | ||
|
|
bccb3b3296 | ||
|
|
c6285cdf9d | ||
|
|
cde750f76d | ||
|
|
dedd60f02b | ||
|
|
d0c9fc6dbb | ||
|
|
f728224ef2 | ||
|
|
fba7682f01 | ||
|
|
79ecaf6a99 | ||
|
|
6941ee7ab2 | ||
|
|
5a9711dc90 | ||
|
|
5106b829c3 | ||
|
|
e1796c3d42 | ||
|
|
14d3e4ea28 | ||
|
|
36f033ae57 | ||
|
|
0de2fc4af7 | ||
|
|
b450a50103 | ||
|
|
e07b2053af | ||
|
|
7d3c0d3b76 | ||
|
|
27b2ca0b76 | ||
|
|
803a0a9a70 | ||
|
|
4891acba2d | ||
|
|
fa51270218 | ||
|
|
a68e6af15a | ||
|
|
7ad9b6d74a | ||
|
|
9acd5e695e | ||
|
|
d4be3b9f31 | ||
|
|
277f141587 | ||
|
|
2a5c51a236 | ||
|
|
ce205d4c4d | ||
|
|
2ed0ae837c | ||
|
|
57c7911c91 | ||
|
|
a56ec9166b | ||
|
|
e03432a22d | ||
|
|
be004b8423 | ||
|
|
e08a0411d6 | ||
|
|
3d7894049f | ||
|
|
de664d4b93 | ||
|
|
78e026b6ee | ||
|
|
9eba8dd024 | ||
|
|
01100d3e6e | ||
|
|
0f1eb4a936 | ||
|
|
a8eefae123 | ||
|
|
746158d354 | ||
|
|
d9f4264fc4 | ||
|
|
a89b53779d | ||
|
|
27ceeecff3 | ||
|
|
1ba5835af6 | ||
|
|
0db956aa4d | ||
|
|
9d1628a329 | ||
|
|
fc33fa320b | ||
|
|
b6f88cbbdd | ||
|
|
4b9b9e97cb | ||
|
|
3ebe0e937e | ||
|
|
4d771d2bce | ||
|
|
919f90a571 | ||
|
|
c7d07a37ea | ||
|
|
87c21bfa50 | ||
|
|
df4f6b206b | ||
|
|
9e3c585a28 | ||
|
|
e4a43c539b | ||
|
|
03e15a0f80 | ||
|
|
b98a956d51 | ||
|
|
524bfde5a3 | ||
|
|
963cee0a13 | ||
|
|
45e9357ad9 | ||
|
|
6120ea9be1 | ||
|
|
376060b053 | ||
|
|
e04c4aab29 | ||
|
|
479e6b1381 | ||
|
|
f6f7dc96e9 | ||
|
|
f84f54afda | ||
|
|
e22ef6e3cc | ||
|
|
02b69afe8b | ||
|
|
b7a0a09e58 | ||
|
|
6105792f29 | ||
|
|
1fbc626ee2 | ||
|
|
ca07abc1cd | ||
|
|
60583c3366 | ||
|
|
a7dcf5896c | ||
|
|
438cb87fc7 | ||
|
|
f8b6260ab5 | ||
|
|
d2b3f0f94b | ||
|
|
d6b4466bc3 | ||
|
|
ce3d517cb3 | ||
|
|
a6ea021468 | ||
|
|
b58dfdf4f3 | ||
|
|
676eb55f99 | ||
|
|
121d9980c1 | ||
|
|
947d8473e0 | ||
|
|
c1569686f7 | ||
|
|
75966fd37c | ||
|
|
d0cfc14af9 | ||
|
|
941b66d342 | ||
|
|
388195be97 | ||
|
|
bbefd8ac97 | ||
|
|
5b92e1bd3d | ||
|
|
82f17fd607 | ||
|
|
3e37b7b6f0 | ||
|
|
5d29ff6497 | ||
|
|
f4f5aaf146 | ||
|
|
5931604b58 | ||
|
|
67ca5e5ef2 | ||
|
|
384183120f | ||
|
|
a9ac2d4672 | ||
|
|
1b96bb6d08 | ||
|
|
cc45eeb90b | ||
|
|
4b2cd0a024 | ||
|
|
ad447a6b08 | ||
|
|
e4d7604193 | ||
|
|
757f88be04 | ||
|
|
cff484b5e1 | ||
|
|
2dc568b5cd | ||
|
|
448f505729 | ||
|
|
6d1ba11a8e | ||
|
|
0f5a232142 | ||
|
|
bbab591570 | ||
|
|
2bc3c1859a | ||
|
|
7c61a4dc25 | ||
|
|
5a57da53be | ||
|
|
72c46664db | ||
|
|
8689c41c68 | ||
|
|
74eac8f29b | ||
|
|
bb48f1caac | ||
|
|
068d03bd01 | ||
|
|
5072879dca | ||
|
|
0fb7eec670 | ||
|
|
4293497b29 | ||
|
|
95f10f19cb | ||
|
|
288f2a60e7 | ||
|
|
2e32b0e2b1 | ||
|
|
09759a4e8c | ||
|
|
dfd42a6c0c | ||
|
|
576c3bf918 | ||
|
|
19fee044bf | ||
|
|
45a74fdb7f | ||
|
|
db00553ca6 | ||
|
|
a2c4bf6a2d | ||
|
|
7adcac8f39 | ||
|
|
863b7d8ab4 | ||
|
|
33c6b2c6a5 | ||
|
|
6dee2422e1 | ||
|
|
5d224b43ca | ||
|
|
3f2a143104 | ||
|
|
ee3848141c | ||
|
|
df2a7a9ec0 | ||
|
|
05f0f6f688 | ||
|
|
d947d0f6db | ||
|
|
d063bc0842 | ||
|
|
dd473c4807 | ||
|
|
7bd58abd27 | ||
|
|
6f941044c7 | ||
|
|
3da11645cf | ||
|
|
048bff919e | ||
|
|
f76334213d | ||
|
|
71054ac429 | ||
|
|
248b7214e3 | ||
|
|
094558b1f1 | ||
|
|
18495abb69 | ||
|
|
cc709ac380 |
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
105
.github/workflows/lint.yml
vendored
Normal file
105
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
name: Linting
|
||||
|
||||
# Trigger on pull requests and pushes to master branch where Go-related files
|
||||
# have been changed.
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- "**.go"
|
||||
- ".github/workflows/lint.yml"
|
||||
- "tools/e2e-output.txt"
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
paths:
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- "**.go"
|
||||
- ".github/workflows/lint.yml"
|
||||
- "tools/e2e-output.txt"
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
PROMU_VER: '0.14.0'
|
||||
PROMTOOL_VER: '2.43.0'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.20.2'
|
||||
|
||||
- name: Test
|
||||
run: make test
|
||||
|
||||
- name: Install e2e deps
|
||||
run: |
|
||||
Invoke-WebRequest -Uri https://github.com/prometheus/promu/releases/download/v$($Env:PROMU_VER)/promu-$($Env:PROMU_VER).windows-amd64.zip -OutFile promu-$($Env:PROMU_VER).windows-amd64.zip
|
||||
Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath .
|
||||
Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin"
|
||||
|
||||
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.2.0
|
||||
# GOPATH\bin dir must be appended to PATH else the `promu` command won't be found
|
||||
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- name: e2e Test
|
||||
run: make e2e-test
|
||||
|
||||
promtool:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.20.2'
|
||||
|
||||
- name: Install promtool
|
||||
run: |
|
||||
Invoke-WebRequest -Uri https://github.com/prometheus/prometheus/releases/download/v$($Env:PROMTOOL_VER)/prometheus-$($Env:PROMTOOL_VER).windows-amd64.zip -OutFile prometheus-$($Env:PROMTOOL_VER).windows-amd64.zip
|
||||
Expand-Archive -Path prometheus-$($Env:PROMTOOL_VER).windows-amd64.zip -DestinationPath .
|
||||
Copy-Item -Path prometheus-$($Env:PROMTOOL_VER).windows-amd64\promtool.exe -Destination "$(go env GOPATH)\bin"
|
||||
|
||||
Invoke-WebRequest -Uri https://github.com/prometheus/promu/releases/download/v$($Env:PROMU_VER)/promu-$($Env:PROMU_VER).windows-amd64.zip -OutFile promu-$($Env:PROMU_VER).windows-amd64.zip
|
||||
Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath .
|
||||
Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin"
|
||||
|
||||
# No binaries available so build from source
|
||||
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.2.0
|
||||
# GOPATH\bin dir must be appended to PATH else the `promu` command won't be found
|
||||
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- name: Promtool
|
||||
run: make promtool
|
||||
|
||||
lint:
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
# `gofmt` linter run by golangci-lint fails on CRLF line endings (the default for Windows)
|
||||
- name: Set git to use LF
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.20.2'
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.51.2
|
||||
args: "--timeout=5m"
|
||||
|
||||
# golangci-lint action doesn't always provide helpful output, so re-run without the action for
|
||||
# better output of the problem.
|
||||
# The cache from the golangci-lint step is re-used here, so this step should finish quickly.
|
||||
- name: errors
|
||||
if: ${{ failure() }}
|
||||
run: golangci-lint run --timeout=5m -c .golangci.yaml
|
||||
106
.github/workflows/release.yml
vendored
Normal file
106
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
name: Releases
|
||||
|
||||
# Trigger on releases.
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
- edited
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
env:
|
||||
PROMU_VER: '0.14.0'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# fetch-depth required for gitversion in `Build` step
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.20.2'
|
||||
|
||||
- name: Install Build deps
|
||||
run: |
|
||||
dotnet tool install --global GitVersion.Tool --version 5.*
|
||||
Invoke-WebRequest -Uri https://github.com/prometheus/promu/releases/download/v$($Env:PROMU_VER)/promu-$($Env:PROMU_VER).windows-amd64.zip -OutFile promu-$($Env:PROMU_VER).windows-amd64.zip
|
||||
Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath .
|
||||
Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin"
|
||||
|
||||
# No binaries available so build from source
|
||||
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.4.0
|
||||
# GOPATH\bin dir must be added to PATH else the `promu` and `goversioninfo` commands won't be found
|
||||
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
dotnet-gitversion /output json /showvariable FullSemVer | Set-Content VERSION -PassThru
|
||||
$Version = Get-Content VERSION
|
||||
# Windows versioninfo resources need the file version by parts (but product version is free text)
|
||||
$VersionParts = ($Version -replace '^v?([0-9\.]+).*$','$1').Split(".")
|
||||
goversioninfo.exe -ver-major $VersionParts[0] -ver-minor $VersionParts[1] -ver-patch $VersionParts[2] -product-version $Version -platform-specific
|
||||
|
||||
make crossbuild
|
||||
# '+' symbols are invalid characters in image tags
|
||||
(Get-Content -Path VERSION) -replace '\+', '_' | Set-Content -Path VERSION
|
||||
make build-all
|
||||
# GH requires all files to have different names, so add version/arch to differentiate
|
||||
foreach($Arch in "amd64", "arm64","386") {
|
||||
Move-Item output\$Arch\windows_exporter.exe output\windows_exporter-$Version-$Arch.exe
|
||||
}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows_exporter_binaries
|
||||
path: output\windows_exporter-*.exe
|
||||
|
||||
- name: Build Release Artifacts
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$BuildVersion = Get-Content VERSION
|
||||
$TagName = $env:GITHUB_REF -replace 'refs/tags/', ''
|
||||
# The MSI version is not semver compliant, so just take the numerical parts
|
||||
$MSIVersion = $TagName -replace '^v?([0-9\.]+).*$','$1'
|
||||
foreach($Arch in "amd64", "386") {
|
||||
Write-Verbose "Building windows_exporter $MSIVersion msi for $Arch"
|
||||
.\installer\build.ps1 -PathToExecutable .\output\windows_exporter-$BuildVersion-$Arch.exe -Version $MSIVersion -Arch "$Arch"
|
||||
Move-Item installer\Output\windows_exporter-$MSIVersion-$Arch.msi output\
|
||||
}
|
||||
|
||||
promu checksum output\
|
||||
|
||||
- name: Login to GitHub container registry
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Push Latest image
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
$Env:VERSION = 'latest'
|
||||
make push-all
|
||||
|
||||
- name: Release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
$TagName = $env:GITHUB_REF -replace 'refs/tags/', ''
|
||||
Get-ChildItem -Path output\* -Include @('windows_exporter*.msi', 'windows_exporter*.exe', 'sha256sums.txt') | Foreach-Object {gh release upload $TagName $_}
|
||||
make push-all
|
||||
26
.github/workflows/spelling.yml
vendored
Normal file
26
.github/workflows/spelling.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Spell checking
|
||||
|
||||
# Trigger on pull requests, and pushes to master branch.
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
PROMU_VER: 'v0.14.0'
|
||||
|
||||
jobs:
|
||||
codespell:
|
||||
name: Check for spelling errors
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: codespell-project/actions-codespell@master
|
||||
with:
|
||||
check_filenames: true
|
||||
# When using this Action in other repos, the --skip option below can be removed
|
||||
skip: ./.git,go.mod,go.sum
|
||||
ignore_words_list: calle
|
||||
@@ -3,11 +3,10 @@ linters:
|
||||
enable:
|
||||
- deadcode
|
||||
- errcheck
|
||||
- golint
|
||||
- revive
|
||||
- govet
|
||||
- gofmt
|
||||
- ineffassign
|
||||
- interfacer
|
||||
- structcheck
|
||||
- unconvert
|
||||
- varcheck
|
||||
@@ -20,4 +19,7 @@ issues:
|
||||
- # Golint has many capitalisation complaints on WMI class names
|
||||
text: "`?\\w+`? should be `?\\w+`?"
|
||||
linters:
|
||||
- golint
|
||||
- revive
|
||||
- text: "don't use ALL_CAPS in Go names; use CamelCase"
|
||||
linters:
|
||||
- revive
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
go:
|
||||
version: 1.20
|
||||
repository:
|
||||
path: github.com/prometheus-community/windows_exporter
|
||||
build:
|
||||
@@ -14,5 +16,4 @@ tarball:
|
||||
- LICENSE
|
||||
crossbuild:
|
||||
platforms:
|
||||
- windows/amd64
|
||||
- windows/386
|
||||
- windows
|
||||
|
||||
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
||||
# Note this image doesn't really matter for hostprocess but it is good to build per OS version
|
||||
# the files in the image are copied to $env:CONTAINER_SANDBOX_MOUNT_POINT on the host
|
||||
# but the file system is the Host NOT the container
|
||||
ARG BASE="mcr.microsoft.com/windows/nanoserver:1809"
|
||||
FROM $BASE
|
||||
|
||||
ENV PATH="C:\Windows\system32;C:\Windows;"
|
||||
COPY output/amd64/windows_exporter.exe /windows_exporter.exe
|
||||
ENTRYPOINT ["windows_exporter.exe"]
|
||||
@@ -1,6 +1,9 @@
|
||||
Contributors in alphabetical order
|
||||
Maintainers in alphabetical order
|
||||
|
||||
* [Ben Reedy](https://github.com/breed808) - breed808@breed808.com
|
||||
* [Calle Pettersson](https://github.com/carlpett) - calle@cape.nu
|
||||
|
||||
Alumni
|
||||
|
||||
* [Ben Reedy](https://github.com/breed808)
|
||||
* [Brian Brazil](https://github.com/brian-brazil)
|
||||
* [Martin Lindhe](https://github.com/martinlindhe)
|
||||
* [Calle Pettersson](https://github.com/carlpett)
|
||||
|
||||
41
Makefile
41
Makefile
@@ -1,4 +1,15 @@
|
||||
export GOOS=windows
|
||||
export DOCKER_IMAGE_NAME ?= windows-exporter
|
||||
export DOCKER_REPO ?= ghcr.io/prometheus-community
|
||||
|
||||
VERSION?=$(shell cat VERSION)
|
||||
DOCKER?=docker
|
||||
|
||||
# Image Variables for Hostprocess Container
|
||||
# Windows image build is heavily influenced by https://github.com/kubernetes/kubernetes/blob/master/cluster/images/etcd/Makefile
|
||||
OS=1809
|
||||
ALL_OS:= 1809 ltsc2022
|
||||
BASE_IMAGE=mcr.microsoft.com/windows/nanoserver
|
||||
|
||||
.PHONY: build
|
||||
build: windows_exporter.exe
|
||||
@@ -8,12 +19,19 @@ windows_exporter.exe: **/*.go
|
||||
test:
|
||||
go test -v ./...
|
||||
|
||||
bench:
|
||||
go test -v -bench='benchmark(cpu|logicaldisk|logon|memory|net|process|service|system|tcp|time)collector' ./...
|
||||
|
||||
lint:
|
||||
golangci-lint -c .golangci.yaml run
|
||||
|
||||
.PHONY: e2e-test
|
||||
e2e-test: windows_exporter.exe
|
||||
powershell -NonInteractive -ExecutionPolicy Bypass -File .\tools\end-to-end-test.ps1
|
||||
pwsh -NonInteractive -ExecutionPolicy Bypass -File .\tools\end-to-end-test.ps1
|
||||
|
||||
.PHONY: promtool
|
||||
promtool: windows_exporter.exe
|
||||
pwsh -NonInteractive -ExecutionPolicy Bypass -File .\tools\promtool.ps1
|
||||
|
||||
fmt:
|
||||
gofmt -l -w -s .
|
||||
@@ -22,4 +40,25 @@ crossbuild:
|
||||
# The prometheus/golang-builder image for promu crossbuild doesn't exist
|
||||
# on Windows, so for now, we'll just build twice
|
||||
GOARCH=amd64 promu build --prefix=output/amd64
|
||||
GOARCH=arm64 promu build --prefix=output/arm64
|
||||
GOARCH=386 promu build --prefix=output/386
|
||||
|
||||
build-image: crossbuild
|
||||
$(DOCKER) build --build-arg=BASE=$(BASE_IMAGE):$(OS) -f Dockerfile -t $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$(OS) .
|
||||
|
||||
sub-build-%:
|
||||
$(MAKE) OS=$* build-image
|
||||
|
||||
build-all: $(addprefix sub-build-,$(ALL_OS))
|
||||
|
||||
push:
|
||||
set -x; \
|
||||
for osversion in ${ALL_OS}; do \
|
||||
$(DOCKER) push $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
|
||||
$(DOCKER) manifest create --amend $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
|
||||
full_version=`$(DOCKER) manifest inspect $(BASE_IMAGE):$${osversion} | grep "os.version" | head -n 1 | awk -F\" '{print $$4}'` || true; \
|
||||
$(DOCKER) manifest annotate --os windows --arch amd64 --os-version $${full_version} $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
|
||||
done
|
||||
$(DOCKER) manifest push --purge $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
|
||||
push-all: build-all push
|
||||
|
||||
49
README.md
49
README.md
@@ -1,6 +1,6 @@
|
||||
# windows_exporter
|
||||
|
||||
[](https://ci.appveyor.com/project/prometheus-community/windows-exporter)
|
||||

|
||||
|
||||
A Prometheus exporter for Windows machines.
|
||||
|
||||
@@ -10,6 +10,7 @@ A Prometheus exporter for Windows machines.
|
||||
Name | Description | Enabled by default
|
||||
---------|-------------|--------------------
|
||||
[ad](docs/collector.ad.md) | Active Directory Domain Services |
|
||||
[adcs](docs/collector.adcs.md) | Active Directory Certificate Services |
|
||||
[adfs](docs/collector.adfs.md) | Active Directory Federation Services |
|
||||
[cache](docs/collector.cache.md) | Cache metrics |
|
||||
[cpu](docs/collector.cpu.md) | CPU usage | ✓
|
||||
@@ -26,6 +27,11 @@ Name | Description | Enabled by default
|
||||
[logical_disk](docs/collector.logical_disk.md) | Logical disks, disk I/O | ✓
|
||||
[logon](docs/collector.logon.md) | User logon sessions |
|
||||
[memory](docs/collector.memory.md) | Memory usage metrics |
|
||||
[mscluster_cluster](docs/collector.mscluster_cluster.md) | MSCluster cluster metrics |
|
||||
[mscluster_network](docs/collector.mscluster_network.md) | MSCluster network metrics |
|
||||
[mscluster_node](docs/collector.mscluster_node.md) | MSCluster Node metrics |
|
||||
[mscluster_resource](docs/collector.mscluster_resource.md) | MSCluster Resource metrics |
|
||||
[mscluster_resourcegroup](docs/collector.mscluster_resourcegroup.md) | MSCluster ResourceGroup metrics |
|
||||
[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 |
|
||||
[netframework_clrexceptions](docs/collector.netframework_clrexceptions.md) | .NET Framework CLR Exceptions |
|
||||
@@ -40,14 +46,17 @@ Name | Description | Enabled by default
|
||||
[os](docs/collector.os.md) | OS metrics (memory, processes, users) | ✓
|
||||
[process](docs/collector.process.md) | Per-process metrics |
|
||||
[remote_fx](docs/collector.remote_fx.md) | RemoteFX protocol (RDP) metrics |
|
||||
[scheduled_task](docs/collector.scheduled_task.md) | Scheduled Tasks metrics |
|
||||
[service](docs/collector.service.md) | Service state metrics | ✓
|
||||
[smtp](docs/collector.smtp.md) | IIS SMTP Server |
|
||||
[system](docs/collector.system.md) | System calls | ✓
|
||||
[tcp](docs/collector.tcp.md) | TCP connections |
|
||||
[teradici_pcoip](docs/collector.teradici_pcoip.md) | [Teradici PCoIP](https://www.teradici.com/web-help/pcoip_wmi_specs/) session metrics |
|
||||
[time](docs/collector.time.md) | Windows Time Service |
|
||||
[thermalzone](docs/collector.thermalzone.md) | Thermal information
|
||||
[terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS)
|
||||
[textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file | ✓
|
||||
[vmware_blast](docs/collector.vmware_blast.md) | VMware Blast session metrics |
|
||||
[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.
|
||||
@@ -73,13 +82,15 @@ windows_exporter accepts flags to configure certain behaviours. The ones configu
|
||||
|
||||
Flag | Description | Default value
|
||||
---------|-------------|--------------------
|
||||
`--telemetry.addr` | host:port for exporter. | `:9182`
|
||||
`--web.listen-address` | host:port for exporter. | `:9182`
|
||||
`--telemetry.path` | URL path for surfacing collected metrics. | `/metrics`
|
||||
`--telemetry.max-requests` | Maximum number of concurrent requests. 0 to disable. | `5`
|
||||
`--collectors.enabled` | Comma-separated list of collectors to use. Use `[defaults]` as a placeholder for all the collectors enabled by default." | `[defaults]`
|
||||
`--collectors.print` | If true, print available collectors and exit. |
|
||||
`--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.print` | If true, print available collectors and exit. |
|
||||
`--scrape.timeout-margin` | Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads. | `0.5`
|
||||
`--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.insecure-skip-verify` | Skip TLS when loading config file from URL | false
|
||||
|
||||
## Installation
|
||||
The latest release can be downloaded from the [releases page](https://github.com/prometheus-community/windows_exporter/releases).
|
||||
@@ -95,7 +106,7 @@ Name | Description
|
||||
`LISTEN_PORT` | The port to bind to. Defaults to 9182.
|
||||
`METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics`
|
||||
`TEXTFILE_DIR` | As the `--collector.textfile.directory` flag, provide a directory to read text files with metrics from
|
||||
`REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (whitelist). Defaults to an empty string (any remote address).
|
||||
`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.
|
||||
|
||||
Parameters are sent to the installer via `msiexec`. Example invocations:
|
||||
@@ -114,6 +125,18 @@ On some older versions of Windows you may need to surround parameter values with
|
||||
msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,thermalzone" TEXTFILE_DIR="C:\custom_metrics\"
|
||||
```
|
||||
|
||||
Powershell versions 7.3 and above require [PSNativeCommandArgumentPassing](https://learn.microsoft.com/en-us/powershell/scripting/learn/experimental-features?view=powershell-7.3) to be set to `Legacy` when using `--% EXTRA_FLAGS`:
|
||||
|
||||
```powershell
|
||||
$PSNativeCommandArgumentPassing = 'Legacy'
|
||||
msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,service --% EXTRA_FLAGS="--collector.service.services-where ""Name LIKE 'sql%'"""
|
||||
```
|
||||
|
||||
|
||||
## Kubernetes Implementation
|
||||
|
||||
See detailed steps to install on Windows Kubernetes [here](./kubernetes/kubernetes.md).
|
||||
|
||||
## Supported versions
|
||||
|
||||
windows_exporter supports Windows Server versions 2008R2 and later, and desktop Windows version 7 and later.
|
||||
@@ -136,13 +159,25 @@ The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182
|
||||
|
||||
### Enable only process collector and specify a custom query
|
||||
|
||||
.\windows_exporter.exe --collectors.enabled "process" --collector.process.whitelist="firefox.+"
|
||||
.\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 which gets expanded with all default collectors.
|
||||
|
||||
.\windows_exporter.exe --collectors.enabled "[defaults],process,container"
|
||||
|
||||
This enables the additional process and container collectors on top of the defaults.
|
||||
|
||||
### Using a configuration file
|
||||
|
||||
YAML configuration files can be specified with the `--config.file` flag. E.G. `.\windows_exporter.exe --config.file=config.yml`
|
||||
YAML 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
|
||||
collectors:
|
||||
|
||||
84
appveyor.yml
84
appveyor.yml
@@ -1,84 +0,0 @@
|
||||
version: "{build}"
|
||||
|
||||
os: Visual Studio 2019
|
||||
build: off
|
||||
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
GO111MODULE: on
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\prometheus-community\windows_exporter
|
||||
|
||||
install:
|
||||
- mkdir %GOPATH%\bin
|
||||
- set PATH=%GOPATH%\bin;%PATH%
|
||||
- set PATH=%PATH%;C:\msys64\mingw64\bin
|
||||
- choco install gitversion.portable make -y
|
||||
- ps: |
|
||||
appveyor DownloadFile https://github.com/golangci/golangci-lint/releases/download/v1.21.0/golangci-lint-1.21.0-windows-amd64.zip
|
||||
Expand-Archive golangci-lint-1.21.0-windows-amd64.zip
|
||||
Move-Item golangci-lint-1.21.0-windows-amd64\golangci-lint-1.21.0-windows-amd64\golangci-lint.exe $env:GOPATH\bin\golangci-lint.exe
|
||||
- ps: |
|
||||
$env:GO111MODULE="off"
|
||||
go get -u github.com/prometheus/promu
|
||||
go get -u github.com/josephspurrier/goversioninfo/cmd/goversioninfo
|
||||
$env:GO111MODULE="on"
|
||||
|
||||
test_script:
|
||||
- make test
|
||||
|
||||
after_test:
|
||||
- make lint
|
||||
- make e2e-test
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
# go mod download (or, if we don't call it, go build) will write every dependent package name to
|
||||
# stderr, which will be interpreted as an error and abort the build if ErrorActionPreference is Stop,
|
||||
# so we need to run it before setting the preference.
|
||||
go mod download
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
gitversion /output json /showvariable FullSemVer | Set-Content VERSION -PassThru
|
||||
$Version = Get-Content VERSION
|
||||
# Windows versioninfo resources need the file version by parts (but product version is free text)
|
||||
$VersionParts = ($Version -replace '^v?([0-9\.]+).*$','$1').Split(".")
|
||||
goversioninfo.exe -ver-major $VersionParts[0] -ver-minor $VersionParts[1] -ver-patch $VersionParts[2] -product-version $Version -platform-specific
|
||||
|
||||
make crossbuild
|
||||
# GH requires all files to have different names, so add version/arch to differentiate
|
||||
foreach($Arch in "amd64","386") {
|
||||
Rename-Item output\$Arch\windows_exporter.exe -NewName windows_exporter-$Version-$Arch.exe
|
||||
}
|
||||
|
||||
after_build:
|
||||
- ps: |
|
||||
# Build installer packages only on tagged releases
|
||||
if($env:APPVEYOR_REPO_TAG -ne "True") {
|
||||
return
|
||||
}
|
||||
$ErrorActionPreference = "Stop"
|
||||
$BuildVersion = Get-Content VERSION
|
||||
# The MSI version is not semver compliant, so just take the numerical parts
|
||||
$MSIVersion = $env:APPVEYOR_REPO_TAG_NAME -replace '^v?([0-9\.]+).*$','$1'
|
||||
foreach($Arch in "amd64","386") {
|
||||
Write-Verbose "Building windows_exporter $MSIVersion msi for $Arch"
|
||||
.\installer\build.ps1 -PathToExecutable .\output\$Arch\windows_exporter-$BuildVersion-$Arch.exe -Version $MSIVersion -Arch "$Arch"
|
||||
Move-Item installer\Output\windows_exporter-$MSIVersion-$Arch.msi output\$Arch\
|
||||
}
|
||||
- promu checksum output\
|
||||
|
||||
artifacts:
|
||||
- name: Artifacts
|
||||
path: output\**\*
|
||||
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
description: windows_exporter version $(appveyor_build_version)
|
||||
artifact: Artifacts
|
||||
auth_token:
|
||||
secure: 'hFR7Ymxt/Rb25p4BweFvMNhX03lHD9kXJXrRlC/KbThazHuLD5NTx2ibMI6LYRsr'
|
||||
draft: false
|
||||
prerelease: false
|
||||
on:
|
||||
appveyor_repo_tag: true
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -5,17 +6,16 @@ package collector
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("ad", NewADCollector)
|
||||
}
|
||||
|
||||
// A ADCollector is a Prometheus collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics
|
||||
type ADCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
AddressBookOperationsTotal *prometheus.Desc
|
||||
AddressBookClientSessions *prometheus.Desc
|
||||
ApproximateHighestDistinguishedNameTag *prometheus.Desc
|
||||
@@ -79,10 +79,12 @@ type ADCollector struct {
|
||||
TombstonedObjectsVisitedTotal *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewADCollector ...
|
||||
func NewADCollector() (Collector, error) {
|
||||
// newADCollector ...
|
||||
func newADCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "ad"
|
||||
return &ADCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
AddressBookOperationsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "address_book_operations_total"),
|
||||
"",
|
||||
@@ -456,7 +458,7 @@ func NewADCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *ADCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting ad metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting ad metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -616,7 +618,7 @@ type Win32_PerfRawData_DirectoryServices_DirectoryServices struct {
|
||||
|
||||
func (c *ADCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_DirectoryServices_DirectoryServices
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
9
collector/ad_test.go
Normal file
9
collector/ad_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkADCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "ad", newADCollector)
|
||||
}
|
||||
244
collector/adcs.go
Normal file
244
collector/adcs.go
Normal file
@@ -0,0 +1,244 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type adcsCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
RequestsPerSecond *prometheus.Desc
|
||||
RequestProcessingTime *prometheus.Desc
|
||||
RetrievalsPerSecond *prometheus.Desc
|
||||
RetrievalProcessingTime *prometheus.Desc
|
||||
FailedRequestsPerSecond *prometheus.Desc
|
||||
IssuedRequestsPerSecond *prometheus.Desc
|
||||
PendingRequestsPerSecond *prometheus.Desc
|
||||
RequestCryptographicSigningTime *prometheus.Desc
|
||||
RequestPolicyModuleProcessingTime *prometheus.Desc
|
||||
ChallengeResponsesPerSecond *prometheus.Desc
|
||||
ChallengeResponseProcessingTime *prometheus.Desc
|
||||
SignedCertificateTimestampListsPerSecond *prometheus.Desc
|
||||
SignedCertificateTimestampListProcessingTime *prometheus.Desc
|
||||
}
|
||||
|
||||
// ADCSCollectorMethod ...
|
||||
func adcsCollectorMethod(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "adcs"
|
||||
return &adcsCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
RequestsPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "requests_total"),
|
||||
"Total certificate requests processed",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
RequestProcessingTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "request_processing_time_seconds"),
|
||||
"Last time elapsed for certificate requests",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
RetrievalsPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "retrievals_total"),
|
||||
"Total certificate retrieval requests processed",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
RetrievalProcessingTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "retrievals_processing_time_seconds"),
|
||||
"Last time elapsed for certificate retrieval request",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
FailedRequestsPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "failed_requests_total"),
|
||||
"Total failed certificate requests processed",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
IssuedRequestsPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "issued_requests_total"),
|
||||
"Total issued certificate requests processed",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
PendingRequestsPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pending_requests_total"),
|
||||
"Total pending certificate requests processed",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
RequestCryptographicSigningTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "request_cryptographic_signing_time_seconds"),
|
||||
"Last time elapsed for signing operation request",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
RequestPolicyModuleProcessingTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "request_policy_module_processing_time_seconds"),
|
||||
"Last time elapsed for policy module processing request",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
ChallengeResponsesPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "challenge_responses_total"),
|
||||
"Total certificate challenge responses processed",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
ChallengeResponseProcessingTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "challenge_response_processing_time_seconds"),
|
||||
"Last time elapsed for challenge response",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
SignedCertificateTimestampListsPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "signed_certificate_timestamp_lists_total"),
|
||||
"Total Signed Certificate Timestamp Lists processed",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
SignedCertificateTimestampListProcessingTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "signed_certificate_timestamp_list_processing_time_seconds"),
|
||||
"Last time elapsed for Signed Certificate Timestamp List",
|
||||
[]string{"cert_template"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *adcsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collectADCSCounters(ctx, ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting ADCS metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type perflibADCS struct {
|
||||
Name string
|
||||
RequestsPerSecond float64 `perflib:"Requests/sec"`
|
||||
RequestProcessingTime float64 `perflib:"Request processing time (ms)"`
|
||||
RetrievalsPerSecond float64 `perflib:"Retrievals/sec"`
|
||||
RetrievalProcessingTime float64 `perflib:"Retrieval processing time (ms)"`
|
||||
FailedRequestsPerSecond float64 `perflib:"Failed Requests/sec"`
|
||||
IssuedRequestsPerSecond float64 `perflib:"Issued Requests/sec"`
|
||||
PendingRequestsPerSecond float64 `perflib:"Pending Requests/sec"`
|
||||
RequestCryptographicSigningTime float64 `perflib:"Request cryptographic signing time (ms)"`
|
||||
RequestPolicyModuleProcessingTime float64 `perflib:"Request policy module processing time (ms)"`
|
||||
ChallengeResponsesPerSecond float64 `perflib:"Challenge Responses/sec"`
|
||||
ChallengeResponseProcessingTime float64 `perflib:"Challenge Response processing time (ms)"`
|
||||
SignedCertificateTimestampListsPerSecond float64 `perflib:"Signed Certificate Timestamp Lists/sec"`
|
||||
SignedCertificateTimestampListProcessingTime float64 `perflib:"Signed Certificate Timestamp List processing time (ms)"`
|
||||
}
|
||||
|
||||
func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
dst := make([]perflibADCS, 0)
|
||||
if _, ok := ctx.perfObjects["Certification Authority"]; !ok {
|
||||
return nil, errors.New("Perflib did not contain an entry for Certification Authority")
|
||||
}
|
||||
err := unmarshalObject(ctx.perfObjects["Certification Authority"], &dst, c.logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("Perflib query for Certification Authority (ADCS) returned empty result set")
|
||||
}
|
||||
|
||||
for _, d := range dst {
|
||||
n := strings.ToLower(d.Name)
|
||||
if n == "" {
|
||||
continue
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RequestsPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.RequestsPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RequestProcessingTime,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.RequestProcessingTime),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RetrievalsPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.RetrievalsPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RetrievalProcessingTime,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.RetrievalProcessingTime),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FailedRequestsPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.FailedRequestsPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IssuedRequestsPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.IssuedRequestsPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PendingRequestsPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.PendingRequestsPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RequestCryptographicSigningTime,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.RequestCryptographicSigningTime),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RequestPolicyModuleProcessingTime,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.RequestPolicyModuleProcessingTime),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ChallengeResponsesPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.ChallengeResponsesPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ChallengeResponseProcessingTime,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.ChallengeResponseProcessingTime),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SignedCertificateTimestampListsPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.SignedCertificateTimestampListsPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SignedCertificateTimestampListProcessingTime,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.SignedCertificateTimestampListProcessingTime),
|
||||
d.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
9
collector/adcs_test.go
Normal file
9
collector/adcs_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkADCSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "adcs", adcsCollectorMethod)
|
||||
}
|
||||
@@ -1,34 +1,70 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("adfs", newADFSCollector, "AD FS")
|
||||
}
|
||||
|
||||
type adfsCollector struct {
|
||||
adLoginConnectionFailures *prometheus.Desc
|
||||
certificateAuthentications *prometheus.Desc
|
||||
deviceAuthentications *prometheus.Desc
|
||||
extranetAccountLockouts *prometheus.Desc
|
||||
federatedAuthentications *prometheus.Desc
|
||||
passportAuthentications *prometheus.Desc
|
||||
passiveRequests *prometheus.Desc
|
||||
passwordChangeFailed *prometheus.Desc
|
||||
passwordChangeSucceeded *prometheus.Desc
|
||||
tokenRequests *prometheus.Desc
|
||||
windowsIntegratedAuthentications *prometheus.Desc
|
||||
logger log.Logger
|
||||
|
||||
adLoginConnectionFailures *prometheus.Desc
|
||||
certificateAuthentications *prometheus.Desc
|
||||
deviceAuthentications *prometheus.Desc
|
||||
extranetAccountLockouts *prometheus.Desc
|
||||
federatedAuthentications *prometheus.Desc
|
||||
passportAuthentications *prometheus.Desc
|
||||
passiveRequests *prometheus.Desc
|
||||
passwordChangeFailed *prometheus.Desc
|
||||
passwordChangeSucceeded *prometheus.Desc
|
||||
tokenRequests *prometheus.Desc
|
||||
windowsIntegratedAuthentications *prometheus.Desc
|
||||
oAuthAuthZRequests *prometheus.Desc
|
||||
oAuthClientAuthentications *prometheus.Desc
|
||||
oAuthClientAuthenticationsFailures *prometheus.Desc
|
||||
oAuthClientCredentialsRequestFailures *prometheus.Desc
|
||||
oAuthClientCredentialsRequests *prometheus.Desc
|
||||
oAuthClientPrivateKeyJwtAuthenticationFailures *prometheus.Desc
|
||||
oAuthClientPrivateKeyJwtAuthentications *prometheus.Desc
|
||||
oAuthClientSecretBasicAuthenticationFailures *prometheus.Desc
|
||||
oAuthClientSecretBasicAuthentications *prometheus.Desc
|
||||
oAuthClientSecretPostAuthenticationFailures *prometheus.Desc
|
||||
oAuthClientSecretPostAuthentications *prometheus.Desc
|
||||
oAuthClientWindowsIntegratedAuthenticationFailures *prometheus.Desc
|
||||
oAuthClientWindowsIntegratedAuthentications *prometheus.Desc
|
||||
oAuthLogonCertificateRequestFailures *prometheus.Desc
|
||||
oAuthLogonCertificateTokenRequests *prometheus.Desc
|
||||
oAuthPasswordGrantRequestFailures *prometheus.Desc
|
||||
oAuthPasswordGrantRequests *prometheus.Desc
|
||||
oAuthTokenRequests *prometheus.Desc
|
||||
samlPTokenRequests *prometheus.Desc
|
||||
ssoAuthenticationFailures *prometheus.Desc
|
||||
ssoAuthentications *prometheus.Desc
|
||||
wsfedTokenRequests *prometheus.Desc
|
||||
wstrustTokenRequests *prometheus.Desc
|
||||
upAuthenticationFailures *prometheus.Desc
|
||||
upAuthentications *prometheus.Desc
|
||||
externalAuthenticationFailures *prometheus.Desc
|
||||
externalAuthentications *prometheus.Desc
|
||||
artifactDBFailures *prometheus.Desc
|
||||
avgArtifactDBQueryTime *prometheus.Desc
|
||||
configDBFailures *prometheus.Desc
|
||||
avgConfigDBQueryTime *prometheus.Desc
|
||||
federationMetadataRequests *prometheus.Desc
|
||||
}
|
||||
|
||||
// newADFSCollector constructs a new adfsCollector
|
||||
func newADFSCollector() (Collector, error) {
|
||||
func newADFSCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "adfs"
|
||||
|
||||
return &adfsCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
adLoginConnectionFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "ad_login_connection_failures_total"),
|
||||
"Total number of connection failures to an Active Directory domain controller",
|
||||
@@ -95,26 +131,250 @@ func newADFSCollector() (Collector, error) {
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthAuthZRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_authorization_requests_total"),
|
||||
"Total number of incoming requests to the OAuth Authorization endpoint",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_authentication_success_total"),
|
||||
"Total number of successful OAuth client Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientAuthenticationsFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_authentication_failure_total"),
|
||||
"Total number of failed OAuth client Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientCredentialsRequestFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_credentials_failure_total"),
|
||||
"Total number of failed OAuth Client Credentials Requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientCredentialsRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_credentials_success_total"),
|
||||
"Total number of successful RP tokens issued for OAuth Client Credentials Requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientPrivateKeyJwtAuthenticationFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jwt_authentication_failure_total"),
|
||||
"Total number of failed OAuth Client Private Key Jwt Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientPrivateKeyJwtAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jwt_authentications_success_total"),
|
||||
"Total number of successful OAuth Client Private Key Jwt Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientSecretBasicAuthenticationFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_basic_authentications_failure_total"),
|
||||
"Total number of failed OAuth Client Secret Basic Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientSecretBasicAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_basic_authentications_success_total"),
|
||||
"Total number of successful OAuth Client Secret Basic Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientSecretPostAuthenticationFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_post_authentications_failure_total"),
|
||||
"Total number of failed OAuth Client Secret Post Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientSecretPostAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_post_authentications_success_total"),
|
||||
"Total number of successful OAuth Client Secret Post Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientWindowsIntegratedAuthenticationFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_windows_authentications_failure_total"),
|
||||
"Total number of failed OAuth Client Windows Integrated Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthClientWindowsIntegratedAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_windows_authentications_success_total"),
|
||||
"Total number of successful OAuth Client Windows Integrated Authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthLogonCertificateRequestFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_logon_certificate_requests_failure_total"),
|
||||
"Total number of failed OAuth Logon Certificate Requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthLogonCertificateTokenRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_logon_certificate_token_requests_success_total"),
|
||||
"Total number of successful RP tokens issued for OAuth Logon Certificate Requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthPasswordGrantRequestFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_password_grant_requests_failure_total"),
|
||||
"Total number of failed OAuth Password Grant Requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthPasswordGrantRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_password_grant_requests_success_total"),
|
||||
"Total number of successful OAuth Password Grant Requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
oAuthTokenRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "oauth_token_requests_success_total"),
|
||||
"Total number of successful RP tokens issued over OAuth protocol",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
samlPTokenRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "samlp_token_requests_success_total"),
|
||||
"Total number of successful RP tokens issued over SAML-P protocol",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ssoAuthenticationFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "sso_authentications_failure_total"),
|
||||
"Total number of failed SSO authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ssoAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "sso_authentications_success_total"),
|
||||
"Total number of successful SSO authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
wsfedTokenRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "wsfed_token_requests_success_total"),
|
||||
"Total number of successful RP tokens issued over WS-Fed protocol",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
wstrustTokenRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "wstrust_token_requests_success_total"),
|
||||
"Total number of successful RP tokens issued over WS-Trust protocol",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
upAuthenticationFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "userpassword_authentications_failure_total"),
|
||||
"Total number of failed AD U/P authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
upAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "userpassword_authentications_success_total"),
|
||||
"Total number of successful AD U/P authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
externalAuthenticationFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "external_authentications_failure_total"),
|
||||
"Total number of failed authentications from external MFA providers",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
externalAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "external_authentications_success_total"),
|
||||
"Total number of successful authentications from external MFA providers",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
artifactDBFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "db_artifact_failure_total"),
|
||||
"Total number of failures connecting to the artifact database",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
avgArtifactDBQueryTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "db_artifact_query_time_seconds_total"),
|
||||
"Accumulator of time taken for an artifact database query",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
configDBFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "db_config_failure_total"),
|
||||
"Total number of failures connecting to the configuration database",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
avgConfigDBQueryTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "db_config_query_time_seconds_total"),
|
||||
"Accumulator of time taken for a configuration database query",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
federationMetadataRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "federation_metadata_requests_total"),
|
||||
"Total number of Federation Metadata requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type perflibADFS struct {
|
||||
AdLoginConnectionFailures float64 `perflib:"AD login Connection Failures"`
|
||||
CertificateAuthentications float64 `perflib:"Certificate Authentications"`
|
||||
DeviceAuthentications float64 `perflib:"Device Authentications"`
|
||||
ExtranetAccountLockouts float64 `perflib:"Extranet Account Lockouts"`
|
||||
FederatedAuthentications float64 `perflib:"Federated Authentications"`
|
||||
PassportAuthentications float64 `perflib:"Microsoft Passport Authentications"`
|
||||
PassiveRequests float64 `perflib:"Passive Requests"`
|
||||
PasswordChangeFailed float64 `perflib:"Password Change Failed Requests"`
|
||||
PasswordChangeSucceeded float64 `perflib:"Password Change Successful Requests"`
|
||||
TokenRequests float64 `perflib:"Token Requests"`
|
||||
WindowsIntegratedAuthentications float64 `perflib:"Windows Integrated Authentications"`
|
||||
AdLoginConnectionFailures float64 `perflib:"AD Login Connection Failures"`
|
||||
CertificateAuthentications float64 `perflib:"Certificate Authentications"`
|
||||
DeviceAuthentications float64 `perflib:"Device Authentications"`
|
||||
ExtranetAccountLockouts float64 `perflib:"Extranet Account Lockouts"`
|
||||
FederatedAuthentications float64 `perflib:"Federated Authentications"`
|
||||
PassportAuthentications float64 `perflib:"Microsoft Passport Authentications"`
|
||||
PassiveRequests float64 `perflib:"Passive Requests"`
|
||||
PasswordChangeFailed float64 `perflib:"Password Change Failed Requests"`
|
||||
PasswordChangeSucceeded float64 `perflib:"Password Change Successful Requests"`
|
||||
TokenRequests float64 `perflib:"Token Requests"`
|
||||
WindowsIntegratedAuthentications float64 `perflib:"Windows Integrated Authentications"`
|
||||
OAuthAuthZRequests float64 `perflib:"OAuth AuthZ Requests"`
|
||||
OAuthClientAuthentications float64 `perflib:"OAuth Client Authentications"`
|
||||
OAuthClientAuthenticationFailures float64 `perflib:"OAuth Client Authentications Failures"`
|
||||
OAuthClientCredentialRequestFailures float64 `perflib:"OAuth Client Credentials Request Failures"`
|
||||
OAuthClientCredentialRequests float64 `perflib:"OAuth Client Credentials Requests"`
|
||||
OAuthClientPrivKeyJWTAuthnFailures float64 `perflib:"OAuth Client Private Key Jwt Authentication Failures"`
|
||||
OAuthClientPrivKeyJWTAuthentications float64 `perflib:"OAuth Client Private Key Jwt Authentications"`
|
||||
OAuthClientBasicAuthnFailures float64 `perflib:"OAuth Client Secret Basic Authentication Failures"`
|
||||
OAuthClientBasicAuthentications float64 `perflib:"OAuth Client Secret Basic Authentication Requests"`
|
||||
OAuthClientSecretPostAuthnFailures float64 `perflib:"OAuth Client Secret Post Authentication Failures"`
|
||||
OAuthClientSecretPostAuthentications float64 `perflib:"OAuth Client Secret Post Authentications"`
|
||||
OAuthClientWindowsAuthnFailures float64 `perflib:"OAuth Client Windows Integrated Authentication Failures"`
|
||||
OAuthClientWindowsAuthentications float64 `perflib:"OAuth Client Windows Integrated Authentications"`
|
||||
OAuthLogonCertRequestFailures float64 `perflib:"OAuth Logon Certificate Request Failures"`
|
||||
OAuthLogonCertTokenRequests float64 `perflib:"OAuth Logon Certificate Token Requests"`
|
||||
OAuthPasswordGrantRequestFailures float64 `perflib:"OAuth Password Grant Request Failures"`
|
||||
OAuthPasswordGrantRequests float64 `perflib:"OAuth Password Grant Requests"`
|
||||
OAuthTokenRequests float64 `perflib:"OAuth Token Requests"`
|
||||
SAMLPTokenRequests float64 `perflib:"SAML-P Token Requests"`
|
||||
SSOAuthenticationFailures float64 `perflib:"SSO Authentication Failures"`
|
||||
SSOAuthentications float64 `perflib:"SSO Authentications"`
|
||||
WSFedTokenRequests float64 `perflib:"WS-Fed Token Requests"`
|
||||
WSTrustTokenRequests float64 `perflib:"WS-Trust Token Requests"`
|
||||
UsernamePasswordAuthnFailures float64 `perflib:"U/P Authentication Failures"`
|
||||
UsernamePasswordAuthentications float64 `perflib:"U/P Authentications"`
|
||||
ExternalAuthentications float64 `perflib:"External Authentications"`
|
||||
ExternalAuthNFailures float64 `perflib:"External Authentication Failures"`
|
||||
ArtifactDBFailures float64 `perflib:"Artifact Database Connection Failures"`
|
||||
AvgArtifactDBQueryTime float64 `perflib:"Average Artifact Database Query Time"`
|
||||
ConfigDBFailures float64 `perflib:"Configuration Database Connection Failures"`
|
||||
AvgConfigDBQueryTime float64 `perflib:"Average Config Database Query Time"`
|
||||
FederationMetadataRequests float64 `perflib:"Federation Metadata Requests"`
|
||||
}
|
||||
|
||||
func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var adfsData []perflibADFS
|
||||
err := unmarshalObject(ctx.perfObjects["AD FS"], &adfsData)
|
||||
err := unmarshalObject(ctx.perfObjects["AD FS"], &adfsData, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -184,5 +444,197 @@ func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].WindowsIntegratedAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthAuthZRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthAuthZRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientAuthenticationsFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientAuthenticationFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientCredentialsRequestFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientCredentialRequestFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientCredentialsRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientCredentialRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientPrivateKeyJwtAuthenticationFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientPrivKeyJWTAuthnFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientPrivateKeyJwtAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientPrivKeyJWTAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientSecretBasicAuthenticationFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientBasicAuthnFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientSecretBasicAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientBasicAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientSecretPostAuthenticationFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientSecretPostAuthnFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientSecretPostAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientSecretPostAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientWindowsIntegratedAuthenticationFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientWindowsAuthnFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthClientWindowsIntegratedAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthClientWindowsAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthLogonCertificateRequestFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthLogonCertRequestFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthLogonCertificateTokenRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthLogonCertTokenRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthPasswordGrantRequestFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthPasswordGrantRequestFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthPasswordGrantRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthPasswordGrantRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.oAuthTokenRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].OAuthTokenRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.samlPTokenRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].SAMLPTokenRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ssoAuthenticationFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].SSOAuthenticationFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ssoAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].SSOAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.wsfedTokenRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].WSFedTokenRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.wstrustTokenRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].WSTrustTokenRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.upAuthenticationFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].UsernamePasswordAuthnFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.upAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].UsernamePasswordAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.externalAuthenticationFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].ExternalAuthNFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.externalAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].ExternalAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.artifactDBFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].ArtifactDBFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.avgArtifactDBQueryTime,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].AvgArtifactDBQueryTime*math.Pow(10, -8),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.configDBFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].ConfigDBFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.avgConfigDBQueryTime,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].AvgConfigDBQueryTime*math.Pow(10, -8),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.federationMetadataRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].FederationMetadataRequests,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
9
collector/adfs_test.go
Normal file
9
collector/adfs_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkADFSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "adfs", newADFSCollector)
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("cache", newCacheCollector, "Cache")
|
||||
}
|
||||
|
||||
// A CacheCollector is a Prometheus collector for Perflib Cache metrics
|
||||
type CacheCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
AsyncCopyReadsTotal *prometheus.Desc
|
||||
AsyncDataMapsTotal *prometheus.Desc
|
||||
AsyncFastReadsTotal *prometheus.Desc
|
||||
@@ -45,9 +45,11 @@ type CacheCollector struct {
|
||||
}
|
||||
|
||||
// NewCacheCollector ...
|
||||
func newCacheCollector() (Collector, error) {
|
||||
func newCacheCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "cache"
|
||||
return &CacheCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
AsyncCopyReadsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "async_copy_reads_total"),
|
||||
"(AsyncCopyReadsTotal)",
|
||||
@@ -228,7 +230,7 @@ func newCacheCollector() (Collector, error) {
|
||||
// Collect implements the Collector interface
|
||||
func (c *CacheCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting cache metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting cache metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -270,7 +272,7 @@ type perflibCache struct {
|
||||
|
||||
func (c *CacheCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []perflibCache // Single-instance class, array is required but will have single entry.
|
||||
if err := unmarshalObject(ctx.perfObjects["Cache"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["Cache"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/leoluk/perflib_exporter/perflib"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus-community/windows_exporter/perflib"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
@@ -24,33 +27,35 @@ const (
|
||||
|
||||
// getWindowsVersion reads the version number of the OS from the Registry
|
||||
// See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version
|
||||
func getWindowsVersion() float64 {
|
||||
func getWindowsVersion(logger log.Logger) float64 {
|
||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
log.Warn("Couldn't open registry", err)
|
||||
_ = level.Warn(logger).Log("msg", "Couldn't open registry", "err", err)
|
||||
return 0
|
||||
}
|
||||
defer func() {
|
||||
err = k.Close()
|
||||
if err != nil {
|
||||
log.Warnf("Failed to close registry key: %v", err)
|
||||
_ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
currentv, _, err := k.GetStringValue("CurrentVersion")
|
||||
if err != nil {
|
||||
log.Warn("Couldn't open registry to determine current Windows version:", err)
|
||||
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine current Windows version", "err", err)
|
||||
return 0
|
||||
}
|
||||
|
||||
currentv_flt, err := strconv.ParseFloat(currentv, 64)
|
||||
|
||||
log.Debugf("Detected Windows version %f\n", currentv_flt)
|
||||
_ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected Windows version %f\n", currentv_flt))
|
||||
|
||||
return currentv_flt
|
||||
}
|
||||
|
||||
type collectorBuilder func() (Collector, error)
|
||||
type collectorBuilder func(log.Logger) (Collector, error)
|
||||
type flagsBuilder func(*kingpin.Application)
|
||||
type perfCounterNamesBuilder func(log.Logger) []string
|
||||
|
||||
var (
|
||||
builders = make(map[string]collectorBuilder)
|
||||
@@ -77,12 +82,12 @@ func Available() []string {
|
||||
}
|
||||
return cs
|
||||
}
|
||||
func Build(collector string) (Collector, error) {
|
||||
func Build(collector string, logger log.Logger) (Collector, error) {
|
||||
builder, exists := builders[collector]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("Unknown collector %q", collector)
|
||||
}
|
||||
return builder()
|
||||
return builder(logger)
|
||||
}
|
||||
func getPerfQuery(collectors []string) string {
|
||||
parts := make([]string, 0, len(collectors))
|
||||
@@ -148,3 +153,7 @@ func expandEnabledChildCollectors(enabled string) []string {
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func milliSecToSec(t float64) float64 {
|
||||
return t / 1000
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ package collector
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func TestExpandChildCollectors(t *testing.T) {
|
||||
@@ -32,3 +35,27 @@ func TestExpandChildCollectors(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkCollector(b *testing.B, name string, collectFunc func(logger log.Logger) (Collector, error)) {
|
||||
// Create perflib scrape context. Some perflib collectors required a correct context,
|
||||
// or will fail during benchmark.
|
||||
scrapeContext, err := PrepareScrapeContext([]string{name})
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
c, err := collectFunc(log.NewNopLogger())
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
|
||||
metrics := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
for {
|
||||
<-metrics
|
||||
}
|
||||
}()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Collect(scrapeContext, metrics) //nolint:errcheck
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("container", NewContainerMetricsCollector)
|
||||
}
|
||||
|
||||
// A ContainerMetricsCollector is a Prometheus collector for containers metrics
|
||||
type ContainerMetricsCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
// Presence
|
||||
ContainerAvailable *prometheus.Desc
|
||||
|
||||
@@ -36,12 +39,20 @@ type ContainerMetricsCollector struct {
|
||||
PacketsSent *prometheus.Desc
|
||||
DroppedPacketsIncoming *prometheus.Desc
|
||||
DroppedPacketsOutgoing *prometheus.Desc
|
||||
|
||||
// Storage
|
||||
ReadCountNormalized *prometheus.Desc
|
||||
ReadSizeBytes *prometheus.Desc
|
||||
WriteCountNormalized *prometheus.Desc
|
||||
WriteSizeBytes *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewContainerMetricsCollector constructs a new ContainerMetricsCollector
|
||||
func NewContainerMetricsCollector() (Collector, error) {
|
||||
// newContainerMetricsCollector constructs a new ContainerMetricsCollector
|
||||
func newContainerMetricsCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "container"
|
||||
return &ContainerMetricsCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
ContainerAvailable: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "available"),
|
||||
"Available",
|
||||
@@ -126,6 +137,30 @@ func NewContainerMetricsCollector() (Collector, error) {
|
||||
[]string{"container_id", "interface"},
|
||||
nil,
|
||||
),
|
||||
ReadCountNormalized: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "storage_read_count_normalized_total"),
|
||||
"Read Count Normalized",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
ReadSizeBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "storage_read_size_bytes_total"),
|
||||
"Read Size Bytes",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
WriteCountNormalized: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "storage_write_count_normalized_total"),
|
||||
"Write Count Normalized",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
WriteSizeBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "storage_write_size_bytes_total"),
|
||||
"Write Size Bytes",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -133,17 +168,17 @@ func NewContainerMetricsCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *ContainerMetricsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting ContainerMetricsCollector metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting ContainerMetricsCollector metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// containerClose closes the container resource
|
||||
func containerClose(c hcsshim.Container) {
|
||||
err := c.Close()
|
||||
func (c *ContainerMetricsCollector) containerClose(container hcsshim.Container) {
|
||||
err := container.Close()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
_ = level.Error(c.logger).Log("err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +187,7 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
|
||||
// Types Container is passed to get the containers compute systems only
|
||||
containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}})
|
||||
if err != nil {
|
||||
log.Error("Err in Getting containers:", err)
|
||||
_ = level.Error(c.logger).Log("msg", "Err in Getting containers", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -167,22 +202,26 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
containerPrefixes := make(map[string]string)
|
||||
|
||||
for _, containerDetails := range containers {
|
||||
container, err := hcsshim.OpenContainer(containerDetails.ID)
|
||||
if container != nil {
|
||||
defer containerClose(container)
|
||||
defer c.containerClose(container)
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("err in opening container: ", containerDetails.ID, err)
|
||||
_ = level.Error(c.logger).Log("msg", "err in opening container", "containerId", containerDetails.ID, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
cstats, err := container.Statistics()
|
||||
if err != nil {
|
||||
log.Error("err in fetching container Statistics: ", containerDetails.ID, err)
|
||||
_ = level.Error(c.logger).Log("msg", "err in fetching container Statistics", "containerId", containerDetails.ID, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
containerIdWithPrefix := getContainerIdWithPrefix(containerDetails)
|
||||
containerPrefixes[containerDetails.ID] = containerIdWithPrefix
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ContainerAvailable,
|
||||
@@ -226,52 +265,96 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
|
||||
float64(cstats.Processor.RuntimeKernel100ns)*ticksToSecondsScaleFactor,
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadCountNormalized,
|
||||
prometheus.CounterValue,
|
||||
float64(cstats.Storage.ReadCountNormalized),
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadSizeBytes,
|
||||
prometheus.CounterValue,
|
||||
float64(cstats.Storage.ReadSizeBytes),
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WriteCountNormalized,
|
||||
prometheus.CounterValue,
|
||||
float64(cstats.Storage.WriteCountNormalized),
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WriteSizeBytes,
|
||||
prometheus.CounterValue,
|
||||
float64(cstats.Storage.WriteSizeBytes),
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
}
|
||||
|
||||
if len(cstats.Network) == 0 {
|
||||
log.Info("No Network Stats for container: ", containerDetails.ID)
|
||||
hnsEndpoints, err := hcsshim.HNSListEndpointRequest()
|
||||
if err != nil {
|
||||
_ = level.Warn(c.logger).Log("msg", "Failed to collect network stats for containers")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if len(hnsEndpoints) == 0 {
|
||||
_ = level.Info(c.logger).Log("msg", fmt.Sprintf("No network stats for containers to collect"))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, endpoint := range hnsEndpoints {
|
||||
endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id)
|
||||
if err != nil {
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for interface %s", endpoint.Id), "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
networkStats := cstats.Network
|
||||
for _, containerId := range endpoint.SharedContainers {
|
||||
containerIdWithPrefix, ok := containerPrefixes[containerId]
|
||||
endpointId := strings.ToUpper(endpoint.Id)
|
||||
|
||||
if !ok {
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for container %s", containerId))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, networkInterface := range networkStats {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.BytesReceived),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
float64(endpointStats.BytesReceived),
|
||||
containerIdWithPrefix, endpointId,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesSent,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.BytesSent),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
float64(endpointStats.BytesSent),
|
||||
containerIdWithPrefix, endpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.PacketsReceived),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
float64(endpointStats.PacketsReceived),
|
||||
containerIdWithPrefix, endpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsSent,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.PacketsSent),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
float64(endpointStats.PacketsSent),
|
||||
containerIdWithPrefix, endpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DroppedPacketsIncoming,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.DroppedPacketsIncoming),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
float64(endpointStats.DroppedPacketsIncoming),
|
||||
containerIdWithPrefix, endpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DroppedPacketsOutgoing,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.DroppedPacketsOutgoing),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
float64(endpointStats.DroppedPacketsOutgoing),
|
||||
containerIdWithPrefix, endpointId,
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
9
collector/container_test.go
Normal file
9
collector/container_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkContainerCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "container", newContainerMetricsCollector)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -5,27 +6,21 @@ package collector
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
var deps string
|
||||
// See below for 6.05 magic value
|
||||
if getWindowsVersion() > 6.05 {
|
||||
deps = "Processor Information"
|
||||
} else {
|
||||
deps = "Processor"
|
||||
}
|
||||
registerCollector("cpu", newCPUCollector, deps)
|
||||
}
|
||||
|
||||
type cpuCollectorBasic struct {
|
||||
logger log.Logger
|
||||
|
||||
CStateSecondsTotal *prometheus.Desc
|
||||
TimeTotal *prometheus.Desc
|
||||
InterruptsTotal *prometheus.Desc
|
||||
DPCsTotal *prometheus.Desc
|
||||
}
|
||||
type cpuCollectorFull struct {
|
||||
logger log.Logger
|
||||
|
||||
CStateSecondsTotal *prometheus.Desc
|
||||
TimeTotal *prometheus.Desc
|
||||
InterruptsTotal *prometheus.Desc
|
||||
@@ -36,13 +31,18 @@ type cpuCollectorFull struct {
|
||||
ProcessorFrequencyMHz *prometheus.Desc
|
||||
ProcessorMaxFrequencyMHz *prometheus.Desc
|
||||
ProcessorPerformance *prometheus.Desc
|
||||
ProcessorMPerf *prometheus.Desc
|
||||
ProcessorRTC *prometheus.Desc
|
||||
ProcessorUtility *prometheus.Desc
|
||||
ProcessorPrivUtility *prometheus.Desc
|
||||
}
|
||||
|
||||
// newCPUCollector constructs a new cpuCollector, appropriate for the running OS
|
||||
func newCPUCollector() (Collector, error) {
|
||||
func newCPUCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "cpu"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
version := getWindowsVersion()
|
||||
version := getWindowsVersion(logger)
|
||||
// For Windows 2008 (version 6.0) or earlier we only have the "Processor"
|
||||
// class. As of Windows 2008 R2 (version 6.1) the more detailed
|
||||
// "Processor Information" set is available (although some of the counters
|
||||
@@ -51,6 +51,7 @@ func newCPUCollector() (Collector, error) {
|
||||
// Value 6.05 was selected to split between Windows versions.
|
||||
if version < 6.05 {
|
||||
return &cpuCollectorBasic{
|
||||
logger: logger,
|
||||
CStateSecondsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"),
|
||||
"Time spent in low-power idle state",
|
||||
@@ -59,7 +60,7 @@ func newCPUCollector() (Collector, error) {
|
||||
),
|
||||
TimeTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "time_total"),
|
||||
"Time that processor spent in different modes (idle, user, system, ...)",
|
||||
"Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)",
|
||||
[]string{"core", "mode"},
|
||||
nil,
|
||||
),
|
||||
@@ -79,6 +80,7 @@ func newCPUCollector() (Collector, error) {
|
||||
}
|
||||
|
||||
return &cpuCollectorFull{
|
||||
logger: logger,
|
||||
CStateSecondsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"),
|
||||
"Time spent in low-power idle state",
|
||||
@@ -87,7 +89,7 @@ func newCPUCollector() (Collector, error) {
|
||||
),
|
||||
TimeTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "time_total"),
|
||||
"Time that processor spent in different modes (idle, user, system, ...)",
|
||||
"Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)",
|
||||
[]string{"core", "mode"},
|
||||
nil,
|
||||
),
|
||||
@@ -128,11 +130,35 @@ func newCPUCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
ProcessorPerformance: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_performance"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_performance_total"),
|
||||
"Processor Performance is the average performance of the processor while it is executing instructions, as a percentage of the nominal performance of the processor. On some processors, Processor Performance may exceed 100%",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
ProcessorMPerf: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_mperf_total"),
|
||||
"Processor MPerf is the number of TSC ticks incremented while executing instructions",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
ProcessorRTC: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_rtc_total"),
|
||||
"Processor RTC represents the number of RTC ticks made since the system booted. It should consistently be 64e6, and can be used to properly derive Processor Utility Rate",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
ProcessorUtility: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_utility_total"),
|
||||
"Processor Utility represents is the amount of time the core spends executing instructions",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
ProcessorPrivUtility: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_privileged_utility_total"),
|
||||
"Processor Privilieged Utility represents is the amount of time the core has spent executing instructions inside the kernel",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -157,7 +183,7 @@ type perflibProcessor struct {
|
||||
|
||||
func (c *cpuCollectorBasic) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
data := make([]perflibProcessor, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Processor"], &data)
|
||||
err := unmarshalObject(ctx.perfObjects["Processor"], &data, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -257,14 +283,16 @@ type perflibProcessorInformation struct {
|
||||
PrivilegedUtilitySeconds float64 `perflib:"% Privileged Utility"`
|
||||
ProcessorFrequencyMHz float64 `perflib:"Processor Frequency"`
|
||||
ProcessorPerformance float64 `perflib:"% Processor Performance"`
|
||||
ProcessorMPerf float64 `perflib:"% Processor Performance,secondvalue"`
|
||||
ProcessorTimeSeconds float64 `perflib:"% Processor Time"`
|
||||
ProcessorUtilityRate float64 `perflib:"% Processor Utility"`
|
||||
ProcessorRTC float64 `perflib:"% Processor Utility,secondvalue"`
|
||||
UserTimeSeconds float64 `perflib:"% User Time"`
|
||||
}
|
||||
|
||||
func (c *cpuCollectorFull) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
data := make([]perflibProcessorInformation, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Processor Information"], &data)
|
||||
err := unmarshalObject(ctx.perfObjects["Processor Information"], &data, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -365,10 +393,34 @@ func (c *cpuCollectorFull) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessorPerformance,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
cpu.ProcessorPerformance,
|
||||
core,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessorMPerf,
|
||||
prometheus.CounterValue,
|
||||
cpu.ProcessorMPerf,
|
||||
core,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessorRTC,
|
||||
prometheus.CounterValue,
|
||||
cpu.ProcessorRTC,
|
||||
core,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessorUtility,
|
||||
prometheus.CounterValue,
|
||||
cpu.ProcessorUtilityRate,
|
||||
core,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessorPrivUtility,
|
||||
prometheus.CounterValue,
|
||||
cpu.PrivilegedUtilitySeconds,
|
||||
core,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -7,15 +8,12 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/log"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("cpu_info", newCpuInfoCollector)
|
||||
}
|
||||
|
||||
// If you are adding additional labels to the metric, make sure that they get added in here as well. See below for explanation.
|
||||
const (
|
||||
win32ProcessorQuery = "SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name FROM Win32_Processor"
|
||||
@@ -23,13 +21,18 @@ const (
|
||||
|
||||
// A CpuInfoCollector is a Prometheus collector for a few WMI metrics in Win32_Processor
|
||||
type CpuInfoCollector struct {
|
||||
logger log.Logger
|
||||
CpuInfo *prometheus.Desc
|
||||
}
|
||||
|
||||
func newCpuInfoCollector() (Collector, error) {
|
||||
func newCpuInfoCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "cpu_info"
|
||||
|
||||
return &CpuInfoCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
CpuInfo: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, "", "cpu_info"),
|
||||
prometheus.BuildFQName(Namespace, "", subsystem),
|
||||
"Labeled CPU information as provided provided by Win32_Processor",
|
||||
[]string{
|
||||
"architecture",
|
||||
@@ -58,7 +61,7 @@ type win32_Processor struct {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *CpuInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting cpu_info metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting cpu_info metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
9
collector/cpu_test.go
Normal file
9
collector/cpu_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkCPUCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "cpu", newCPUCollector)
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus-community/windows_exporter/headers/sysinfoapi"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("cs", NewCSCollector)
|
||||
}
|
||||
|
||||
// A CSCollector is a Prometheus collector for WMI metrics
|
||||
type CSCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
PhysicalMemoryBytes *prometheus.Desc
|
||||
LogicalProcessors *prometheus.Desc
|
||||
Hostname *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewCSCollector ...
|
||||
func NewCSCollector() (Collector, error) {
|
||||
// newCSCollector ...
|
||||
func newCSCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "cs"
|
||||
|
||||
return &CSCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
LogicalProcessors: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "logical_processors"),
|
||||
"ComputerSystem.NumberOfLogicalProcessors",
|
||||
@@ -54,57 +54,53 @@ func NewCSCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *CSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting cs metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting cs metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_ComputerSystem docs:
|
||||
// - https://msdn.microsoft.com/en-us/library/aa394102
|
||||
type Win32_ComputerSystem struct {
|
||||
NumberOfLogicalProcessors uint32
|
||||
TotalPhysicalMemory uint64
|
||||
DNSHostname string
|
||||
Domain string
|
||||
Workgroup *string
|
||||
}
|
||||
|
||||
func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_ComputerSystem
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
// Get systeminfo for number of processors
|
||||
systemInfo := sysinfoapi.GetSystemInfo()
|
||||
|
||||
// Get memory status for physical memory
|
||||
mem, err := sysinfoapi.GlobalMemoryStatusEx()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.LogicalProcessors,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].NumberOfLogicalProcessors),
|
||||
float64(systemInfo.NumberOfProcessors),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PhysicalMemoryBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TotalPhysicalMemory),
|
||||
float64(mem.TotalPhys),
|
||||
)
|
||||
|
||||
var fqdn string
|
||||
if dst[0].Workgroup == nil || dst[0].Domain != *dst[0].Workgroup {
|
||||
fqdn = dst[0].DNSHostname + "." + dst[0].Domain
|
||||
} else {
|
||||
fqdn = dst[0].DNSHostname
|
||||
hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domain, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fqdn, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSFullyQualified)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Hostname,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
dst[0].DNSHostname,
|
||||
dst[0].Domain,
|
||||
hostname,
|
||||
domain,
|
||||
fqdn,
|
||||
)
|
||||
|
||||
|
||||
9
collector/cs_test.go
Normal file
9
collector/cs_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkCsCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "cs", newCSCollector)
|
||||
}
|
||||
@@ -1,27 +1,25 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
var dfsrEnabledCollectors = kingpin.Flag("collectors.dfsr.sources-enabled", "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String()
|
||||
const (
|
||||
FlagDfsrEnabledCollectors = "collectors.dfsr.sources-enabled"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Perflib sources are dynamic, depending on the enabled child collectors
|
||||
var perflibDependencies []string
|
||||
for _, source := range expandEnabledChildCollectors(*dfsrEnabledCollectors) {
|
||||
perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source))
|
||||
}
|
||||
|
||||
registerCollector("dfsr", NewDFSRCollector, perflibDependencies...)
|
||||
}
|
||||
var dfsrEnabledCollectors *string
|
||||
|
||||
// DFSRCollector contains the metric and state data of the DFSR collectors.
|
||||
type DFSRCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
// Connection source
|
||||
ConnectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc
|
||||
ConnectionBytesReceivedTotal *prometheus.Desc
|
||||
@@ -91,10 +89,16 @@ func dfsrGetPerfObjectName(collector string) string {
|
||||
return (prefix + suffix)
|
||||
}
|
||||
|
||||
// NewDFSRCollector is registered
|
||||
func NewDFSRCollector() (Collector, error) {
|
||||
log.Info("dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
|
||||
// newDFSRCollectorFlags is registered
|
||||
func newDFSRCollectorFlags(app *kingpin.Application) {
|
||||
dfsrEnabledCollectors = app.Flag(FlagDfsrEnabledCollectors, "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String()
|
||||
}
|
||||
|
||||
// newDFSRCollector is registered
|
||||
func newDFSRCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "dfsr"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
_ = level.Info(logger).Log("msg", "dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
|
||||
|
||||
enabled := expandEnabledChildCollectors(*dfsrEnabledCollectors)
|
||||
perfCounters := make([]string, 0, len(enabled))
|
||||
@@ -104,6 +108,8 @@ func NewDFSRCollector() (Collector, error) {
|
||||
addPerfCounterDependencies(subsystem, perfCounters)
|
||||
|
||||
dfsrCollector := DFSRCollector{
|
||||
logger: logger,
|
||||
|
||||
// Connection
|
||||
ConnectionBandwidthSavingsUsingDFSReplicationTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connection_bandwidth_savings_using_dfs_replication_bytes_total"),
|
||||
@@ -128,7 +134,7 @@ func NewDFSRCollector() (Collector, error) {
|
||||
|
||||
ConnectionFilesReceivedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connection_received_files_total"),
|
||||
"Total number of files receieved for connection",
|
||||
"Total number of files received for connection",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
@@ -447,7 +453,7 @@ type PerflibDFSRConnection struct {
|
||||
|
||||
func (c *DFSRCollector) collectConnection(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var dst []PerflibDFSRConnection
|
||||
if err := unmarshalObject(ctx.perfObjects["DFS Replication Connections"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["DFS Replication Connections"], &dst, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -554,7 +560,7 @@ type PerflibDFSRFolder struct {
|
||||
|
||||
func (c *DFSRCollector) collectFolder(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var dst []PerflibDFSRFolder
|
||||
if err := unmarshalObject(ctx.perfObjects["DFS Replicated Folders"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["DFS Replicated Folders"], &dst, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -764,7 +770,7 @@ type PerflibDFSRVolume struct {
|
||||
|
||||
func (c *DFSRCollector) collectVolume(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var dst []PerflibDFSRVolume
|
||||
if err := unmarshalObject(ctx.perfObjects["DFS Replication Service Volumes"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["DFS Replication Service Volumes"], &dst, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
9
collector/dfsr_test.go
Normal file
9
collector/dfsr_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDFSRCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "dfsr", newDFSRCollector)
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("dhcp", NewDhcpCollector, "DHCP Server")
|
||||
}
|
||||
|
||||
// A DhcpCollector is a Prometheus collector perflib DHCP metrics
|
||||
type DhcpCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
PacketsReceivedTotal *prometheus.Desc
|
||||
DuplicatesDroppedTotal *prometheus.Desc
|
||||
PacketsExpiredTotal *prometheus.Desc
|
||||
@@ -39,10 +39,12 @@ type DhcpCollector struct {
|
||||
FailoverBndupdDropped *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewDhcpCollector() (Collector, error) {
|
||||
func newDhcpCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "dhcp"
|
||||
|
||||
return &DhcpCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
PacketsReceivedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"),
|
||||
"Total number of packets received by the DHCP server (PacketsReceivedTotal)",
|
||||
@@ -229,7 +231,7 @@ type dhcpPerf struct {
|
||||
|
||||
func (c *DhcpCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var perflib []dhcpPerf
|
||||
if err := unmarshalObject(ctx.perfObjects["DHCP Server"], &perflib); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["DHCP Server"], &perflib, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
9
collector/dhcp_test.go
Normal file
9
collector/dhcp_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDHCPCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "dhcp", newDhcpCollector)
|
||||
}
|
||||
209
collector/diskdrive.go
Normal file
209
collector/diskdrive.go
Normal file
@@ -0,0 +1,209 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const (
|
||||
win32DiskQuery = "SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive"
|
||||
)
|
||||
|
||||
// A DiskDriveInfoCollector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive
|
||||
type DiskDriveInfoCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
DiskInfo *prometheus.Desc
|
||||
Status *prometheus.Desc
|
||||
Size *prometheus.Desc
|
||||
Partitions *prometheus.Desc
|
||||
Availability *prometheus.Desc
|
||||
}
|
||||
|
||||
func newDiskDriveInfoCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "diskdrive"
|
||||
|
||||
return &DiskDriveInfoCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
DiskInfo: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "info"),
|
||||
"General drive information",
|
||||
[]string{
|
||||
"device_id",
|
||||
"model",
|
||||
"caption",
|
||||
"name",
|
||||
},
|
||||
nil,
|
||||
),
|
||||
|
||||
Status: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "status"),
|
||||
"Status of the drive",
|
||||
[]string{
|
||||
"name", "status"},
|
||||
nil,
|
||||
),
|
||||
|
||||
Size: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "size"),
|
||||
"Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
|
||||
Partitions: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "partitions"),
|
||||
"Number of partitions",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
|
||||
Availability: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "availability"),
|
||||
"Availability Status",
|
||||
[]string{
|
||||
"name", "availability"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Win32_DiskDrive struct {
|
||||
DeviceID string
|
||||
Model string
|
||||
Size uint64
|
||||
Name string
|
||||
Caption string
|
||||
Partitions uint32
|
||||
Status string
|
||||
Availability uint16
|
||||
}
|
||||
|
||||
var (
|
||||
allDiskStatus = []string{
|
||||
"OK",
|
||||
"Error",
|
||||
"Degraded",
|
||||
"Unknown",
|
||||
"Pred fail",
|
||||
"Starting",
|
||||
"Stopping",
|
||||
"Service",
|
||||
"Stressed",
|
||||
"Nonrecover",
|
||||
"No Contact",
|
||||
"Lost Comm",
|
||||
}
|
||||
|
||||
availMap = map[int]string{
|
||||
|
||||
1: "Other",
|
||||
2: "Unknown",
|
||||
3: "Running / Full Power",
|
||||
4: "Warning",
|
||||
5: "In Test",
|
||||
6: "Not Applicable",
|
||||
7: "Power Off",
|
||||
8: "Off line",
|
||||
9: "Off Duty",
|
||||
10: "Degraded",
|
||||
11: "Not Installed",
|
||||
12: "Install Error",
|
||||
13: "Power Save - Unknown",
|
||||
14: "Power Save - Low Power Mode",
|
||||
15: "Power Save - Standby",
|
||||
16: "Power Cycle",
|
||||
17: "Power Save - Warning",
|
||||
18: "Paused",
|
||||
19: "Not Ready",
|
||||
20: "Not Configured",
|
||||
21: "Quiesced",
|
||||
}
|
||||
)
|
||||
|
||||
// Collect sends the metric values for each metric to the provided prometheus Metric channel.
|
||||
func (c *DiskDriveInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting disk_drive_info metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_DiskDrive
|
||||
|
||||
if err := wmi.Query(win32DiskQuery, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
for _, disk := range dst {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DiskInfo,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
strings.Trim(disk.DeviceID, "\\.\\"),
|
||||
strings.TrimRight(disk.Model, " "),
|
||||
strings.TrimRight(disk.Caption, " "),
|
||||
strings.TrimRight(disk.Name, "\\.\\"),
|
||||
)
|
||||
|
||||
for _, status := range allDiskStatus {
|
||||
isCurrentState := 0.0
|
||||
if status == disk.Status {
|
||||
isCurrentState = 1.0
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Status,
|
||||
prometheus.GaugeValue,
|
||||
isCurrentState,
|
||||
strings.Trim(disk.Name, "\\.\\"),
|
||||
status,
|
||||
)
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Size,
|
||||
prometheus.GaugeValue,
|
||||
float64(disk.Size),
|
||||
strings.Trim(disk.Name, "\\.\\"),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Partitions,
|
||||
prometheus.GaugeValue,
|
||||
float64(disk.Partitions),
|
||||
strings.Trim(disk.Name, "\\.\\"),
|
||||
)
|
||||
|
||||
for availNum, val := range availMap {
|
||||
isCurrentState := 0.0
|
||||
if availNum == int(disk.Availability) {
|
||||
isCurrentState = 1.0
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Availability,
|
||||
prometheus.GaugeValue,
|
||||
isCurrentState,
|
||||
strings.Trim(disk.Name, "\\.\\"),
|
||||
val,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
9
collector/diskdrive_test.go
Normal file
9
collector/diskdrive_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDiskDriveCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "disk_drive", newDiskDriveInfoCollector)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -5,17 +6,16 @@ package collector
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("dns", NewDNSCollector)
|
||||
}
|
||||
|
||||
// A DNSCollector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics
|
||||
type DNSCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
ZoneTransferRequestsReceived *prometheus.Desc
|
||||
ZoneTransferRequestsSent *prometheus.Desc
|
||||
ZoneTransferResponsesReceived *prometheus.Desc
|
||||
@@ -40,10 +40,12 @@ type DNSCollector struct {
|
||||
UnmatchedResponsesReceived *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewDNSCollector ...
|
||||
func NewDNSCollector() (Collector, error) {
|
||||
// newDNSCollector ...
|
||||
func newDNSCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "dns"
|
||||
return &DNSCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
ZoneTransferRequestsReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_received_total"),
|
||||
"Number of zone transfer requests (AXFR/IXFR) received by the master DNS server",
|
||||
@@ -136,7 +138,7 @@ func NewDNSCollector() (Collector, error) {
|
||||
),
|
||||
Responses: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "responses_total"),
|
||||
"Number of reponses sent by DNS server",
|
||||
"Number of responses sent by DNS server",
|
||||
[]string{"protocol"},
|
||||
nil,
|
||||
),
|
||||
@@ -183,7 +185,7 @@ func NewDNSCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *DNSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting dns metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting dns metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -237,7 +239,7 @@ type Win32_PerfRawData_DNS_DNS struct {
|
||||
|
||||
func (c *DNSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_DNS_DNS
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
9
collector/dns_test.go
Normal file
9
collector/dns_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDNSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "dns", newDNSCollector)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -7,26 +8,20 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("exchange", newExchangeCollector,
|
||||
"MSExchange ADAccess Processes",
|
||||
"MSExchangeTransport Queues",
|
||||
"MSExchange HttpProxy",
|
||||
"MSExchange ActiveSync",
|
||||
"MSExchange Availability Service",
|
||||
"MSExchange OWA",
|
||||
"MSExchangeAutodiscover",
|
||||
"MSExchange WorkloadManagement Workloads",
|
||||
"MSExchange RpcClientAccess",
|
||||
)
|
||||
}
|
||||
const (
|
||||
FlagExchangeListAllCollectors = "collectors.exchange.list"
|
||||
FlagExchangeCollectorsEnabled = "collectors.exchange.enabled"
|
||||
)
|
||||
|
||||
type exchangeCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
LDAPReadTime *prometheus.Desc
|
||||
LDAPSearchTime *prometheus.Desc
|
||||
LDAPWriteTime *prometheus.Desc
|
||||
@@ -82,19 +77,27 @@ var (
|
||||
"RpcClientAccess",
|
||||
}
|
||||
|
||||
argExchangeListAllCollectors = kingpin.Flag(
|
||||
"collectors.exchange.list",
|
||||
argExchangeListAllCollectors *bool
|
||||
|
||||
argExchangeCollectorsEnabled *string
|
||||
)
|
||||
|
||||
// newExchangeCollectorFlags ...
|
||||
func newExchangeCollectorFlags(app *kingpin.Application) {
|
||||
argExchangeListAllCollectors = app.Flag(
|
||||
FlagExchangeListAllCollectors,
|
||||
"List the collectors along with their perflib object name/ids",
|
||||
).Bool()
|
||||
|
||||
argExchangeCollectorsEnabled = kingpin.Flag(
|
||||
"collectors.exchange.enabled",
|
||||
argExchangeCollectorsEnabled = app.Flag(
|
||||
FlagExchangeCollectorsEnabled,
|
||||
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
|
||||
).Default("").String()
|
||||
)
|
||||
}
|
||||
|
||||
// newExchangeCollector returns a new Collector
|
||||
func newExchangeCollector() (Collector, error) {
|
||||
func newExchangeCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "exchange"
|
||||
|
||||
// desc creates a new prometheus description
|
||||
desc := func(metricName string, description string, labels ...string) *prometheus.Desc {
|
||||
@@ -107,6 +110,8 @@ func newExchangeCollector() (Collector, error) {
|
||||
}
|
||||
|
||||
c := exchangeCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
RPCAveragedLatency: desc("rpc_avg_latency_sec", "The latency (sec), averaged for the past 1024 packets"),
|
||||
RPCRequests: desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service"),
|
||||
ActiveUserCount: desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes"),
|
||||
@@ -202,7 +207,7 @@ func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Met
|
||||
|
||||
for _, collectorName := range c.enabledCollectors {
|
||||
if err := collectorFuncs[collectorName](ctx, ch); err != nil {
|
||||
log.Errorf("Error in %s: %s", collectorName, err)
|
||||
_ = level.Error(c.logger).Log("msg", "Error in "+collectorName, "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -222,7 +227,7 @@ type perflibADAccessProcesses struct {
|
||||
|
||||
func (c *exchangeCollector) collectADAccessProcesses(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibADAccessProcesses
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange ADAccess Processes"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange ADAccess Processes"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -234,7 +239,7 @@ func (c *exchangeCollector) collectADAccessProcesses(ctx *ScrapeContext, ch chan
|
||||
}
|
||||
|
||||
// since we're not including the PID suffix from the instance names in the label names,
|
||||
// we get an occational duplicate. This seems to affect about 4 instances only on this object.
|
||||
// we get an occasional duplicate. This seems to affect about 4 instances only on this object.
|
||||
labelUseCount[labelName]++
|
||||
if labelUseCount[labelName] > 1 {
|
||||
labelName = fmt.Sprintf("%s_%d", labelName, labelUseCount[labelName])
|
||||
@@ -280,7 +285,7 @@ type perflibAvailabilityService struct {
|
||||
|
||||
func (c *exchangeCollector) collectAvailabilityService(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibAvailabilityService
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange Availability Service"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange Availability Service"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -308,7 +313,7 @@ type perflibHTTPProxy struct {
|
||||
|
||||
func (c *exchangeCollector) collectHTTPProxy(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibHTTPProxy
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange HttpProxy"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange HttpProxy"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -362,7 +367,7 @@ type perflibOWA struct {
|
||||
|
||||
func (c *exchangeCollector) collectOWA(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibOWA
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange OWA"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange OWA"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -390,7 +395,7 @@ type perflibActiveSync struct {
|
||||
|
||||
func (c *exchangeCollector) collectActiveSync(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibActiveSync
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange ActiveSync"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange ActiveSync"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -426,7 +431,7 @@ type perflibRPCClientAccess struct {
|
||||
|
||||
func (c *exchangeCollector) collectRPC(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibRPCClientAccess
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange RpcClientAccess"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange RpcClientAccess"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -482,7 +487,7 @@ type perflibTransportQueues struct {
|
||||
|
||||
func (c *exchangeCollector) collectTransportQueues(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibTransportQueues
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchangeTransport Queues"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchangeTransport Queues"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -556,7 +561,7 @@ type perflibWorkloadManagementWorkloads struct {
|
||||
|
||||
func (c *exchangeCollector) collectWorkloadManagementWorkloads(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibWorkloadManagementWorkloads
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange WorkloadManagement Workloads"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchange WorkloadManagement Workloads"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -607,7 +612,7 @@ type perflibAutodiscover struct {
|
||||
|
||||
func (c *exchangeCollector) collectAutoDiscover(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var data []perflibAutodiscover
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchangeAutodiscover"], &data); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["MSExchangeAutodiscover"], &data, c.logger); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, autodisc := range data {
|
||||
|
||||
9
collector/exchange_test.go
Normal file
9
collector/exchange_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkExchangeCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "exchange", newExchangeCollector)
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("fsrmquota", newFSRMQuotaCollector)
|
||||
}
|
||||
|
||||
type FSRMQuotaCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
QuotasCount *prometheus.Desc
|
||||
Path *prometheus.Desc
|
||||
PeakUsage *prometheus.Desc
|
||||
@@ -24,9 +23,11 @@ type FSRMQuotaCollector struct {
|
||||
Template *prometheus.Desc
|
||||
}
|
||||
|
||||
func newFSRMQuotaCollector() (Collector, error) {
|
||||
func newFSRMQuotaCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "fsrmquota"
|
||||
return &FSRMQuotaCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
QuotasCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "count"),
|
||||
"Number of Quotas",
|
||||
@@ -88,7 +89,7 @@ func newFSRMQuotaCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *FSRMQuotaCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting fsrmquota metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting fsrmquota metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -113,7 +114,7 @@ type MSFT_FSRMQuota struct {
|
||||
|
||||
func (c *FSRMQuotaCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []MSFT_FSRMQuota
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
|
||||
var count int
|
||||
|
||||
|
||||
9
collector/fsrmquota_test.go
Normal file
9
collector/fsrmquota_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkFsrmQuotaCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "fsrmquota", newFSRMQuotaCollector)
|
||||
}
|
||||
@@ -1,21 +1,22 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("hyperv", NewHyperVCollector)
|
||||
}
|
||||
|
||||
// HyperVCollector is a Prometheus collector for hyper-v
|
||||
type HyperVCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
||||
HealthCritical *prometheus.Desc
|
||||
HealthOk *prometheus.Desc
|
||||
@@ -52,6 +53,11 @@ type HyperVCollector struct {
|
||||
LogicalProcessors *prometheus.Desc
|
||||
VirtualProcessors *prometheus.Desc
|
||||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor
|
||||
HostLPGuestRunTimePercent *prometheus.Desc
|
||||
HostLPHypervisorRunTimePercent *prometheus.Desc
|
||||
HostLPTotalRunTimePercent *prometheus.Desc
|
||||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
|
||||
HostGuestRunTime *prometheus.Desc
|
||||
HostHypervisorRunTime *prometheus.Desc
|
||||
@@ -110,12 +116,27 @@ type HyperVCollector struct {
|
||||
VMNetworkDroppedPacketsOutgoing *prometheus.Desc
|
||||
VMNetworkPacketsReceived *prometheus.Desc
|
||||
VMNetworkPacketsSent *prometheus.Desc
|
||||
|
||||
// Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM
|
||||
VMMemoryAddedMemory *prometheus.Desc
|
||||
VMMemoryAveragePressure *prometheus.Desc
|
||||
VMMemoryCurrentPressure *prometheus.Desc
|
||||
VMMemoryGuestVisiblePhysicalMemory *prometheus.Desc
|
||||
VMMemoryMaximumPressure *prometheus.Desc
|
||||
VMMemoryMemoryAddOperations *prometheus.Desc
|
||||
VMMemoryMemoryRemoveOperations *prometheus.Desc
|
||||
VMMemoryMinimumPressure *prometheus.Desc
|
||||
VMMemoryPhysicalMemory *prometheus.Desc
|
||||
VMMemoryRemovedMemory *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewHyperVCollector ...
|
||||
func NewHyperVCollector() (Collector, error) {
|
||||
// newHyperVCollector ...
|
||||
func newHyperVCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "hyperv"
|
||||
buildSubsystemName := func(component string) string { return "hyperv_" + component }
|
||||
return &HyperVCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
HealthCritical: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("health"), "critical"),
|
||||
"This counter represents the number of virtual machines with critical health",
|
||||
@@ -296,6 +317,27 @@ func NewHyperVCollector() (Collector, error) {
|
||||
|
||||
//
|
||||
|
||||
HostLPGuestRunTimePercent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("host_lp"), "guest_run_time_percent"),
|
||||
"The percentage of time spent by the processor in guest code",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
HostLPHypervisorRunTimePercent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("host_lp"), "hypervisor_run_time_percent"),
|
||||
"The percentage of time spent by the processor in hypervisor code",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
HostLPTotalRunTimePercent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("host_lp"), "total_run_time_percent"),
|
||||
"The percentage of time spent by the processor in guest and hypervisor code",
|
||||
[]string{"core"},
|
||||
nil,
|
||||
),
|
||||
|
||||
//
|
||||
|
||||
HostGuestRunTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "guest_run_time"),
|
||||
"The time spent by the virtual processor in guest code",
|
||||
@@ -592,6 +634,69 @@ func NewHyperVCollector() (Collector, error) {
|
||||
[]string{"vm_interface"},
|
||||
nil,
|
||||
),
|
||||
|
||||
//
|
||||
|
||||
VMMemoryAddedMemory: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "added_total"),
|
||||
"This counter represents memory in MB added to the VM",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryAveragePressure: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_average"),
|
||||
"This gauge represents the average pressure in the VM.",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryCurrentPressure: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_current"),
|
||||
"This gauge represents the current pressure in the VM.",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryGuestVisiblePhysicalMemory: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "physical_guest_visible"),
|
||||
"'This gauge represents the amount of memory in MB visible to the VM guest.'",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryMaximumPressure: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_maximum"),
|
||||
"This gauge represents the maximum pressure band in the VM.",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryMemoryAddOperations: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "add_operations_total"),
|
||||
"This counter represents the number of operations adding memory to the VM.",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryMemoryRemoveOperations: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "remove_operations_total"),
|
||||
"This counter represents the number of operations removing memory from the VM.",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryMinimumPressure: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_minimum"),
|
||||
"This gauge represents the minimum pressure band in the VM.",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryPhysicalMemory: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "physical"),
|
||||
"This gauge represents the current amount of memory in MB assigned to the VM.",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
VMMemoryRemovedMemory: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "removed_total"),
|
||||
"This counter represents memory in MB removed from the VM",
|
||||
[]string{"vm"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -599,52 +704,62 @@ func NewHyperVCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *HyperVCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collectVmHealth(ch); err != nil {
|
||||
log.Error("failed collecting hyperV health status metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV health status metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmVid(ch); err != nil {
|
||||
log.Error("failed collecting hyperV pages metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV pages metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmHv(ch); err != nil {
|
||||
log.Error("failed collecting hyperV hv status metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV hv status metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmProcessor(ch); err != nil {
|
||||
log.Error("failed collecting hyperV processor metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV processor metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectHostLPUsage(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV host logical processors metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectHostCpuUsage(ch); err != nil {
|
||||
log.Error("failed collecting hyperV host CPU metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV host CPU metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmCpuUsage(ch); err != nil {
|
||||
log.Error("failed collecting hyperV VM CPU metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV VM CPU metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmSwitch(ch); err != nil {
|
||||
log.Error("failed collecting hyperV switch metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV switch metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmEthernet(ch); err != nil {
|
||||
log.Error("failed collecting hyperV ethernet metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV ethernet metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmStorage(ch); err != nil {
|
||||
log.Error("failed collecting hyperV virtual storage metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV virtual storage metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmNetwork(ch); err != nil {
|
||||
log.Error("failed collecting hyperV virtual network metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV virtual network metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if desc, err := c.collectVmMemory(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV virtual memory metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -659,7 +774,7 @@ type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
||||
|
||||
func (c *HyperVCollector) collectVmHealth(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -692,7 +807,7 @@ type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmVid(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -756,7 +871,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmHv(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -894,7 +1009,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisor struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmProcessor(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisor
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -918,6 +1033,59 @@ func (c *HyperVCollector) collectVmProcessor(ch chan<- prometheus.Metric) (*prom
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor ...
|
||||
type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct {
|
||||
Name string
|
||||
PercentGuestRunTime uint64
|
||||
PercentHypervisorRunTime uint64
|
||||
PercentTotalRunTime uint
|
||||
}
|
||||
|
||||
func (c *HyperVCollector) collectHostLPUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
if strings.Contains(obj.Name, "_Total") {
|
||||
continue
|
||||
}
|
||||
// The name format is Hv LP <core id>
|
||||
parts := strings.Split(obj.Name, " ")
|
||||
if len(parts) != 3 {
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Unexpected format of Name in collectHostLPUsage: %q", obj.Name))
|
||||
continue
|
||||
}
|
||||
coreId := parts[2]
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HostLPGuestRunTimePercent,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.PercentGuestRunTime),
|
||||
coreId,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HostLPHypervisorRunTimePercent,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.PercentHypervisorRunTime),
|
||||
coreId,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HostLPTotalRunTimePercent,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.PercentTotalRunTime),
|
||||
coreId,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ...
|
||||
type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct {
|
||||
Name string
|
||||
@@ -929,7 +1097,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct {
|
||||
|
||||
func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -941,7 +1109,7 @@ func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*pro
|
||||
// The name format is Root VP <core id>
|
||||
parts := strings.Split(obj.Name, " ")
|
||||
if len(parts) != 3 {
|
||||
log.Warnf("Unexpected format of Name in collectHostCpuUsage: %q", obj.Name)
|
||||
_ = level.Warn(c.logger).Log("msg", "Unexpected format of Name in collectHostCpuUsage: "+obj.Name)
|
||||
continue
|
||||
}
|
||||
coreId := parts[2]
|
||||
@@ -990,7 +1158,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1002,12 +1170,12 @@ func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prome
|
||||
// The name format is <VM Name>:Hv VP <vcore id>
|
||||
parts := strings.Split(obj.Name, ":")
|
||||
if len(parts) != 2 {
|
||||
log.Warnf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, "<VM Name>:Hv VP <vcore id>")
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, "<VM Name>:Hv VP <vcore id>"))
|
||||
continue
|
||||
}
|
||||
coreParts := strings.Split(parts[1], " ")
|
||||
if len(coreParts) != 3 {
|
||||
log.Warnf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP <vcore id>")
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP <vcore id>"))
|
||||
continue
|
||||
}
|
||||
vmName := parts[0]
|
||||
@@ -1077,7 +1245,7 @@ type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1212,6 +1380,12 @@ func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometh
|
||||
float64(obj.PacketsReceivedPersec),
|
||||
obj.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsSent,
|
||||
prometheus.CounterValue,
|
||||
float64(obj.PacketsSentPersec),
|
||||
obj.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PurgedMacAddresses,
|
||||
prometheus.CounterValue,
|
||||
@@ -1236,7 +1410,7 @@ type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmEthernet(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1306,7 +1480,7 @@ type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1375,7 +1549,7 @@ type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct {
|
||||
|
||||
func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1430,3 +1604,104 @@ func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*promet
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM ...
|
||||
type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct {
|
||||
Name string
|
||||
AddedMemory uint64
|
||||
AveragePressure uint64
|
||||
CurrentPressure uint64
|
||||
GuestVisiblePhysicalMemory uint64
|
||||
MaximumPressure uint64
|
||||
MemoryAddOperations uint64
|
||||
MemoryRemoveOperations uint64
|
||||
MinimumPressure uint64
|
||||
PhysicalMemory uint64
|
||||
RemovedMemory uint64
|
||||
}
|
||||
|
||||
func (c *HyperVCollector) collectVmMemory(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
if strings.Contains(obj.Name, "_Total") {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryAddedMemory,
|
||||
prometheus.CounterValue,
|
||||
float64(obj.AddedMemory),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryAveragePressure,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.AveragePressure),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryCurrentPressure,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.CurrentPressure),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryGuestVisiblePhysicalMemory,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.GuestVisiblePhysicalMemory),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryMaximumPressure,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.MaximumPressure),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryMemoryAddOperations,
|
||||
prometheus.CounterValue,
|
||||
float64(obj.MemoryAddOperations),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryMemoryRemoveOperations,
|
||||
prometheus.CounterValue,
|
||||
float64(obj.MemoryRemoveOperations),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryMinimumPressure,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.MinimumPressure),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryPhysicalMemory,
|
||||
prometheus.GaugeValue,
|
||||
float64(obj.PhysicalMemory),
|
||||
obj.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VMMemoryRemovedMemory,
|
||||
prometheus.CounterValue,
|
||||
float64(obj.RemovedMemory),
|
||||
obj.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
9
collector/hyperv_test.go
Normal file
9
collector/hyperv_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkHypervCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "hyperv", newHyperVCollector)
|
||||
}
|
||||
2019
collector/iis.go
2019
collector/iis.go
File diff suppressed because it is too large
Load Diff
49
collector/iis_test.go
Normal file
49
collector/iis_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkIISCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "iis", newIISCollector)
|
||||
}
|
||||
|
||||
func TestIISDeduplication(t *testing.T) {
|
||||
start := []perflibAPP_POOL_WAS{
|
||||
{
|
||||
Name: "foo",
|
||||
Frequency_Object: 1,
|
||||
},
|
||||
{
|
||||
Name: "foo1#999",
|
||||
Frequency_Object: 2,
|
||||
},
|
||||
{
|
||||
Name: "foo#2",
|
||||
Frequency_Object: 3,
|
||||
},
|
||||
{
|
||||
Name: "bar$2",
|
||||
Frequency_Object: 4,
|
||||
},
|
||||
{
|
||||
Name: "bar_2",
|
||||
Frequency_Object: 5,
|
||||
},
|
||||
}
|
||||
var expected = make(map[string]perflibAPP_POOL_WAS)
|
||||
// Should be deduplicated from "foo#2"
|
||||
expected["foo"] = perflibAPP_POOL_WAS{Name: "foo#2", Frequency_Object: 3}
|
||||
// Map key should have suffix stripped, but struct name field should be unchanged
|
||||
expected["foo1"] = perflibAPP_POOL_WAS{Name: "foo1#999", Frequency_Object: 2}
|
||||
// Map key and Name should be identical, as there is no suffix starting with "#"
|
||||
expected["bar$2"] = perflibAPP_POOL_WAS{Name: "bar$2", Frequency_Object: 4}
|
||||
// Map key and Name should be identical, as there is no suffix starting with "#"
|
||||
expected["bar_2"] = perflibAPP_POOL_WAS{Name: "bar_2", Frequency_Object: 5}
|
||||
|
||||
deduplicated := dedupIISNames(start)
|
||||
if !reflect.DeepEqual(expected, deduplicated) {
|
||||
t.Errorf("Flattened values do not match!\nExpected result: %+v\nActual result: %+v", expected, deduplicated)
|
||||
}
|
||||
}
|
||||
415
collector/init.go
Normal file
415
collector/init.go
Normal file
@@ -0,0 +1,415 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
)
|
||||
|
||||
// collectorInit represents the required initialisation config for a collector.
|
||||
type collectorInit struct {
|
||||
// Name of collector to be initialised
|
||||
name string
|
||||
// Builder function for the collector
|
||||
flags flagsBuilder
|
||||
// Builder function for the collector
|
||||
builder collectorBuilder
|
||||
// Perflib counter names for the collector.
|
||||
// These will be included in the Perflib scrape scope by the exporter.
|
||||
perfCounterFunc perfCounterNamesBuilder
|
||||
}
|
||||
|
||||
func getDFSRCollectorDeps(_ log.Logger) []string {
|
||||
// Perflib sources are dynamic, depending on the enabled child collectors
|
||||
var perflibDependencies []string
|
||||
for _, source := range expandEnabledChildCollectors(*dfsrEnabledCollectors) {
|
||||
perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source))
|
||||
}
|
||||
|
||||
return perflibDependencies
|
||||
}
|
||||
|
||||
var collectors = []collectorInit{
|
||||
{
|
||||
name: "ad",
|
||||
flags: nil,
|
||||
builder: newADCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "adcs",
|
||||
flags: nil,
|
||||
builder: adcsCollectorMethod,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"Certification Authority"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "adfs",
|
||||
flags: nil,
|
||||
builder: newADFSCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"AD FS"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cache",
|
||||
flags: nil,
|
||||
builder: newCacheCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"Cache"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "container",
|
||||
flags: nil,
|
||||
builder: newContainerMetricsCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "cpu",
|
||||
flags: nil,
|
||||
builder: newCPUCollector,
|
||||
perfCounterFunc: func(logger log.Logger) []string {
|
||||
if getWindowsVersion(logger) > 6.05 {
|
||||
return []string{"Processor Information"}
|
||||
}
|
||||
return []string{"Processor"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cpu_info",
|
||||
flags: nil,
|
||||
builder: newCpuInfoCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "cs",
|
||||
flags: nil,
|
||||
builder: newCSCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "dfsr",
|
||||
flags: newDFSRCollectorFlags,
|
||||
builder: newDFSRCollector,
|
||||
perfCounterFunc: getDFSRCollectorDeps,
|
||||
},
|
||||
{
|
||||
name: "dhcp",
|
||||
flags: nil,
|
||||
builder: newDhcpCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "diskdrive",
|
||||
flags: nil,
|
||||
builder: newDiskDriveInfoCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "dns",
|
||||
flags: nil,
|
||||
builder: newDNSCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "exchange",
|
||||
flags: newExchangeCollectorFlags,
|
||||
builder: newExchangeCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{
|
||||
"MSExchange ADAccess Processes",
|
||||
"MSExchangeTransport Queues",
|
||||
"MSExchange HttpProxy",
|
||||
"MSExchange ActiveSync",
|
||||
"MSExchange Availability Service",
|
||||
"MSExchange OWA",
|
||||
"MSExchangeAutodiscover",
|
||||
"MSExchange WorkloadManagement Workloads",
|
||||
"MSExchange RpcClientAccess",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fsrmquota",
|
||||
flags: nil,
|
||||
builder: newFSRMQuotaCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "hyperv",
|
||||
flags: nil,
|
||||
builder: newHyperVCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "iis",
|
||||
flags: newIISCollectorFlags,
|
||||
builder: newIISCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{
|
||||
"Web Service",
|
||||
"APP_POOL_WAS",
|
||||
"Web Service Cache",
|
||||
"W3SVC_W3WP",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "logical_disk",
|
||||
flags: newLogicalDiskCollectorFlags,
|
||||
builder: newLogicalDiskCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"LogicalDisk"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "logon",
|
||||
flags: nil,
|
||||
builder: newLogonCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "memory",
|
||||
flags: nil,
|
||||
builder: newMemoryCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"Memory"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mscluster_cluster",
|
||||
flags: nil,
|
||||
builder: newMSCluster_ClusterCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "mscluster_network",
|
||||
flags: nil,
|
||||
builder: newMSCluster_NetworkCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "mscluster_node",
|
||||
flags: nil,
|
||||
builder: newMSCluster_NodeCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "mscluster_resource",
|
||||
flags: nil,
|
||||
builder: newMSCluster_ResourceCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "mscluster_resourcegroup",
|
||||
flags: nil,
|
||||
builder: newMSCluster_ResourceGroupCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "msmq",
|
||||
flags: newMSMQCollectorFlags,
|
||||
builder: newMSMQCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "mssql",
|
||||
flags: newMSSQLCollectorFlags,
|
||||
builder: newMSSQLCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "net",
|
||||
flags: newNetworkCollectorFlags,
|
||||
builder: newNetworkCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"Network Interface"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "netframework_clrexceptions",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRExceptionsCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "netframework_clrinterop",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRInteropCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "netframework_clrjit",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRJitCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "netframework_clrloading",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRLoadingCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "netframework_clrlocksandthreads",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRLocksAndThreadsCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "netframework_clrmemory",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRMemoryCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "netframework_clrremoting",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRRemotingCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "netframework_clrsecurity",
|
||||
flags: nil,
|
||||
builder: newNETFramework_NETCLRSecurityCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "nps",
|
||||
builder: newNPSCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "os",
|
||||
flags: nil,
|
||||
builder: newOSCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"Paging File"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "process",
|
||||
flags: newProcessCollectorFlags,
|
||||
builder: newProcessCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"Process"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remote_fx",
|
||||
flags: nil,
|
||||
builder: newRemoteFx,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"RemoteFX Network"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "scheduled_task",
|
||||
flags: newScheduledTaskFlags,
|
||||
builder: newScheduledTask,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "service",
|
||||
flags: newServiceCollectorFlags,
|
||||
builder: newserviceCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "smtp",
|
||||
flags: newSMTPCollectorFlags,
|
||||
builder: newSMTPCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"SMTP Server"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "system",
|
||||
flags: nil,
|
||||
builder: newSystemCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"System"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "teradici_pcoip",
|
||||
flags: nil,
|
||||
builder: newTeradiciPcoipCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "tcp",
|
||||
flags: nil,
|
||||
builder: newTCPCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"TCPv4"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminal_services",
|
||||
flags: nil,
|
||||
builder: newTerminalServicesCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{
|
||||
"Terminal Services",
|
||||
"Terminal Services Session",
|
||||
"Remote Desktop Connection Broker Counterset",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "textfile",
|
||||
flags: newTextFileCollectorFlags,
|
||||
builder: newTextFileCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "thermalzone",
|
||||
flags: nil,
|
||||
builder: newThermalZoneCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "time",
|
||||
flags: nil,
|
||||
builder: newTimeCollector,
|
||||
perfCounterFunc: func(_ log.Logger) []string {
|
||||
return []string{"Windows Time Service"}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "vmware",
|
||||
flags: nil,
|
||||
builder: newVmwareCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "vmware_blast",
|
||||
flags: nil,
|
||||
builder: newVmwareBlastCollector,
|
||||
perfCounterFunc: nil,
|
||||
},
|
||||
}
|
||||
|
||||
// RegisterCollectorsFlags To be called by the exporter for collector initialisation before running app.Parse
|
||||
func RegisterCollectorsFlags(app *kingpin.Application) {
|
||||
for _, v := range collectors {
|
||||
if v.flags != nil {
|
||||
v.flags(app)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterCollectors To be called by the exporter for collector initialisation
|
||||
func RegisterCollectors(logger log.Logger) {
|
||||
for _, v := range collectors {
|
||||
var perfCounterNames []string
|
||||
|
||||
if v.perfCounterFunc != nil {
|
||||
perfCounterNames = v.perfCounterFunc(logger)
|
||||
}
|
||||
|
||||
registerCollector(v.name, v.builder, perfCounterNames...)
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,45 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("logical_disk", NewLogicalDiskCollector, "LogicalDisk")
|
||||
}
|
||||
const (
|
||||
FlagLogicalDiskVolumeOldExclude = "collector.logical_disk.volume-blacklist"
|
||||
FlagLogicalDiskVolumeOldInclude = "collector.logical_disk.volume-whitelist"
|
||||
|
||||
FlagLogicalDiskVolumeExclude = "collector.logical_disk.volume-exclude"
|
||||
FlagLogicalDiskVolumeInclude = "collector.logical_disk.volume-include"
|
||||
)
|
||||
|
||||
var (
|
||||
volumeWhitelist = kingpin.Flag(
|
||||
"collector.logical_disk.volume-whitelist",
|
||||
"Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.",
|
||||
).Default(".+").String()
|
||||
volumeBlacklist = kingpin.Flag(
|
||||
"collector.logical_disk.volume-blacklist",
|
||||
"Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.",
|
||||
).Default("").String()
|
||||
volumeOldInclude *string
|
||||
volumeOldExclude *string
|
||||
|
||||
volumeInclude *string
|
||||
volumeExclude *string
|
||||
|
||||
volumeIncludeSet bool
|
||||
volumeExcludeSet bool
|
||||
)
|
||||
|
||||
// A LogicalDiskCollector is a Prometheus collector for perflib logicalDisk metrics
|
||||
type LogicalDiskCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
RequestsQueued *prometheus.Desc
|
||||
AvgReadQueue *prometheus.Desc
|
||||
AvgWriteQueue *prometheus.Desc
|
||||
ReadBytesTotal *prometheus.Desc
|
||||
ReadsTotal *prometheus.Desc
|
||||
WriteBytesTotal *prometheus.Desc
|
||||
@@ -43,15 +54,63 @@ type LogicalDiskCollector struct {
|
||||
WriteLatency *prometheus.Desc
|
||||
ReadWriteLatency *prometheus.Desc
|
||||
|
||||
volumeWhitelistPattern *regexp.Regexp
|
||||
volumeBlacklistPattern *regexp.Regexp
|
||||
volumeIncludePattern *regexp.Regexp
|
||||
volumeExcludePattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewLogicalDiskCollector ...
|
||||
func NewLogicalDiskCollector() (Collector, error) {
|
||||
// newLogicalDiskCollectorFlags ...
|
||||
func newLogicalDiskCollectorFlags(app *kingpin.Application) {
|
||||
volumeInclude = app.Flag(
|
||||
FlagLogicalDiskVolumeInclude,
|
||||
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.",
|
||||
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
|
||||
volumeIncludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
volumeExclude = app.Flag(
|
||||
FlagLogicalDiskVolumeExclude,
|
||||
"Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.",
|
||||
).Default("").PreAction(func(c *kingpin.ParseContext) error {
|
||||
volumeExcludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
volumeOldInclude = app.Flag(
|
||||
FlagLogicalDiskVolumeOldInclude,
|
||||
"DEPRECATED: Use --collector.logical_disk.volume-include",
|
||||
).Hidden().String()
|
||||
volumeOldExclude = app.Flag(
|
||||
FlagLogicalDiskVolumeOldExclude,
|
||||
"DEPRECATED: Use --collector.logical_disk.volume-exclude",
|
||||
).Hidden().String()
|
||||
}
|
||||
|
||||
// newLogicalDiskCollector ...
|
||||
func newLogicalDiskCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "logical_disk"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
if *volumeOldExclude != "" {
|
||||
if !volumeExcludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.logical_disk.volume-blacklist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-exclude")
|
||||
*volumeExclude = *volumeOldExclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.logical_disk.volume-blacklist and --collector.logical_disk.volume-exclude are mutually exclusive")
|
||||
}
|
||||
}
|
||||
if *volumeOldInclude != "" {
|
||||
if !volumeIncludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.logical_disk.volume-whitelist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-include")
|
||||
*volumeInclude = *volumeOldInclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.logical_disk.volume-whitelist and --collector.logical_disk.volume-include are mutually exclusive")
|
||||
}
|
||||
}
|
||||
|
||||
return &LogicalDiskCollector{
|
||||
logger: logger,
|
||||
|
||||
RequestsQueued: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "requests_queued"),
|
||||
"The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)",
|
||||
@@ -59,6 +118,20 @@ func NewLogicalDiskCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
|
||||
AvgReadQueue: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "avg_read_requests_queued"),
|
||||
"Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
AvgWriteQueue: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "avg_write_requests_queued"),
|
||||
"Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
ReadBytesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "read_bytes_total"),
|
||||
"The number of bytes transferred from the disk during read operations (LogicalDisk.DiskReadBytesPerSec)",
|
||||
@@ -103,14 +176,14 @@ func NewLogicalDiskCollector() (Collector, error) {
|
||||
|
||||
FreeSpace: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "free_bytes"),
|
||||
"Free space in bytes (LogicalDisk.PercentFreeSpace)",
|
||||
"Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
TotalSpace: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "size_bytes"),
|
||||
"Total space in bytes (LogicalDisk.PercentFreeSpace_Base)",
|
||||
"Total space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
@@ -150,8 +223,8 @@ func NewLogicalDiskCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
|
||||
volumeWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeWhitelist)),
|
||||
volumeBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeBlacklist)),
|
||||
volumeIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeInclude)),
|
||||
volumeExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeExclude)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -159,7 +232,7 @@ func NewLogicalDiskCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *LogicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting logical_disk metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting logical_disk metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -169,33 +242,35 @@ func (c *LogicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.
|
||||
// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class
|
||||
// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference
|
||||
type logicalDisk struct {
|
||||
Name string
|
||||
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`
|
||||
DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"`
|
||||
DiskReadsPerSec float64 `perflib:"Disk Reads/sec"`
|
||||
DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"`
|
||||
DiskWritesPerSec float64 `perflib:"Disk Writes/sec"`
|
||||
PercentDiskReadTime float64 `perflib:"% Disk Read Time"`
|
||||
PercentDiskWriteTime float64 `perflib:"% Disk Write Time"`
|
||||
PercentFreeSpace float64 `perflib:"% Free Space_Base"`
|
||||
PercentFreeSpace_Base float64 `perflib:"Free Megabytes"`
|
||||
PercentIdleTime float64 `perflib:"% Idle Time"`
|
||||
SplitIOPerSec float64 `perflib:"Split IO/Sec"`
|
||||
AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"`
|
||||
AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"`
|
||||
AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"`
|
||||
Name string
|
||||
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`
|
||||
AvgDiskReadQueueLength float64 `perflib:"Avg. Disk Read Queue Length"`
|
||||
AvgDiskWriteQueueLength float64 `perflib:"Avg. Disk Write Queue Length"`
|
||||
DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"`
|
||||
DiskReadsPerSec float64 `perflib:"Disk Reads/sec"`
|
||||
DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"`
|
||||
DiskWritesPerSec float64 `perflib:"Disk Writes/sec"`
|
||||
PercentDiskReadTime float64 `perflib:"% Disk Read Time"`
|
||||
PercentDiskWriteTime float64 `perflib:"% Disk Write Time"`
|
||||
PercentFreeSpace float64 `perflib:"% Free Space_Base"`
|
||||
PercentFreeSpace_Base float64 `perflib:"Free Megabytes"`
|
||||
PercentIdleTime float64 `perflib:"% Idle Time"`
|
||||
SplitIOPerSec float64 `perflib:"Split IO/Sec"`
|
||||
AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"`
|
||||
AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"`
|
||||
AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"`
|
||||
}
|
||||
|
||||
func (c *LogicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []logicalDisk
|
||||
if err := unmarshalObject(ctx.perfObjects["LogicalDisk"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["LogicalDisk"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, volume := range dst {
|
||||
if volume.Name == "_Total" ||
|
||||
c.volumeBlacklistPattern.MatchString(volume.Name) ||
|
||||
!c.volumeWhitelistPattern.MatchString(volume.Name) {
|
||||
c.volumeExcludePattern.MatchString(volume.Name) ||
|
||||
!c.volumeIncludePattern.MatchString(volume.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -206,6 +281,20 @@ func (c *LogicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AvgReadQueue,
|
||||
prometheus.GaugeValue,
|
||||
volume.AvgDiskReadQueueLength*ticksToSecondsScaleFactor,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AvgWriteQueue,
|
||||
prometheus.GaugeValue,
|
||||
volume.AvgDiskWriteQueueLength*ticksToSecondsScaleFactor,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
|
||||
13
collector/logical_disk_test.go
Normal file
13
collector/logical_disk_test.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkLogicalDiskCollector(b *testing.B) {
|
||||
// Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all disks.
|
||||
localVolumeInclude := ".+"
|
||||
volumeInclude = &localVolumeInclude
|
||||
|
||||
benchmarkCollector(b, "logical_disk", newLogicalDiskCollector)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -5,25 +6,25 @@ package collector
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("logon", NewLogonCollector)
|
||||
}
|
||||
|
||||
// A LogonCollector is a Prometheus collector for WMI metrics
|
||||
type LogonCollector struct {
|
||||
logger log.Logger
|
||||
LogonType *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewLogonCollector ...
|
||||
func NewLogonCollector() (Collector, error) {
|
||||
// newLogonCollector ...
|
||||
func newLogonCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "logon"
|
||||
|
||||
return &LogonCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
LogonType: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "logon_type"),
|
||||
"Number of active logon sessions (LogonSession.LogonType)",
|
||||
@@ -37,7 +38,7 @@ func NewLogonCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *LogonCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting user metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting user metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -51,7 +52,7 @@ type Win32_LogonSession struct {
|
||||
|
||||
func (c *LogonCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_LogonSession
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/logon_test.go
Normal file
10
collector/logon_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkLogonCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newLogonCollector)
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
// returns data points from Win32_PerfRawData_PerfOS_Memory
|
||||
// <add link to documentation here> - Win32_PerfRawData_PerfOS_Memory class
|
||||
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("memory", NewMemoryCollector, "Memory")
|
||||
}
|
||||
|
||||
// A MemoryCollector is a Prometheus collector for perflib Memory metrics
|
||||
type MemoryCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
AvailableBytes *prometheus.Desc
|
||||
CacheBytes *prometheus.Desc
|
||||
CacheBytesPeak *prometheus.Desc
|
||||
@@ -50,11 +50,13 @@ type MemoryCollector struct {
|
||||
WriteCopiesTotal *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewMemoryCollector ...
|
||||
func NewMemoryCollector() (Collector, error) {
|
||||
// newMemoryCollector ...
|
||||
func newMemoryCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "memory"
|
||||
|
||||
return &MemoryCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
AvailableBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "available_bytes"),
|
||||
"The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+
|
||||
@@ -76,7 +78,8 @@ func NewMemoryCollector() (Collector, error) {
|
||||
),
|
||||
CacheFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cache_faults_total"),
|
||||
"(CacheFaultsPersec)",
|
||||
"Number of faults which occur when a page sought in the file system cache is not found there and must be retrieved from elsewhere in memory (soft fault) "+
|
||||
"or from disk (hard fault) (Cache Faults/sec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
@@ -95,13 +98,14 @@ func NewMemoryCollector() (Collector, error) {
|
||||
DemandZeroFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "demand_zero_faults_total"),
|
||||
"The number of zeroed pages required to satisfy faults. Zeroed pages, pages emptied of previously stored data and filled with zeros, are a security"+
|
||||
" feature of Windows that prevent processes from seeing data stored by earlier processes that used the memory space (DemandZeroFaults)",
|
||||
" feature of Windows that prevent processes from seeing data stored by earlier processes that used the memory space (Demand Zero Faults/sec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
FreeAndZeroPageListBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "free_and_zero_page_list_bytes"),
|
||||
"(FreeAndZeroPageListBytes)",
|
||||
"The amount of physical memory, in bytes, that is assigned to the free and zero page lists. This memory does not contain cached data. It is immediately"+
|
||||
" available for allocation to a process or for system use (FreeAndZeroPageListBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
@@ -113,13 +117,14 @@ func NewMemoryCollector() (Collector, error) {
|
||||
),
|
||||
ModifiedPageListBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "modified_page_list_bytes"),
|
||||
"(ModifiedPageListBytes)",
|
||||
"The amount of physical memory, in bytes, that is assigned to the modified page list. This memory contains cached data and code that is not actively in "+
|
||||
"use by processes, the system and the system cache (ModifiedPageListBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PageFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"),
|
||||
"(PageFaultsPersec)",
|
||||
"Overall rate at which faulted pages are handled by the processor (Page Faults/sec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
@@ -161,14 +166,15 @@ func NewMemoryCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
PoolNonpagedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_bytes_total"),
|
||||
"(PoolNonpagedBytes)",
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_bytes"),
|
||||
"Number of bytes in the non-paged pool, an area of the system virtual memory that is used for objects that cannot be written to disk, but must "+
|
||||
"remain in physical memory as long as they are allocated (PoolNonpagedBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PoolPagedAllocsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_paged_allocs_total"),
|
||||
"(PoolPagedAllocs)",
|
||||
"Number of calls to allocate space in the paged pool, regardless of the amount of space allocated in each call (PoolPagedAllocs)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
@@ -180,67 +186,72 @@ func NewMemoryCollector() (Collector, error) {
|
||||
),
|
||||
PoolPagedResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_paged_resident_bytes"),
|
||||
"(PoolPagedResidentBytes)",
|
||||
"The size, in bytes, of the portion of the paged pool that is currently resident and active in physical memory. The paged pool is an area of the "+
|
||||
"system virtual memory that is used for objects that can be written to disk when they are not being used (PoolPagedResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
StandbyCacheCoreBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "standby_cache_core_bytes"),
|
||||
"(StandbyCacheCoreBytes)",
|
||||
"The amount of physical memory, in bytes, that is assigned to the core standby cache page lists. This memory contains cached data and code that is "+
|
||||
"not actively in use by processes, the system and the system cache (StandbyCacheCoreBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
StandbyCacheNormalPriorityBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "standby_cache_normal_priority_bytes"),
|
||||
"(StandbyCacheNormalPriorityBytes)",
|
||||
"The amount of physical memory, in bytes, that is assigned to the normal priority standby cache page lists. This memory contains cached data and "+
|
||||
"code that is not actively in use by processes, the system and the system cache (StandbyCacheNormalPriorityBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
StandbyCacheReserveBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "standby_cache_reserve_bytes"),
|
||||
"(StandbyCacheReserveBytes)",
|
||||
"The amount of physical memory, in bytes, that is assigned to the reserve standby cache page lists. This memory contains cached data and code "+
|
||||
"that is not actively in use by processes, the system and the system cache (StandbyCacheReserveBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemCacheResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_cache_resident_bytes"),
|
||||
"(SystemCacheResidentBytes)",
|
||||
"The size, in bytes, of the portion of the system file cache which is currently resident and active in physical memory (SystemCacheResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemCodeResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_code_resident_bytes"),
|
||||
"(SystemCodeResidentBytes)",
|
||||
"The size, in bytes, of the pageable operating system code that is currently resident and active in physical memory (SystemCodeResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemCodeTotalBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_code_total_bytes"),
|
||||
"(SystemCodeTotalBytes)",
|
||||
"The size, in bytes, of the pageable operating system code currently mapped into the system virtual address space (SystemCodeTotalBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemDriverResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_driver_resident_bytes"),
|
||||
"(SystemDriverResidentBytes)",
|
||||
"The size, in bytes, of the pageable physical memory being used by device drivers. It is the working set (physical memory area) of the drivers (SystemDriverResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemDriverTotalBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_driver_total_bytes"),
|
||||
"(SystemDriverTotalBytes)",
|
||||
"The size, in bytes, of the pageable virtual memory currently being used by device drivers. Pageable memory can be written to disk when it is not being used (SystemDriverTotalBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TransitionFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "transition_faults_total"),
|
||||
"(TransitionFaultsPersec)",
|
||||
"Number of faults rate at which page faults are resolved by recovering pages that were being used by another process sharing the page, or were on the "+
|
||||
"modified page list or the standby list, or were being written to disk at the time of the page fault (TransitionFaultsPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TransitionPagesRepurposedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "transition_pages_repurposed_total"),
|
||||
"(TransitionPagesRePurposedPersec)",
|
||||
"Transition Pages RePurposed is the rate at which the number of transition cache pages were reused for a different purpose (TransitionPagesRePurposedPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
@@ -257,7 +268,7 @@ func NewMemoryCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *MemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting memory metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting memory metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -302,7 +313,7 @@ type memory struct {
|
||||
|
||||
func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []memory
|
||||
if err := unmarshalObject(ctx.perfObjects["Memory"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["Memory"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -326,7 +337,7 @@ func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metri
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CacheFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].CacheFaultsPersec,
|
||||
)
|
||||
|
||||
@@ -344,7 +355,7 @@ func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metri
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DemandZeroFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].DemandZeroFaultsPersec,
|
||||
)
|
||||
|
||||
@@ -368,37 +379,37 @@ func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metri
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PageFaultsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPageReadsTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PageReadsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPagesReadTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PagesInputPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPagesWrittenTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PagesOutputPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPageOperationsTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PagesPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPageWritesTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PageWritesPersec,
|
||||
)
|
||||
|
||||
@@ -416,7 +427,7 @@ func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metri
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolPagedAllocsTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PoolPagedAllocs,
|
||||
)
|
||||
|
||||
@@ -482,19 +493,19 @@ func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metri
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TransitionFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].TransitionFaultsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TransitionPagesRepurposedTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].TransitionPagesRePurposedPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WriteCopiesTotal,
|
||||
prometheus.GaugeValue,
|
||||
prometheus.CounterValue,
|
||||
dst[0].WriteCopiesPersec,
|
||||
)
|
||||
|
||||
|
||||
9
collector/memory_test.go
Normal file
9
collector/memory_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMemoryCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "memory", newMemoryCollector)
|
||||
}
|
||||
1199
collector/mscluster_cluster.go
Normal file
1199
collector/mscluster_cluster.go
Normal file
File diff suppressed because it is too large
Load Diff
117
collector/mscluster_network.go
Normal file
117
collector/mscluster_network.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
// A MSCluster_NetworkCollector is a Prometheus collector for WMI MSCluster_Network metrics
|
||||
type MSCluster_NetworkCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
Characteristics *prometheus.Desc
|
||||
Flags *prometheus.Desc
|
||||
Metric *prometheus.Desc
|
||||
Role *prometheus.Desc
|
||||
State *prometheus.Desc
|
||||
}
|
||||
|
||||
func newMSCluster_NetworkCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "mscluster_network"
|
||||
return &MSCluster_NetworkCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
Characteristics: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "characteristics"),
|
||||
"Provides the characteristics of the network.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Flags: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "flags"),
|
||||
"Provides access to the flags set for the node. ",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Metric: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "metric"),
|
||||
"The metric of a cluster network (networks with lower values are used first). If this value is set, then the AutoMetric property is set to false.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Role: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "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 ",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
State: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "state"),
|
||||
"Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MSCluster_Network docs:
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
|
||||
type MSCluster_Network struct {
|
||||
Name string
|
||||
|
||||
Characteristics uint
|
||||
Flags uint
|
||||
Metric uint
|
||||
Role uint
|
||||
State uint
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *MSCluster_NetworkCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var dst []MSCluster_Network
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Characteristics,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Characteristics),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Flags,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Flags),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Metric,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Metric),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Role,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Role),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.State,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.State),
|
||||
v.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
252
collector/mscluster_node.go
Normal file
252
collector/mscluster_node.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
// A MSCluster_NodeCollector is a Prometheus collector for WMI MSCluster_Node metrics
|
||||
type MSCluster_NodeCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
BuildNumber *prometheus.Desc
|
||||
Characteristics *prometheus.Desc
|
||||
DetectedCloudPlatform *prometheus.Desc
|
||||
DynamicWeight *prometheus.Desc
|
||||
Flags *prometheus.Desc
|
||||
MajorVersion *prometheus.Desc
|
||||
MinorVersion *prometheus.Desc
|
||||
NeedsPreventQuorum *prometheus.Desc
|
||||
NodeDrainStatus *prometheus.Desc
|
||||
NodeHighestVersion *prometheus.Desc
|
||||
NodeLowestVersion *prometheus.Desc
|
||||
NodeWeight *prometheus.Desc
|
||||
State *prometheus.Desc
|
||||
StatusInformation *prometheus.Desc
|
||||
}
|
||||
|
||||
func newMSCluster_NodeCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "mscluster_node"
|
||||
return &MSCluster_NodeCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
BuildNumber: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "build_number"),
|
||||
"Provides access to the node's BuildNumber property.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Characteristics: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "characteristics"),
|
||||
"Provides access to the characteristics set for the node.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
DetectedCloudPlatform: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "detected_cloud_platform"),
|
||||
"(DetectedCloudPlatform)",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
DynamicWeight: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "dynamic_weight"),
|
||||
"The dynamic vote weight of the node adjusted by dynamic quorum feature.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Flags: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "flags"),
|
||||
"Provides access to the flags set for the node.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
MajorVersion: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "major_version"),
|
||||
"Provides access to the node's MajorVersion property, which specifies the major portion of the Windows version installed.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
MinorVersion: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "minor_version"),
|
||||
"Provides access to the node's MinorVersion property, which specifies the minor portion of the Windows version installed.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
NeedsPreventQuorum: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "needs_prevent_quorum"),
|
||||
"Whether the cluster service on that node should be started with prevent quorum flag.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
NodeDrainStatus: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "node_drain_status"),
|
||||
"The current node drain status of a node. 0: Not Initiated; 1: In Progress; 2: Completed; 3: Failed",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
NodeHighestVersion: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "node_highest_version"),
|
||||
"Provides access to the node's NodeHighestVersion property, which specifies the highest possible version of the cluster service with which the node can join or communicate.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
NodeLowestVersion: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "node_lowest_version"),
|
||||
"Provides access to the node's NodeLowestVersion property, which specifies the lowest possible version of the cluster service with which the node can join or communicate.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
NodeWeight: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "node_weight"),
|
||||
"The vote weight of the node.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
State: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "state"),
|
||||
"Returns the current state of a node. -1: Unknown; 0: Up; 1: Down; 2: Paused; 3: Joining",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
StatusInformation: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "status_information"),
|
||||
"The isolation or quarantine status of the node.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MSCluster_Node docs:
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node
|
||||
type MSCluster_Node struct {
|
||||
Name string
|
||||
|
||||
BuildNumber uint
|
||||
Characteristics uint
|
||||
DetectedCloudPlatform uint
|
||||
DynamicWeight uint
|
||||
Flags uint
|
||||
MajorVersion uint
|
||||
MinorVersion uint
|
||||
NeedsPreventQuorum uint
|
||||
NodeDrainStatus uint
|
||||
NodeHighestVersion uint
|
||||
NodeLowestVersion uint
|
||||
NodeWeight uint
|
||||
State uint
|
||||
StatusInformation uint
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *MSCluster_NodeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var dst []MSCluster_Node
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BuildNumber,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.BuildNumber),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Characteristics,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Characteristics),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DetectedCloudPlatform,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.DetectedCloudPlatform),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DynamicWeight,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.DynamicWeight),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Flags,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Flags),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MajorVersion,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.MajorVersion),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MinorVersion,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.MinorVersion),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NeedsPreventQuorum,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.NeedsPreventQuorum),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NodeDrainStatus,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.NodeDrainStatus),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NodeHighestVersion,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.NodeHighestVersion),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NodeLowestVersion,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.NodeLowestVersion),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NodeWeight,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.NodeWeight),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.State,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.State),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StatusInformation,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.StatusInformation),
|
||||
v.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
284
collector/mscluster_resource.go
Normal file
284
collector/mscluster_resource.go
Normal file
@@ -0,0 +1,284 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
// A MSCluster_ResourceCollector is a Prometheus collector for WMI MSCluster_Resource metrics
|
||||
type MSCluster_ResourceCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
Characteristics *prometheus.Desc
|
||||
DeadlockTimeout *prometheus.Desc
|
||||
EmbeddedFailureAction *prometheus.Desc
|
||||
Flags *prometheus.Desc
|
||||
IsAlivePollInterval *prometheus.Desc
|
||||
LooksAlivePollInterval *prometheus.Desc
|
||||
MonitorProcessId *prometheus.Desc
|
||||
PendingTimeout *prometheus.Desc
|
||||
ResourceClass *prometheus.Desc
|
||||
RestartAction *prometheus.Desc
|
||||
RestartDelay *prometheus.Desc
|
||||
RestartPeriod *prometheus.Desc
|
||||
RestartThreshold *prometheus.Desc
|
||||
RetryPeriodOnFailure *prometheus.Desc
|
||||
State *prometheus.Desc
|
||||
Subclass *prometheus.Desc
|
||||
}
|
||||
|
||||
func newMSCluster_ResourceCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "mscluster_resource"
|
||||
return &MSCluster_ResourceCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
Characteristics: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "characteristics"),
|
||||
"Provides the characteristics of the object.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
DeadlockTimeout: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "deadlock_timeout"),
|
||||
"Indicates the length of time to wait, in milliseconds, before declaring a deadlock in any call into a resource.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
EmbeddedFailureAction: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "embedded_failure_action"),
|
||||
"The time, in milliseconds, that a resource should remain in a failed state before the Cluster service attempts to restart it.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
Flags: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "flags"),
|
||||
"Provides access to the flags set for the object.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
IsAlivePollInterval: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "is_alive_poll_interval"),
|
||||
"Provides access to the resource's IsAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it is operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the IsAlivePollInterval property for the resource type associated with the resource.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
LooksAlivePollInterval: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "looks_alive_poll_interval"),
|
||||
"Provides access to the resource's LooksAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it appears operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the LooksAlivePollInterval property for the resource type associated with the resource.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
MonitorProcessId: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "monitor_process_id"),
|
||||
"Provides the process ID of the resource host service that is currently hosting the resource.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
PendingTimeout: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pending_timeout"),
|
||||
"Provides access to the resource's PendingTimeout property. If a resource cannot be brought online or taken offline in the number of milliseconds specified by the PendingTimeout property, the resource is forcibly terminated.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
ResourceClass: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "resource_class"),
|
||||
"Gets or sets the resource class of a resource. 0: Unknown; 1: Storage; 2: Network; 32768: Unknown ",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
RestartAction: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "restart_action"),
|
||||
"Provides access to the resource's RestartAction property, which is the action to be taken by the Cluster Service if the resource fails.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
RestartDelay: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "restart_delay"),
|
||||
"Indicates the time delay before a failed resource is restarted.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
RestartPeriod: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "restart_period"),
|
||||
"Provides access to the resource's RestartPeriod property, which is interval of time, in milliseconds, during which a specified number of restart attempts can be made on a nonresponsive resource.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
RestartThreshold: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "restart_threshold"),
|
||||
"Provides access to the resource's RestartThreshold property which is the maximum number of restart attempts that can be made on a resource within an interval defined by the RestartPeriod property before the Cluster Service initiates the action specified by the RestartAction property.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
RetryPeriodOnFailure: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "retry_period_on_failure"),
|
||||
"Provides access to the resource's RetryPeriodOnFailure property, which is the interval of time (in milliseconds) that a resource should remain in a failed state before the Cluster service attempts to restart it.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
State: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "state"),
|
||||
"The current state of the resource. -1: Unknown; 0: Inherited; 1: Initializing; 2: Online; 3: Offline; 4: Failed; 128: Pending; 129: Online Pending; 130: Offline Pending ",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
Subclass: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "subclass"),
|
||||
"Provides the list of references to nodes that can be the owner of this resource.",
|
||||
[]string{"type", "owner_group", "name"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MSCluster_Resource docs:
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource
|
||||
type MSCluster_Resource struct {
|
||||
Name string
|
||||
Type string
|
||||
OwnerGroup string
|
||||
|
||||
Characteristics uint
|
||||
DeadlockTimeout uint
|
||||
EmbeddedFailureAction uint
|
||||
Flags uint
|
||||
IsAlivePollInterval uint
|
||||
LooksAlivePollInterval uint
|
||||
MonitorProcessId uint
|
||||
PendingTimeout uint
|
||||
ResourceClass uint
|
||||
RestartAction uint
|
||||
RestartDelay uint
|
||||
RestartPeriod uint
|
||||
RestartThreshold uint
|
||||
RetryPeriodOnFailure uint
|
||||
State uint
|
||||
Subclass uint
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *MSCluster_ResourceCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var dst []MSCluster_Resource
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Characteristics,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Characteristics),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DeadlockTimeout,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.DeadlockTimeout),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.EmbeddedFailureAction,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.EmbeddedFailureAction),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Flags,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Flags),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IsAlivePollInterval,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.IsAlivePollInterval),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.LooksAlivePollInterval,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.LooksAlivePollInterval),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MonitorProcessId,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.MonitorProcessId),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PendingTimeout,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.PendingTimeout),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ResourceClass,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.ResourceClass),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RestartAction,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.RestartAction),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RestartDelay,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.RestartDelay),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RestartPeriod,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.RestartPeriod),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RestartThreshold,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.RestartThreshold),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RetryPeriodOnFailure,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.RetryPeriodOnFailure),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.State,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.State),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Subclass,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Subclass),
|
||||
v.Type, v.OwnerGroup, v.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
240
collector/mscluster_resourcegroup.go
Normal file
240
collector/mscluster_resourcegroup.go
Normal file
@@ -0,0 +1,240 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
// A MSCluster_ResourceGroupCollector is a Prometheus collector for WMI MSCluster_ResourceGroup metrics
|
||||
type MSCluster_ResourceGroupCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
AutoFailbackType *prometheus.Desc
|
||||
Characteristics *prometheus.Desc
|
||||
ColdStartSetting *prometheus.Desc
|
||||
DefaultOwner *prometheus.Desc
|
||||
FailbackWindowEnd *prometheus.Desc
|
||||
FailbackWindowStart *prometheus.Desc
|
||||
FailoverPeriod *prometheus.Desc
|
||||
FailoverThreshold *prometheus.Desc
|
||||
FaultDomain *prometheus.Desc
|
||||
Flags *prometheus.Desc
|
||||
GroupType *prometheus.Desc
|
||||
PlacementOptions *prometheus.Desc
|
||||
Priority *prometheus.Desc
|
||||
ResiliencyPeriod *prometheus.Desc
|
||||
State *prometheus.Desc
|
||||
}
|
||||
|
||||
func newMSCluster_ResourceGroupCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "mscluster_resourcegroup"
|
||||
return &MSCluster_ResourceGroupCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
AutoFailbackType: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "auto_failback_type"),
|
||||
"Provides access to the group's AutoFailbackType property.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Characteristics: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "characteristics"),
|
||||
"Provides the characteristics of the group.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
ColdStartSetting: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cold_start_setting"),
|
||||
"Indicates whether a group can start after a cluster cold start.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
DefaultOwner: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "default_owner"),
|
||||
"Number of the last node the resource group was activated on or explicitly moved to.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
FailbackWindowEnd: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "failback_window_end"),
|
||||
"The FailbackWindowEnd property provides the latest time that the group can be moved back to the node identified as its preferred node.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
FailbackWindowStart: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "failback_window_start"),
|
||||
"The FailbackWindowStart property provides the earliest time (that is, local time as kept by the cluster) that the group can be moved back to the node identified as its preferred node.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
FailoverPeriod: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "failover_period"),
|
||||
"The FailoverPeriod property specifies a number of hours during which a maximum number of failover attempts, specified by the FailoverThreshold property, can occur.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
FailoverThreshold: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "failover_threshold"),
|
||||
"The FailoverThreshold property specifies the maximum number of failover attempts.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Flags: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "flags"),
|
||||
"Provides access to the flags set for the group. ",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
GroupType: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "group_type"),
|
||||
"The Type of the resource group.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
Priority: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "priority"),
|
||||
"Priority value of the resource group",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
ResiliencyPeriod: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "resiliency_period"),
|
||||
"The resiliency period for this group, in seconds.",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
State: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "state"),
|
||||
"The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MSCluster_ResourceGroup docs:
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup
|
||||
type MSCluster_ResourceGroup struct {
|
||||
Name string
|
||||
|
||||
AutoFailbackType uint
|
||||
Characteristics uint
|
||||
ColdStartSetting uint
|
||||
DefaultOwner uint
|
||||
FailbackWindowEnd int
|
||||
FailbackWindowStart int
|
||||
FailoverPeriod uint
|
||||
FailoverThreshold uint
|
||||
Flags uint
|
||||
GroupType uint
|
||||
Priority uint
|
||||
ResiliencyPeriod uint
|
||||
State uint
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *MSCluster_ResourceGroupCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var dst []MSCluster_ResourceGroup
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AutoFailbackType,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.AutoFailbackType),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Characteristics,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Characteristics),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ColdStartSetting,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.ColdStartSetting),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DefaultOwner,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.DefaultOwner),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FailbackWindowEnd,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.FailbackWindowEnd),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FailbackWindowStart,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.FailbackWindowStart),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FailoverPeriod,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.FailoverPeriod),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FailoverThreshold,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.FailoverThreshold),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Flags,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Flags),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.GroupType,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.GroupType),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Priority,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.Priority),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ResiliencyPeriod,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.ResiliencyPeriod),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.State,
|
||||
prometheus.GaugeValue,
|
||||
float64(v.State),
|
||||
v.Name,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -5,22 +6,25 @@ package collector
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("msmq", NewMSMQCollector)
|
||||
}
|
||||
const (
|
||||
FlagMsmqWhereClause = "collector.msmq.msmq-where"
|
||||
)
|
||||
|
||||
var (
|
||||
msmqWhereClause = kingpin.Flag("collector.msmq.msmq-where", "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").String()
|
||||
msmqWhereClause *string
|
||||
)
|
||||
|
||||
// A Win32_PerfRawData_MSMQ_MSMQQueueCollector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics
|
||||
type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
BytesinJournalQueue *prometheus.Desc
|
||||
BytesinQueue *prometheus.Desc
|
||||
MessagesinJournalQueue *prometheus.Desc
|
||||
@@ -29,15 +33,23 @@ type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct {
|
||||
queryWhereClause string
|
||||
}
|
||||
|
||||
// newMSMQCollectorFlags ..
|
||||
func newMSMQCollectorFlags(app *kingpin.Application) {
|
||||
msmqWhereClause = app.Flag(FlagMsmqWhereClause, "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").String()
|
||||
}
|
||||
|
||||
// NewWin32_PerfRawData_MSMQ_MSMQQueueCollector ...
|
||||
func NewMSMQCollector() (Collector, error) {
|
||||
func newMSMQCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "msmq"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
if *msmqWhereClause == "" {
|
||||
log.Warn("No where-clause specified for msmq collector. This will generate a very large number of metrics!")
|
||||
_ = level.Warn(logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!")
|
||||
}
|
||||
|
||||
return &Win32_PerfRawData_MSMQ_MSMQQueueCollector{
|
||||
logger: logger,
|
||||
|
||||
BytesinJournalQueue: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_in_journal_queue"),
|
||||
"Size of queue journal in bytes",
|
||||
@@ -70,7 +82,7 @@ func NewMSMQCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting msmq metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting msmq metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -87,35 +99,33 @@ type Win32_PerfRawData_MSMQ_MSMQQueue struct {
|
||||
|
||||
func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_MSMQ_MSMQQueue
|
||||
q := queryAllWhere(&dst, c.queryWhereClause)
|
||||
q := queryAllWhere(&dst, c.queryWhereClause, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, msmq := range dst {
|
||||
|
||||
if msmq.Name == "Computer Queues" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesinJournalQueue,
|
||||
prometheus.GaugeValue,
|
||||
float64(msmq.BytesinJournalQueue),
|
||||
strings.ToLower(msmq.Name),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesinQueue,
|
||||
prometheus.GaugeValue,
|
||||
float64(msmq.BytesinQueue),
|
||||
strings.ToLower(msmq.Name),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MessagesinJournalQueue,
|
||||
prometheus.GaugeValue,
|
||||
float64(msmq.MessagesinJournalQueue),
|
||||
strings.ToLower(msmq.Name),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MessagesinQueue,
|
||||
prometheus.GaugeValue,
|
||||
|
||||
10
collector/msmq_test.go
Normal file
10
collector/msmq_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMsmqCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newMSMQCollector)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -10,27 +11,27 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagMssqlEnabledCollectors = "collectors.mssql.classes-enabled"
|
||||
FlagMssqlPrintCollectors = "collectors.mssql.class-print"
|
||||
)
|
||||
|
||||
var (
|
||||
mssqlEnabledCollectors = kingpin.Flag(
|
||||
"collectors.mssql.classes-enabled",
|
||||
"Comma-separated list of mssql WMI classes to use.").
|
||||
Default(mssqlAvailableClassCollectors()).String()
|
||||
mssqlEnabledCollectors *string
|
||||
|
||||
mssqlPrintCollectors = kingpin.Flag(
|
||||
"collectors.mssql.class-print",
|
||||
"If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.",
|
||||
).Bool()
|
||||
mssqlPrintCollectors *bool
|
||||
)
|
||||
|
||||
type mssqlInstancesType map[string]string
|
||||
|
||||
func getMSSQLInstances() mssqlInstancesType {
|
||||
func getMSSQLInstances(logger log.Logger) mssqlInstancesType {
|
||||
sqlInstances := make(mssqlInstancesType)
|
||||
|
||||
// in case querying the registry fails, return the default instance
|
||||
@@ -40,19 +41,19 @@ func getMSSQLInstances() mssqlInstancesType {
|
||||
regkey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL`
|
||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
log.Warn("Couldn't open registry to determine SQL instances:", err)
|
||||
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine SQL instances", "err", err)
|
||||
return sqlDefaultInstance
|
||||
}
|
||||
defer func() {
|
||||
err = k.Close()
|
||||
if err != nil {
|
||||
log.Warnf("Failed to close registry key: %v", err)
|
||||
_ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
instanceNames, err := k.ReadValueNames(0)
|
||||
if err != nil {
|
||||
log.Warnf("Can't ReadSubKeyNames %#v", err)
|
||||
_ = level.Warn(logger).Log("msg", "Can't ReadSubKeyNames", "err", err)
|
||||
return sqlDefaultInstance
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ func getMSSQLInstances() mssqlInstancesType {
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Detected MSSQL Instances: %#v\n", sqlInstances)
|
||||
_ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected MSSQL Instances: %#v\n", sqlInstances))
|
||||
|
||||
return sqlInstances
|
||||
}
|
||||
@@ -70,7 +71,7 @@ func getMSSQLInstances() mssqlInstancesType {
|
||||
type mssqlCollectorsMap map[string]mssqlCollectorFunc
|
||||
|
||||
func mssqlAvailableClassCollectors() string {
|
||||
return "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions"
|
||||
return "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions,waitstats"
|
||||
}
|
||||
|
||||
func (c *MSSQLCollector) getMSSQLCollectors() mssqlCollectorsMap {
|
||||
@@ -86,6 +87,7 @@ func (c *MSSQLCollector) getMSSQLCollectors() mssqlCollectorsMap {
|
||||
mssqlCollectors["sqlstats"] = c.collectSQLStats
|
||||
mssqlCollectors["sqlerrors"] = c.collectSQLErrors
|
||||
mssqlCollectors["transactions"] = c.collectTransactions
|
||||
mssqlCollectors["waitstats"] = c.collectWaitStats
|
||||
|
||||
return mssqlCollectors
|
||||
}
|
||||
@@ -121,16 +123,16 @@ func mssqlGetPerfObjectName(sqlInstance string, collector string) string {
|
||||
suffix = "SQL Statistics"
|
||||
case "transactions":
|
||||
suffix = "Transactions"
|
||||
case "waitstats":
|
||||
suffix = "Wait Statistics"
|
||||
}
|
||||
return (prefix + suffix)
|
||||
}
|
||||
|
||||
func init() {
|
||||
registerCollector("mssql", NewMSSQLCollector)
|
||||
}
|
||||
|
||||
// A MSSQLCollector is a Prometheus collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics
|
||||
type MSSQLCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
// meta
|
||||
mssqlScrapeDurationDesc *prometheus.Desc
|
||||
mssqlScrapeSuccessDesc *prometheus.Desc
|
||||
@@ -382,18 +384,45 @@ type MSSQLCollector struct {
|
||||
TransactionsVersionStoreCreationUnits *prometheus.Desc
|
||||
TransactionsVersionStoreTruncationUnits *prometheus.Desc
|
||||
|
||||
// Win32_PerfRawData_{instance}_SQLServerWaitStatistics
|
||||
WaitStatsLockWaits *prometheus.Desc
|
||||
WaitStatsMemoryGrantQueueWaits *prometheus.Desc
|
||||
WaitStatsThreadSafeMemoryObjectsWaits *prometheus.Desc
|
||||
WaitStatsLogWriteWaits *prometheus.Desc
|
||||
WaitStatsLogBufferWaits *prometheus.Desc
|
||||
WaitStatsNetworkIOWaits *prometheus.Desc
|
||||
WaitStatsPageIOLatchWaits *prometheus.Desc
|
||||
WaitStatsPageLatchWaits *prometheus.Desc
|
||||
WaitStatsNonpageLatchWaits *prometheus.Desc
|
||||
WaitStatsWaitForTheWorkerWaits *prometheus.Desc
|
||||
WaitStatsWorkspaceSynchronizationWaits *prometheus.Desc
|
||||
WaitStatsTransactionOwnershipWaits *prometheus.Desc
|
||||
|
||||
mssqlInstances mssqlInstancesType
|
||||
mssqlCollectors mssqlCollectorsMap
|
||||
mssqlChildCollectorFailure int
|
||||
}
|
||||
|
||||
// NewMSSQLCollector ...
|
||||
func NewMSSQLCollector() (Collector, error) {
|
||||
// newMSSQLCollectorFlags ...
|
||||
func newMSSQLCollectorFlags(app *kingpin.Application) {
|
||||
mssqlEnabledCollectors = app.Flag(
|
||||
FlagMssqlEnabledCollectors,
|
||||
"Comma-separated list of mssql WMI classes to use.").
|
||||
Default(mssqlAvailableClassCollectors()).String()
|
||||
|
||||
mssqlPrintCollectors = app.Flag(
|
||||
FlagMssqlPrintCollectors,
|
||||
"If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.",
|
||||
).Bool()
|
||||
}
|
||||
|
||||
// newMSSQLCollector ...
|
||||
func newMSSQLCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "mssql"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
enabled := expandEnabledChildCollectors(*mssqlEnabledCollectors)
|
||||
mssqlInstances := getMSSQLInstances()
|
||||
mssqlInstances := getMSSQLInstances(logger)
|
||||
perfCounters := make([]string, 0, len(mssqlInstances)*len(enabled))
|
||||
for instance := range mssqlInstances {
|
||||
for _, c := range enabled {
|
||||
@@ -403,6 +432,7 @@ func NewMSSQLCollector() (Collector, error) {
|
||||
addPerfCounterDependencies(subsystem, perfCounters)
|
||||
|
||||
mssqlCollector := MSSQLCollector{
|
||||
logger: logger,
|
||||
// meta
|
||||
mssqlScrapeDurationDesc: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "collector_duration_seconds"),
|
||||
@@ -1789,6 +1819,91 @@ func NewMSSQLCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
|
||||
// Win32_PerfRawData_{instance}_SQLServerWaitStatistics
|
||||
WaitStatsLockWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_lock_waits"),
|
||||
"(WaitStats.LockWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsMemoryGrantQueueWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_memory_grant_queue_waits"),
|
||||
"(WaitStats.MemoryGrantQueueWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsThreadSafeMemoryObjectsWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_thread_safe_memory_objects_waits"),
|
||||
"(WaitStats.ThreadSafeMemoryObjectsWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsLogWriteWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_log_write_waits"),
|
||||
"(WaitStats.LogWriteWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsLogBufferWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_log_buffer_waits"),
|
||||
"(WaitStats.LogBufferWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsNetworkIOWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_network_io_waits"),
|
||||
"(WaitStats.NetworkIOWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsPageIOLatchWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_page_io_latch_waits"),
|
||||
"(WaitStats.PageIOLatchWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsPageLatchWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_page_latch_waits"),
|
||||
"(WaitStats.PageLatchWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsNonpageLatchWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_nonpage_latch_waits"),
|
||||
"(WaitStats.NonpageLatchWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsWaitForTheWorkerWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_wait_for_the_worker_waits"),
|
||||
"(WaitStats.WaitForTheWorkerWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsWorkspaceSynchronizationWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_workspace_synchronization_waits"),
|
||||
"(WaitStats.WorkspaceSynchronizationWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WaitStatsTransactionOwnershipWaits: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "waitstats_transaction_ownership_waits"),
|
||||
"(WaitStats.TransactionOwnershipWaits)",
|
||||
[]string{"mssql_instance", "item"},
|
||||
nil,
|
||||
),
|
||||
|
||||
mssqlInstances: mssqlInstances,
|
||||
}
|
||||
|
||||
@@ -1818,11 +1933,11 @@ func (c *MSSQLCollector) execute(ctx *ScrapeContext, name string, fn mssqlCollec
|
||||
var success float64
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("mssql class collector %s failed after %fs: %s", name, duration.Seconds(), err)
|
||||
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("mssql class collector %s failed after %fs", name, duration.Seconds()), "err", err)
|
||||
success = 0
|
||||
c.mssqlChildCollectorFailure++
|
||||
} else {
|
||||
log.Debugf("mssql class collector %s succeeded after %fs.", name, duration.Seconds())
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql class collector %s succeeded after %fs.", name, duration.Seconds()))
|
||||
success = 1
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
@@ -1855,7 +1970,7 @@ func (c *MSSQLCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// this shoud return an error if any? some? children errord.
|
||||
// this should return an error if any? some? children errord.
|
||||
if c.mssqlChildCollectorFailure > 0 {
|
||||
return errors.New("at least one child collector failed")
|
||||
}
|
||||
@@ -1913,9 +2028,9 @@ type mssqlAccessMethods struct {
|
||||
|
||||
func (c *MSSQLCollector) collectAccessMethods(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlAccessMethods
|
||||
log.Debugf("mssql_accessmethods collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_accessmethods collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "accessmethods")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "accessmethods")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2248,9 +2363,9 @@ type mssqlAvailabilityReplica struct {
|
||||
|
||||
func (c *MSSQLCollector) collectAvailabilityReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlAvailabilityReplica
|
||||
log.Debugf("mssql_availreplica collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_availreplica collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "availreplica")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "availreplica")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2356,9 +2471,9 @@ type mssqlBufferManager struct {
|
||||
|
||||
func (c *MSSQLCollector) collectBufferManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlBufferManager
|
||||
log.Debugf("mssql_bufman collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_bufman collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2560,9 +2675,9 @@ type mssqlDatabaseReplica struct {
|
||||
|
||||
func (c *MSSQLCollector) collectDatabaseReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlDatabaseReplica
|
||||
log.Debugf("mssql_dbreplica collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_dbreplica collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "dbreplica")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "dbreplica")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2799,9 +2914,9 @@ type mssqlDatabases struct {
|
||||
|
||||
func (c *MSSQLCollector) collectDatabases(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlDatabases
|
||||
log.Debugf("mssql_databases collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_databases collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "databases")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "databases")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3181,9 +3296,9 @@ type mssqlGeneralStatistics struct {
|
||||
|
||||
func (c *MSSQLCollector) collectGeneralStatistics(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlGeneralStatistics
|
||||
log.Debugf("mssql_genstats collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_genstats collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "genstats")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "genstats")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3376,9 +3491,9 @@ type mssqlLocks struct {
|
||||
|
||||
func (c *MSSQLCollector) collectLocks(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlLocks
|
||||
log.Debugf("mssql_locks collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_locks collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "locks")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "locks")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3474,9 +3589,9 @@ type mssqlMemoryManager struct {
|
||||
|
||||
func (c *MSSQLCollector) collectMemoryManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlMemoryManager
|
||||
log.Debugf("mssql_memmgr collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_memmgr collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "memmgr")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "memmgr")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3643,9 +3758,9 @@ type mssqlSQLStatistics struct {
|
||||
|
||||
func (c *MSSQLCollector) collectSQLStats(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlSQLStatistics
|
||||
log.Debugf("mssql_sqlstats collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_sqlstats collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlstats")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlstats")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3731,6 +3846,123 @@ func (c *MSSQLCollector) collectSQLStats(ctx *ScrapeContext, ch chan<- prometheu
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_MSSQLSERVER_SQLServerWaitStatistics docs:
|
||||
// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-wait-statistics-object
|
||||
type mssqlWaitStatistics struct {
|
||||
Name string
|
||||
WaitStatsLockWaits float64 `perflib:"Lock waits"`
|
||||
WaitStatsMemoryGrantQueueWaits float64 `perflib:"Memory grant queue waits"`
|
||||
WaitStatsThreadSafeMemoryObjectsWaits float64 `perflib:"Thread-safe memory objects waits"`
|
||||
WaitStatsLogWriteWaits float64 `perflib:"Log write waits"`
|
||||
WaitStatsLogBufferWaits float64 `perflib:"Log buffer waits"`
|
||||
WaitStatsNetworkIOWaits float64 `perflib:"Network IO waits"`
|
||||
WaitStatsPageIOLatchWaits float64 `perflib:"Page IO latch waits"`
|
||||
WaitStatsPageLatchWaits float64 `perflib:"Page latch waits"`
|
||||
WaitStatsNonpageLatchWaits float64 `perflib:"Non-Page latch waits"`
|
||||
WaitStatsWaitForTheWorkerWaits float64 `perflib:"Wait for the worker"`
|
||||
WaitStatsWorkspaceSynchronizationWaits float64 `perflib:"Workspace synchronization waits"`
|
||||
WaitStatsTransactionOwnershipWaits float64 `perflib:"Transaction ownership waits"`
|
||||
}
|
||||
|
||||
func (c *MSSQLCollector) collectWaitStats(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlWaitStatistics
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_waitstats collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "waitstats")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
item := v.Name
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsLockWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsLockWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsMemoryGrantQueueWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsMemoryGrantQueueWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsThreadSafeMemoryObjectsWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsThreadSafeMemoryObjectsWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsLogWriteWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsLogWriteWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsLogBufferWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsLogBufferWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsNetworkIOWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsNetworkIOWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsPageIOLatchWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsPageIOLatchWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsPageLatchWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsPageLatchWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsNonpageLatchWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsNonpageLatchWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsWaitForTheWorkerWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsWaitForTheWorkerWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsWorkspaceSynchronizationWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsWorkspaceSynchronizationWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WaitStatsTransactionOwnershipWaits,
|
||||
prometheus.CounterValue,
|
||||
v.WaitStatsTransactionOwnershipWaits,
|
||||
sqlInstance, item,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type mssqlSQLErrors struct {
|
||||
Name string
|
||||
ErrorsPersec float64 `perflib:"Errors/sec"`
|
||||
@@ -3740,9 +3972,9 @@ type mssqlSQLErrors struct {
|
||||
// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object
|
||||
func (c *MSSQLCollector) collectSQLErrors(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlSQLErrors
|
||||
log.Debugf("mssql_sqlerrors collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_sqlerrors collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlerrors")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlerrors")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3783,9 +4015,9 @@ type mssqlTransactions struct {
|
||||
// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-transactions-object
|
||||
func (c *MSSQLCollector) collectTransactions(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
|
||||
var dst []mssqlTransactions
|
||||
log.Debugf("mssql_transactions collector iterating sql instance %s.", sqlInstance)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_transactions collector iterating sql instance %s.", sqlInstance))
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "transactions")], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "transactions")], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
9
collector/mssql_test.go
Normal file
9
collector/mssql_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMSSQLCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "mssql", newMSSQLCollector)
|
||||
}
|
||||
122
collector/net.go
122
collector/net.go
@@ -1,37 +1,48 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("net", NewNetworkCollector, "Network Interface")
|
||||
}
|
||||
const (
|
||||
FlagNicOldExclude = "collector.net.nic-blacklist"
|
||||
FlagNicOldInclude = "collector.net.nic-whitelist"
|
||||
|
||||
FlagNicExclude = "collector.net.nic-exclude"
|
||||
FlagNicInclude = "collector.net.nic-include"
|
||||
)
|
||||
|
||||
var (
|
||||
nicWhitelist = kingpin.Flag(
|
||||
"collector.net.nic-whitelist",
|
||||
"Regexp of NIC:s to whitelist. NIC name must both match whitelist and not match blacklist to be included.",
|
||||
).Default(".+").String()
|
||||
nicBlacklist = kingpin.Flag(
|
||||
"collector.net.nic-blacklist",
|
||||
"Regexp of NIC:s to blacklist. NIC name must both match whitelist and not match blacklist to be included.",
|
||||
).Default("").String()
|
||||
nicOldInclude *string
|
||||
nicOldExclude *string
|
||||
|
||||
nicInclude *string
|
||||
nicExclude *string
|
||||
|
||||
nicIncludeSet bool
|
||||
nicExcludeSet bool
|
||||
|
||||
nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
|
||||
)
|
||||
|
||||
// A NetworkCollector is a Prometheus collector for Perflib Network Interface metrics
|
||||
type NetworkCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
BytesReceivedTotal *prometheus.Desc
|
||||
BytesSentTotal *prometheus.Desc
|
||||
BytesTotal *prometheus.Desc
|
||||
OutputQueueLength *prometheus.Desc
|
||||
PacketsOutboundDiscarded *prometheus.Desc
|
||||
PacketsOutboundErrors *prometheus.Desc
|
||||
PacketsTotal *prometheus.Desc
|
||||
@@ -42,15 +53,63 @@ type NetworkCollector struct {
|
||||
PacketsSentTotal *prometheus.Desc
|
||||
CurrentBandwidth *prometheus.Desc
|
||||
|
||||
nicWhitelistPattern *regexp.Regexp
|
||||
nicBlacklistPattern *regexp.Regexp
|
||||
nicIncludePattern *regexp.Regexp
|
||||
nicExcludePattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewNetworkCollector ...
|
||||
func NewNetworkCollector() (Collector, error) {
|
||||
// newNetworkCollectorFlags ...
|
||||
func newNetworkCollectorFlags(app *kingpin.Application) {
|
||||
nicInclude = app.Flag(
|
||||
FlagNicInclude,
|
||||
"Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.",
|
||||
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
|
||||
nicIncludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
nicExclude = app.Flag(
|
||||
FlagNicExclude,
|
||||
"Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.",
|
||||
).Default("").PreAction(func(c *kingpin.ParseContext) error {
|
||||
nicExcludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
nicOldInclude = app.Flag(
|
||||
FlagNicOldInclude,
|
||||
"DEPRECATED: Use --collector.net.nic-include",
|
||||
).Hidden().String()
|
||||
nicOldExclude = app.Flag(
|
||||
FlagNicOldExclude,
|
||||
"DEPRECATED: Use --collector.net.nic-exclude",
|
||||
).Hidden().String()
|
||||
|
||||
}
|
||||
|
||||
// newNetworkCollector ...
|
||||
func newNetworkCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "net"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
if *nicOldExclude != "" {
|
||||
if !nicExcludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.net.nic-blacklist is DEPRECATED and will be removed in a future release, use --collector.net.nic-exclude")
|
||||
*nicExclude = *nicOldExclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.net.nic-blacklist and --collector.net.nic-exclude are mutually exclusive")
|
||||
}
|
||||
}
|
||||
if *nicOldInclude != "" {
|
||||
if !nicIncludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.net.nic-whitelist is DEPRECATED and will be removed in a future release, use --collector.net.nic-include")
|
||||
*nicInclude = *nicOldInclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.net.nic-whitelist and --collector.net.nic-include are mutually exclusive")
|
||||
}
|
||||
}
|
||||
|
||||
return &NetworkCollector{
|
||||
logger: logger,
|
||||
BytesReceivedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"),
|
||||
"(Network.BytesReceivedPerSec)",
|
||||
@@ -69,6 +128,12 @@ func NewNetworkCollector() (Collector, error) {
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
OutputQueueLength: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "output_queue_length_packets"),
|
||||
"(Network.OutputQueueLength)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsOutboundDiscarded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded_total"),
|
||||
"(Network.PacketsOutboundDiscarded)",
|
||||
@@ -118,14 +183,14 @@ func NewNetworkCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
CurrentBandwidth: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "current_bandwidth"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "current_bandwidth_bytes"),
|
||||
"(Network.CurrentBandwidth)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
|
||||
nicWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicWhitelist)),
|
||||
nicBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicBlacklist)),
|
||||
nicIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicInclude)),
|
||||
nicExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicExclude)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -133,7 +198,7 @@ func NewNetworkCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NetworkCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting net metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting net metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -152,6 +217,7 @@ type networkInterface struct {
|
||||
BytesSentPerSec float64 `perflib:"Bytes Sent/sec"`
|
||||
BytesTotalPerSec float64 `perflib:"Bytes Total/sec"`
|
||||
Name string
|
||||
OutputQueueLength float64 `perflib:"Output Queue Length"`
|
||||
PacketsOutboundDiscarded float64 `perflib:"Packets Outbound Discarded"`
|
||||
PacketsOutboundErrors float64 `perflib:"Packets Outbound Errors"`
|
||||
PacketsPerSec float64 `perflib:"Packets/sec"`
|
||||
@@ -166,13 +232,13 @@ type networkInterface struct {
|
||||
func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []networkInterface
|
||||
|
||||
if err := unmarshalObject(ctx.perfObjects["Network Interface"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["Network Interface"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, nic := range dst {
|
||||
if c.nicBlacklistPattern.MatchString(nic.Name) ||
|
||||
!c.nicWhitelistPattern.MatchString(nic.Name) {
|
||||
if c.nicExcludePattern.MatchString(nic.Name) ||
|
||||
!c.nicIncludePattern.MatchString(nic.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -200,6 +266,12 @@ func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
nic.BytesTotalPerSec,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.OutputQueueLength,
|
||||
prometheus.GaugeValue,
|
||||
nic.OutputQueueLength,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsOutboundDiscarded,
|
||||
prometheus.CounterValue,
|
||||
@@ -251,7 +323,7 @@ func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentBandwidth,
|
||||
prometheus.GaugeValue,
|
||||
nic.CurrentBandwidth,
|
||||
nic.CurrentBandwidth/8,
|
||||
name,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNetworkToInstanceName(t *testing.T) {
|
||||
data := map[string]string{
|
||||
@@ -15,3 +18,10 @@ func TestNetworkToInstanceName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNetCollector(b *testing.B) {
|
||||
// Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces.
|
||||
localNicInclude := ".+"
|
||||
nicInclude = &localNicInclude
|
||||
benchmarkCollector(b, "net", newNetworkCollector)
|
||||
}
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrexceptions", NewNETFramework_NETCLRExceptionsCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRExceptionsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics
|
||||
type NETFramework_NETCLRExceptionsCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
NumberofExcepsThrown *prometheus.Desc
|
||||
NumberofFilters *prometheus.Desc
|
||||
NumberofFinallys *prometheus.Desc
|
||||
ThrowToCatchDepth *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRExceptionsCollector ...
|
||||
func NewNETFramework_NETCLRExceptionsCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRExceptionsCollector ...
|
||||
func newNETFramework_NETCLRExceptionsCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrexceptions"
|
||||
return &NETFramework_NETCLRExceptionsCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
NumberofExcepsThrown: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "exceptions_thrown_total"),
|
||||
"Displays the total number of exceptions thrown since the application started. This includes both .NET exceptions and unmanaged exceptions that are converted into .NET exceptions.",
|
||||
@@ -55,7 +57,7 @@ func NewNETFramework_NETCLRExceptionsCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRExceptionsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -73,7 +75,7 @@ type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
|
||||
|
||||
func (c *NETFramework_NETCLRExceptionsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/netframework_clrexceptions_test.go
Normal file
10
collector/netframework_clrexceptions_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNetFrameworkNETCLRExceptionsCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRExceptionsCollector)
|
||||
}
|
||||
@@ -1,28 +1,29 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrinterop", NewNETFramework_NETCLRInteropCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRInteropCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics
|
||||
type NETFramework_NETCLRInteropCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
NumberofCCWs *prometheus.Desc
|
||||
Numberofmarshalling *prometheus.Desc
|
||||
NumberofStubs *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRInteropCollector ...
|
||||
func NewNETFramework_NETCLRInteropCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRInteropCollector ...
|
||||
func newNETFramework_NETCLRInteropCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrinterop"
|
||||
return &NETFramework_NETCLRInteropCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
NumberofCCWs: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "com_callable_wrappers_total"),
|
||||
"Displays the current number of COM callable wrappers (CCWs). A CCW is a proxy for a managed object being referenced from an unmanaged COM client.",
|
||||
@@ -48,7 +49,7 @@ func NewNETFramework_NETCLRInteropCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRInteropCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrinterop metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrinterop metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -66,7 +67,7 @@ type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
|
||||
|
||||
func (c *NETFramework_NETCLRInteropCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/netframework_clrinterop_test.go
Normal file
10
collector/netframework_clrinterop_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRInteropCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRInteropCollector)
|
||||
}
|
||||
@@ -1,29 +1,30 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrjit", NewNETFramework_NETCLRJitCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRJitCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics
|
||||
type NETFramework_NETCLRJitCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
NumberofMethodsJitted *prometheus.Desc
|
||||
TimeinJit *prometheus.Desc
|
||||
StandardJitFailures *prometheus.Desc
|
||||
TotalNumberofILBytesJitted *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRJitCollector ...
|
||||
func NewNETFramework_NETCLRJitCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRJitCollector ...
|
||||
func newNETFramework_NETCLRJitCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrjit"
|
||||
return &NETFramework_NETCLRJitCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
NumberofMethodsJitted: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "jit_methods_total"),
|
||||
"Displays the total number of methods JIT-compiled since the application started. This counter does not include pre-JIT-compiled methods.",
|
||||
@@ -55,7 +56,7 @@ func NewNETFramework_NETCLRJitCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRJitCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrjit metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrjit metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -75,7 +76,7 @@ type Win32_PerfRawData_NETFramework_NETCLRJit struct {
|
||||
|
||||
func (c *NETFramework_NETCLRJitCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRJit
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/netframework_clrjit_test.go
Normal file
10
collector/netframework_clrjit_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRJitCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRJitCollector)
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrloading", NewNETFramework_NETCLRLoadingCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRLoadingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics
|
||||
type NETFramework_NETCLRLoadingCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
BytesinLoaderHeap *prometheus.Desc
|
||||
Currentappdomains *prometheus.Desc
|
||||
CurrentAssemblies *prometheus.Desc
|
||||
@@ -25,10 +25,11 @@ type NETFramework_NETCLRLoadingCollector struct {
|
||||
TotalNumberofLoadFailures *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRLoadingCollector ...
|
||||
func NewNETFramework_NETCLRLoadingCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRLoadingCollector ...
|
||||
func newNETFramework_NETCLRLoadingCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrloading"
|
||||
return &NETFramework_NETCLRLoadingCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
BytesinLoaderHeap: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "loader_heap_size_bytes"),
|
||||
"Displays the current size, in bytes, of the memory committed by the class loader across all application domains. Committed memory is the physical space reserved in the disk paging file.",
|
||||
@@ -90,7 +91,7 @@ func NewNETFramework_NETCLRLoadingCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRLoadingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrloading metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrloading metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -119,7 +120,7 @@ type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
|
||||
|
||||
func (c *NETFramework_NETCLRLoadingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/netframework_clrloading_test.go
Normal file
10
collector/netframework_clrloading_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRLoadingCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRLoadingCollector)
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrlocksandthreads", NewNETFramework_NETCLRLocksAndThreadsCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRLocksAndThreadsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics
|
||||
type NETFramework_NETCLRLocksAndThreadsCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
CurrentQueueLength *prometheus.Desc
|
||||
NumberofcurrentlogicalThreads *prometheus.Desc
|
||||
NumberofcurrentphysicalThreads *prometheus.Desc
|
||||
@@ -23,10 +23,11 @@ type NETFramework_NETCLRLocksAndThreadsCollector struct {
|
||||
TotalNumberofContentions *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRLocksAndThreadsCollector ...
|
||||
func NewNETFramework_NETCLRLocksAndThreadsCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRLocksAndThreadsCollector ...
|
||||
func newNETFramework_NETCLRLocksAndThreadsCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrlocksandthreads"
|
||||
return &NETFramework_NETCLRLocksAndThreadsCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
CurrentQueueLength: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "current_queue_length"),
|
||||
"Displays the total number of threads that are currently waiting to acquire a managed lock in the application.",
|
||||
@@ -76,7 +77,7 @@ func NewNETFramework_NETCLRLocksAndThreadsCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRLocksAndThreadsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -99,7 +100,7 @@ type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
|
||||
|
||||
func (c *NETFramework_NETCLRLocksAndThreadsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/netframework_clrlocksandthreads_test.go
Normal file
10
collector/netframework_clrlocksandthreads_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRLocksAndThreadsCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRLocksAndThreadsCollector)
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrmemory", NewNETFramework_NETCLRMemoryCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRMemoryCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics
|
||||
type NETFramework_NETCLRMemoryCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
AllocatedBytes *prometheus.Desc
|
||||
FinalizationSurvivors *prometheus.Desc
|
||||
HeapSize *prometheus.Desc
|
||||
@@ -31,10 +31,11 @@ type NETFramework_NETCLRMemoryCollector struct {
|
||||
PromotedMemoryfromGen1 *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRMemoryCollector ...
|
||||
func NewNETFramework_NETCLRMemoryCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRMemoryCollector ...
|
||||
func newNETFramework_NETCLRMemoryCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrmemory"
|
||||
return &NETFramework_NETCLRMemoryCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
AllocatedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "allocated_bytes_total"),
|
||||
"Displays the total number of bytes allocated on the garbage collection heap.",
|
||||
@@ -114,7 +115,7 @@ func NewNETFramework_NETCLRMemoryCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRMemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrmemory metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrmemory metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -123,26 +124,31 @@ func (c *NETFramework_NETCLRMemoryCollector) Collect(ctx *ScrapeContext, ch chan
|
||||
type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
|
||||
Name string
|
||||
|
||||
AllocatedBytesPersec uint64
|
||||
FinalizationSurvivors uint64
|
||||
Frequency_PerfTime uint64
|
||||
Gen0heapsize uint64
|
||||
Gen0PromotedBytesPerSec uint64
|
||||
Gen1heapsize uint64
|
||||
Gen1PromotedBytesPerSec uint64
|
||||
Gen2heapsize uint64
|
||||
LargeObjectHeapsize uint64
|
||||
NumberBytesinallHeaps uint64
|
||||
NumberGCHandles uint64
|
||||
NumberGen0Collections uint64
|
||||
NumberGen1Collections uint64
|
||||
NumberGen2Collections uint64
|
||||
NumberInducedGC uint64
|
||||
NumberofPinnedObjects uint64
|
||||
NumberofSinkBlocksinuse uint64
|
||||
NumberTotalcommittedBytes uint64
|
||||
NumberTotalreservedBytes uint64
|
||||
PercentTimeinGC uint32
|
||||
AllocatedBytesPersec uint64
|
||||
FinalizationSurvivors uint64
|
||||
Frequency_PerfTime uint64
|
||||
Gen0heapsize uint64
|
||||
Gen0PromotedBytesPerSec uint64
|
||||
Gen1heapsize uint64
|
||||
Gen1PromotedBytesPerSec uint64
|
||||
Gen2heapsize uint64
|
||||
LargeObjectHeapsize uint64
|
||||
NumberBytesinallHeaps uint64
|
||||
NumberGCHandles uint64
|
||||
NumberGen0Collections uint64
|
||||
NumberGen1Collections uint64
|
||||
NumberGen2Collections uint64
|
||||
NumberInducedGC uint64
|
||||
NumberofPinnedObjects uint64
|
||||
NumberofSinkBlocksinuse uint64
|
||||
NumberTotalcommittedBytes uint64
|
||||
NumberTotalreservedBytes uint64
|
||||
// PercentTimeinGC has countertype=PERF_RAW_FRACTION.
|
||||
// Formula: (100 * CounterValue) / BaseValue
|
||||
// By docs https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/ms974615(v=msdn.10)#perf_raw_fraction
|
||||
PercentTimeinGC uint32
|
||||
// BaseValue is just a "magic" number used to make the calculation come out right.
|
||||
PercentTimeinGC_base uint32
|
||||
ProcessID uint64
|
||||
PromotedFinalizationMemoryfromGen0 uint64
|
||||
PromotedMemoryfromGen0 uint64
|
||||
@@ -151,7 +157,7 @@ type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
|
||||
|
||||
func (c *NETFramework_NETCLRMemoryCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -293,7 +299,7 @@ func (c *NETFramework_NETCLRMemoryCollector) collect(ch chan<- prometheus.Metric
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TimeinGC,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.PercentTimeinGC)/float64(process.Frequency_PerfTime),
|
||||
float64(100*process.PercentTimeinGC)/float64(process.PercentTimeinGC_base),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
10
collector/netframework_clrmemory_test.go
Normal file
10
collector/netframework_clrmemory_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRMemoryCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRMemoryCollector)
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrremoting", NewNETFramework_NETCLRRemotingCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRRemotingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics
|
||||
type NETFramework_NETCLRRemotingCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
Channels *prometheus.Desc
|
||||
ContextBoundClassesLoaded *prometheus.Desc
|
||||
ContextBoundObjects *prometheus.Desc
|
||||
@@ -22,10 +22,11 @@ type NETFramework_NETCLRRemotingCollector struct {
|
||||
TotalRemoteCalls *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRRemotingCollector ...
|
||||
func NewNETFramework_NETCLRRemotingCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRRemotingCollector ...
|
||||
func newNETFramework_NETCLRRemotingCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrremoting"
|
||||
return &NETFramework_NETCLRRemotingCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
Channels: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "channels_total"),
|
||||
"Displays the total number of remoting channels registered across all application domains since application started.",
|
||||
@@ -69,7 +70,7 @@ func NewNETFramework_NETCLRRemotingCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRRemotingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrremoting metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrremoting metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -89,7 +90,7 @@ type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
|
||||
|
||||
func (c *NETFramework_NETCLRRemotingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/netframework_clrremoting_test.go
Normal file
10
collector/netframework_clrremoting_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRRemotingCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRRemotingCollector)
|
||||
}
|
||||
@@ -1,29 +1,30 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("netframework_clrsecurity", NewNETFramework_NETCLRSecurityCollector)
|
||||
}
|
||||
|
||||
// A NETFramework_NETCLRSecurityCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics
|
||||
type NETFramework_NETCLRSecurityCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
NumberLinkTimeChecks *prometheus.Desc
|
||||
TimeinRTchecks *prometheus.Desc
|
||||
StackWalkDepth *prometheus.Desc
|
||||
TotalRuntimeChecks *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRSecurityCollector ...
|
||||
func NewNETFramework_NETCLRSecurityCollector() (Collector, error) {
|
||||
// newNETFramework_NETCLRSecurityCollector ...
|
||||
func newNETFramework_NETCLRSecurityCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "netframework_clrsecurity"
|
||||
return &NETFramework_NETCLRSecurityCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
NumberLinkTimeChecks: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "link_time_checks_total"),
|
||||
"Displays the total number of link-time code access security checks since the application started.",
|
||||
@@ -55,7 +56,7 @@ func NewNETFramework_NETCLRSecurityCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *NETFramework_NETCLRSecurityCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -74,7 +75,7 @@ type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
|
||||
|
||||
func (c *NETFramework_NETCLRSecurityCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
|
||||
q := queryAll(&dst)
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
collector/netframework_clrsecurity_test.go
Normal file
10
collector/netframework_clrsecurity_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRSecurityCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newNETFramework_NETCLRSecurityCollector)
|
||||
}
|
||||
425
collector/nps.go
Normal file
425
collector/nps.go
Normal file
@@ -0,0 +1,425 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
// A npsCollector is a Prometheus collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics
|
||||
|
||||
type npsCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
AccessAccepts *prometheus.Desc
|
||||
AccessChallenges *prometheus.Desc
|
||||
AccessRejects *prometheus.Desc
|
||||
AccessRequests *prometheus.Desc
|
||||
AccessBadAuthenticators *prometheus.Desc
|
||||
AccessDroppedPackets *prometheus.Desc
|
||||
AccessInvalidRequests *prometheus.Desc
|
||||
AccessMalformedPackets *prometheus.Desc
|
||||
AccessPacketsReceived *prometheus.Desc
|
||||
AccessPacketsSent *prometheus.Desc
|
||||
AccessServerResetTime *prometheus.Desc
|
||||
AccessServerUpTime *prometheus.Desc
|
||||
AccessUnknownType *prometheus.Desc
|
||||
|
||||
AccountingRequests *prometheus.Desc
|
||||
AccountingResponses *prometheus.Desc
|
||||
AccountingBadAuthenticators *prometheus.Desc
|
||||
AccountingDroppedPackets *prometheus.Desc
|
||||
AccountingInvalidRequests *prometheus.Desc
|
||||
AccountingMalformedPackets *prometheus.Desc
|
||||
AccountingNoRecord *prometheus.Desc
|
||||
AccountingPacketsReceived *prometheus.Desc
|
||||
AccountingPacketsSent *prometheus.Desc
|
||||
AccountingServerResetTime *prometheus.Desc
|
||||
AccountingServerUpTime *prometheus.Desc
|
||||
AccountingUnknownType *prometheus.Desc
|
||||
}
|
||||
|
||||
func newNPSCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "nps"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
return &npsCollector{
|
||||
logger: logger,
|
||||
AccessAccepts: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_accepts"),
|
||||
"(AccessAccepts)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessChallenges: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_challenges"),
|
||||
"(AccessChallenges)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessRejects: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_rejects"),
|
||||
"(AccessRejects)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_requests"),
|
||||
"(AccessRequests)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessBadAuthenticators: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_bad_authenticators"),
|
||||
"(BadAuthenticators)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessDroppedPackets: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_dropped_packets"),
|
||||
"(DroppedPackets)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessInvalidRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_invalid_requests"),
|
||||
"(InvalidRequests)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessMalformedPackets: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_malformed_packets"),
|
||||
"(MalformedPackets)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessPacketsReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_packets_received"),
|
||||
"(PacketsReceived)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessPacketsSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_packets_sent"),
|
||||
"(PacketsSent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessServerResetTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_server_reset_time"),
|
||||
"(ServerResetTime)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessServerUpTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_server_up_time"),
|
||||
"(ServerUpTime)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccessUnknownType: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "access_unknown_type"),
|
||||
"(UnknownType)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
|
||||
AccountingRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_requests"),
|
||||
"(AccountingRequests)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingResponses: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_responses"),
|
||||
"(AccountingResponses)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingBadAuthenticators: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_bad_authenticators"),
|
||||
"(BadAuthenticators)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingDroppedPackets: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_dropped_packets"),
|
||||
"(DroppedPackets)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingInvalidRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_invalid_requests"),
|
||||
"(InvalidRequests)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingMalformedPackets: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_malformed_packets"),
|
||||
"(MalformedPackets)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingNoRecord: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_no_record"),
|
||||
"(NoRecord)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingPacketsReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_packets_received"),
|
||||
"(PacketsReceived)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingPacketsSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_packets_sent"),
|
||||
"(PacketsSent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingServerResetTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_server_reset_time"),
|
||||
"(ServerResetTime)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingServerUpTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_server_up_time"),
|
||||
"(ServerUpTime)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AccountingUnknownType: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "accounting_unknown_type"),
|
||||
"(UnknownType)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *npsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.CollectAccept(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("failed collecting NPS accept data: %s %v", desc, err))
|
||||
return err
|
||||
}
|
||||
if desc, err := c.CollectAccounting(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("failed collecting NPS accounting data: %s %v", desc, err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_IAS_NPSAuthenticationServer docs:
|
||||
// at the moment there is no Microsoft documentation
|
||||
type Win32_PerfRawData_IAS_NPSAuthenticationServer struct {
|
||||
Name string
|
||||
|
||||
AccessAccepts uint32
|
||||
AccessChallenges uint32
|
||||
AccessRejects uint32
|
||||
AccessRequests uint32
|
||||
AccessBadAuthenticators uint32
|
||||
AccessDroppedPackets uint32
|
||||
AccessInvalidRequests uint32
|
||||
AccessMalformedPackets uint32
|
||||
AccessPacketsReceived uint32
|
||||
AccessPacketsSent uint32
|
||||
AccessServerResetTime uint32
|
||||
AccessServerUpTime uint32
|
||||
AccessUnknownType uint32
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_IAS_NPSAccountingServer struct {
|
||||
Name string
|
||||
|
||||
AccountingRequests uint32
|
||||
AccountingResponses uint32
|
||||
AccountingBadAuthenticators uint32
|
||||
AccountingDroppedPackets uint32
|
||||
AccountingInvalidRequests uint32
|
||||
AccountingMalformedPackets uint32
|
||||
AccountingNoRecord uint32
|
||||
AccountingPacketsReceived uint32
|
||||
AccountingPacketsSent uint32
|
||||
AccountingServerResetTime uint32
|
||||
AccountingServerUpTime uint32
|
||||
AccountingUnknownType uint32
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *npsCollector) CollectAccept(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessAccepts,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessAccepts),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessChallenges,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessChallenges),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessRejects,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessRejects),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessRequests,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessRequests),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessBadAuthenticators,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessBadAuthenticators),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessDroppedPackets,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessDroppedPackets),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessInvalidRequests,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessInvalidRequests),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessMalformedPackets,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessMalformedPackets),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessPacketsReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessPacketsReceived),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessPacketsSent,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessPacketsSent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessServerResetTime,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessServerResetTime),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessServerUpTime,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessServerUpTime),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccessUnknownType,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccessUnknownType),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *npsCollector) CollectAccounting(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_IAS_NPSAccountingServer
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingRequests,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingRequests),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingResponses,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingResponses),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingBadAuthenticators,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingBadAuthenticators),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingDroppedPackets,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingDroppedPackets),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingInvalidRequests,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingInvalidRequests),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingMalformedPackets,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingMalformedPackets),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingNoRecord,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingNoRecord),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingPacketsReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingPacketsReceived),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingPacketsSent,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingPacketsSent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingServerResetTime,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingServerResetTime),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingServerUpTime,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingServerUpTime),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AccountingUnknownType,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AccountingUnknownType),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
9
collector/nps_test.go
Normal file
9
collector/nps_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNPSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "nps", newNPSCollector)
|
||||
}
|
||||
171
collector/os.go
171
collector/os.go
@@ -1,22 +1,27 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus-community/windows_exporter/headers/netapi32"
|
||||
"github.com/prometheus-community/windows_exporter/headers/psapi"
|
||||
"github.com/prometheus-community/windows_exporter/headers/sysinfoapi"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("os", NewOSCollector)
|
||||
}
|
||||
|
||||
// A OSCollector is a Prometheus collector for WMI metrics
|
||||
type OSCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
OSInformation *prometheus.Desc
|
||||
PhysicalMemoryFreeBytes *prometheus.Desc
|
||||
PagingFreeBytes *prometheus.Desc
|
||||
@@ -32,15 +37,23 @@ type OSCollector struct {
|
||||
Timezone *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewOSCollector ...
|
||||
func NewOSCollector() (Collector, error) {
|
||||
type pagingFileCounter struct {
|
||||
Name string
|
||||
Usage float64 `perflib:"% Usage"`
|
||||
UsagePeak float64 `perflib:"% Usage Peak"`
|
||||
}
|
||||
|
||||
// newOSCollector ...
|
||||
func newOSCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "os"
|
||||
|
||||
return &OSCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
OSInformation: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "info"),
|
||||
"OperatingSystem.Caption, OperatingSystem.Version",
|
||||
[]string{"product", "version"},
|
||||
[]string{"product", "version", "major_version", "minor_version", "build_number"},
|
||||
nil,
|
||||
),
|
||||
PagingLimitBytes: prometheus.NewDesc(
|
||||
@@ -86,7 +99,7 @@ func NewOSCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
ProcessMemoryLimitBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "process_memory_limix_bytes"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "process_memory_limit_bytes"),
|
||||
"OperatingSystem.MaxProcessMemorySize",
|
||||
nil,
|
||||
nil,
|
||||
@@ -121,8 +134,8 @@ func NewOSCollector() (Collector, error) {
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *OSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting os metrics:", desc, err)
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("failed collecting os metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -146,41 +159,103 @@ type Win32_OperatingSystem struct {
|
||||
Version string
|
||||
}
|
||||
|
||||
func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_OperatingSystem
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
nwgi, err := netapi32.GetWorkstationInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
gmse, err := sysinfoapi.GlobalMemoryStatusEx()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
currentTime := time.Now()
|
||||
timezoneName, _ := currentTime.Zone()
|
||||
|
||||
// Get total allocation of paging files across all disks.
|
||||
memManKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management`, registry.QUERY_VALUE)
|
||||
defer memManKey.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pagingFiles, _, pagingErr := memManKey.GetStringsValue("ExistingPageFiles")
|
||||
// Get build number and product name from registry
|
||||
ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
|
||||
defer ntKey.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pn, _, err := ntKey.GetStringValue("ProductName")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bn, _, err := ntKey.GetStringValue("CurrentBuildNumber")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var fsipf float64
|
||||
for _, pagingFile := range pagingFiles {
|
||||
fileString := strings.ReplaceAll(pagingFile, `\??\`, "")
|
||||
file, err := os.Stat(fileString)
|
||||
// For unknown reasons, Windows doesn't always create a page file. Continue collection rather than aborting.
|
||||
if err != nil {
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("Failed to read page file (reason: %s): %s\n", err, fileString))
|
||||
} else {
|
||||
fsipf += float64(file.Size())
|
||||
}
|
||||
}
|
||||
|
||||
gpi, err := psapi.GetPerformanceInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pfc = make([]pagingFileCounter, 0)
|
||||
if err := unmarshalObject(ctx.perfObjects["Paging File"], &pfc, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get current page file usage.
|
||||
var pfbRaw float64
|
||||
for _, pageFile := range pfc {
|
||||
if strings.Contains(strings.ToLower(pageFile.Name), "_total") {
|
||||
continue
|
||||
}
|
||||
pfbRaw += pageFile.Usage
|
||||
}
|
||||
|
||||
// Subtract from total page file allocation on disk.
|
||||
pfb := fsipf - (pfbRaw * float64(gpi.PageSize))
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.OSInformation,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
dst[0].Caption,
|
||||
dst[0].Version,
|
||||
fmt.Sprintf("Microsoft %s", pn), // Caption
|
||||
fmt.Sprintf("%d.%d.%s", nwgi.VersionMajor, nwgi.VersionMinor, bn), // Version
|
||||
fmt.Sprintf("%d", nwgi.VersionMajor), // Major Version
|
||||
fmt.Sprintf("%d", nwgi.VersionMinor), // Minor Version
|
||||
bn, // Build number
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PhysicalMemoryFreeBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].FreePhysicalMemory*1024), // KiB -> bytes
|
||||
float64(gmse.AvailPhys),
|
||||
)
|
||||
|
||||
time := dst[0].LocalDateTime
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Time,
|
||||
prometheus.GaugeValue,
|
||||
float64(time.Unix()),
|
||||
float64(currentTime.Unix()),
|
||||
)
|
||||
|
||||
timezoneName, _ := time.Zone()
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Timezone,
|
||||
prometheus.GaugeValue,
|
||||
@@ -188,58 +263,64 @@ func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
|
||||
timezoneName,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PagingFreeBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].FreeSpaceInPagingFiles*1024), // KiB -> bytes
|
||||
)
|
||||
if pagingErr == nil {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PagingFreeBytes,
|
||||
prometheus.GaugeValue,
|
||||
pfb,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PagingLimitBytes,
|
||||
prometheus.GaugeValue,
|
||||
fsipf,
|
||||
)
|
||||
} else {
|
||||
_ = level.Debug(c.logger).Log("Could not find HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management key. windows_os_paging_free_bytes and windows_os_paging_limit_bytes will be omitted.")
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualMemoryFreeBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].FreeVirtualMemory*1024), // KiB -> bytes
|
||||
float64(gmse.AvailPageFile),
|
||||
)
|
||||
|
||||
// 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(dst[0].MaxNumberOfProcesses),
|
||||
float64(4294967295),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessMemoryLimitBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].MaxProcessMemorySize*1024), // KiB -> bytes
|
||||
float64(gmse.TotalVirtual),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Processes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].NumberOfProcesses),
|
||||
float64(gpi.ProcessCount),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Users,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].NumberOfUsers),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PagingLimitBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].SizeStoredInPagingFiles*1024), // KiB -> bytes
|
||||
float64(nwgi.LoggedOnUsers),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualMemoryBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TotalVirtualMemorySize*1024), // KiB -> bytes
|
||||
float64(gmse.TotalPageFile),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VisibleMemoryBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TotalVisibleMemorySize*1024), // KiB -> bytes
|
||||
float64(gmse.TotalPhys),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
|
||||
9
collector/os_test.go
Normal file
9
collector/os_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkOSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "os", newOSCollector)
|
||||
}
|
||||
@@ -4,16 +4,16 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
perflibCollector "github.com/leoluk/perflib_exporter/collector"
|
||||
"github.com/leoluk/perflib_exporter/perflib"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus-community/windows_exporter/perflib"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
)
|
||||
|
||||
var nametable = perflib.QueryNameTable("Counter 009") // Reads the names in English TODO: validate that the English names are always present
|
||||
|
||||
func MapCounterToIndex(name string) string {
|
||||
return strconv.Itoa(int(nametable.LookupIndex(name)))
|
||||
return strconv.Itoa(int(perflib.CounterNameTable.LookupIndex(name)))
|
||||
}
|
||||
|
||||
func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error) {
|
||||
@@ -29,7 +29,7 @@ func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error)
|
||||
return indexed, nil
|
||||
}
|
||||
|
||||
func unmarshalObject(obj *perflib.PerfObject, vs interface{}) error {
|
||||
func unmarshalObject(obj *perflib.PerfObject, vs interface{}, logger log.Logger) error {
|
||||
if obj == nil {
|
||||
return fmt.Errorf("counter not found")
|
||||
}
|
||||
@@ -67,10 +67,20 @@ func unmarshalObject(obj *perflib.PerfObject, vs interface{}) error {
|
||||
if tag == "" {
|
||||
continue
|
||||
}
|
||||
secondValue := false
|
||||
|
||||
st := strings.Split(tag, ",")
|
||||
tag = st[0]
|
||||
|
||||
for _, t := range st {
|
||||
if t == "secondvalue" {
|
||||
secondValue = true
|
||||
}
|
||||
}
|
||||
|
||||
ctr, found := counters[tag]
|
||||
if !found {
|
||||
log.Debugf("missing counter %q, have %v", tag, counterMapKeys(counters))
|
||||
_ = level.Debug(logger).Log("msg", fmt.Sprintf("missing counter %q, have %v", tag, counterMapKeys(counters)))
|
||||
continue
|
||||
}
|
||||
if !target.Field(i).CanSet() {
|
||||
@@ -80,10 +90,18 @@ func unmarshalObject(obj *perflib.PerfObject, vs interface{}) error {
|
||||
return fmt.Errorf("tagged field %v has wrong type %v, must be float64", f.Name, fieldType)
|
||||
}
|
||||
|
||||
if secondValue {
|
||||
if !ctr.Def.HasSecondValue {
|
||||
return fmt.Errorf("tagged field %v expected a SecondValue, which was not present", f.Name)
|
||||
}
|
||||
target.Field(i).SetFloat(float64(ctr.SecondValue))
|
||||
continue
|
||||
}
|
||||
|
||||
switch ctr.Def.CounterType {
|
||||
case perflibCollector.PERF_ELAPSED_TIME:
|
||||
case perflib.PERF_ELAPSED_TIME:
|
||||
target.Field(i).SetFloat(float64(ctr.Value-windowsEpoch) / float64(obj.Frequency))
|
||||
case perflibCollector.PERF_100NSEC_TIMER, perflibCollector.PERF_PRECISION_100NS_TIMER:
|
||||
case perflib.PERF_100NSEC_TIMER, perflib.PERF_PRECISION_100NS_TIMER:
|
||||
target.Field(i).SetFloat(float64(ctr.Value) * ticksToSecondsScaleFactor)
|
||||
default:
|
||||
target.Field(i).SetFloat(float64(ctr.Value))
|
||||
|
||||
@@ -4,13 +4,15 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
perflibCollector "github.com/leoluk/perflib_exporter/collector"
|
||||
"github.com/leoluk/perflib_exporter/perflib"
|
||||
"github.com/prometheus-community/windows_exporter/perflib"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
)
|
||||
|
||||
type simple struct {
|
||||
ValA float64 `perflib:"Something"`
|
||||
ValB float64 `perflib:"Something Else"`
|
||||
ValC float64 `perflib:"Something Else,secondvalue"`
|
||||
}
|
||||
|
||||
func TestUnmarshalPerflib(t *testing.T) {
|
||||
@@ -36,7 +38,7 @@ func TestUnmarshalPerflib(t *testing.T) {
|
||||
{
|
||||
Def: &perflib.PerfCounterDef{
|
||||
Name: "Something",
|
||||
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
|
||||
CounterType: perflib.PERF_COUNTER_COUNTER,
|
||||
},
|
||||
Value: 123,
|
||||
},
|
||||
@@ -56,22 +58,24 @@ func TestUnmarshalPerflib(t *testing.T) {
|
||||
{
|
||||
Def: &perflib.PerfCounterDef{
|
||||
Name: "Something",
|
||||
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
|
||||
CounterType: perflib.PERF_COUNTER_COUNTER,
|
||||
},
|
||||
Value: 123,
|
||||
},
|
||||
{
|
||||
Def: &perflib.PerfCounterDef{
|
||||
Name: "Something Else",
|
||||
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
|
||||
Name: "Something Else",
|
||||
CounterType: perflib.PERF_COUNTER_COUNTER,
|
||||
HasSecondValue: true,
|
||||
},
|
||||
Value: 256,
|
||||
Value: 256,
|
||||
SecondValue: 222,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedOutput: []simple{{ValA: 123, ValB: 256}},
|
||||
expectedOutput: []simple{{ValA: 123, ValB: 256, ValC: 222}},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
@@ -83,7 +87,7 @@ func TestUnmarshalPerflib(t *testing.T) {
|
||||
{
|
||||
Def: &perflib.PerfCounterDef{
|
||||
Name: "Something",
|
||||
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
|
||||
CounterType: perflib.PERF_COUNTER_COUNTER,
|
||||
},
|
||||
Value: 321,
|
||||
},
|
||||
@@ -94,7 +98,7 @@ func TestUnmarshalPerflib(t *testing.T) {
|
||||
{
|
||||
Def: &perflib.PerfCounterDef{
|
||||
Name: "Something",
|
||||
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
|
||||
CounterType: perflib.PERF_COUNTER_COUNTER,
|
||||
},
|
||||
Value: 231,
|
||||
},
|
||||
@@ -109,7 +113,7 @@ func TestUnmarshalPerflib(t *testing.T) {
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
output := make([]simple, 0)
|
||||
err := unmarshalObject(c.obj, &output)
|
||||
err := unmarshalObject(c.obj, &output, log.NewNopLogger())
|
||||
if err != nil && !c.expectError {
|
||||
t.Errorf("Did not expect error, got %q", err)
|
||||
}
|
||||
|
||||
@@ -1,35 +1,44 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("process", newProcessCollector, "Process")
|
||||
}
|
||||
const (
|
||||
FlagProcessOldExclude = "collector.process.blacklist"
|
||||
FlagProcessOldInclude = "collector.process.whitelist"
|
||||
|
||||
FlagProcessExclude = "collector.process.exclude"
|
||||
FlagProcessInclude = "collector.process.include"
|
||||
)
|
||||
|
||||
var (
|
||||
processWhitelist = kingpin.Flag(
|
||||
"collector.process.whitelist",
|
||||
"Regexp of processes to include. Process name must both match whitelist and not match blacklist to be included.",
|
||||
).Default(".*").String()
|
||||
processBlacklist = kingpin.Flag(
|
||||
"collector.process.blacklist",
|
||||
"Regexp of processes to exclude. Process name must both match whitelist and not match blacklist to be included.",
|
||||
).Default("").String()
|
||||
processOldInclude *string
|
||||
processOldExclude *string
|
||||
|
||||
processInclude *string
|
||||
processExclude *string
|
||||
|
||||
processIncludeSet bool
|
||||
processExcludeSet bool
|
||||
)
|
||||
|
||||
type processCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
StartTime *prometheus.Desc
|
||||
CPUTimeTotal *prometheus.Desc
|
||||
HandleCount *prometheus.Desc
|
||||
@@ -42,21 +51,70 @@ type processCollector struct {
|
||||
PrivateBytes *prometheus.Desc
|
||||
ThreadCount *prometheus.Desc
|
||||
VirtualBytes *prometheus.Desc
|
||||
WorkingSetPrivate *prometheus.Desc
|
||||
WorkingSetPeak *prometheus.Desc
|
||||
WorkingSet *prometheus.Desc
|
||||
|
||||
processWhitelistPattern *regexp.Regexp
|
||||
processBlacklistPattern *regexp.Regexp
|
||||
processIncludePattern *regexp.Regexp
|
||||
processExcludePattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// newProcessCollectorFlags ...
|
||||
func newProcessCollectorFlags(app *kingpin.Application) {
|
||||
processInclude = app.Flag(
|
||||
FlagProcessInclude,
|
||||
"Regexp of processes to include. Process name must both match include and not match exclude to be included.",
|
||||
).Default(".*").PreAction(func(c *kingpin.ParseContext) error {
|
||||
processIncludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
processExclude = app.Flag(
|
||||
FlagProcessExclude,
|
||||
"Regexp of processes to exclude. Process name must both match include and not match exclude to be included.",
|
||||
).Default("").PreAction(func(c *kingpin.ParseContext) error {
|
||||
processExcludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
processOldInclude = app.Flag(
|
||||
FlagProcessOldInclude,
|
||||
"DEPRECATED: Use --collector.process.include",
|
||||
).Hidden().String()
|
||||
processOldExclude = app.Flag(
|
||||
FlagProcessOldExclude,
|
||||
"DEPRECATED: Use --collector.process.exclude",
|
||||
).Hidden().String()
|
||||
}
|
||||
|
||||
// NewProcessCollector ...
|
||||
func newProcessCollector() (Collector, error) {
|
||||
func newProcessCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "process"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
if *processWhitelist == ".*" && *processBlacklist == "" {
|
||||
log.Warn("No filters specified for process collector. This will generate a very large number of metrics!")
|
||||
if *processOldExclude != "" {
|
||||
if !processExcludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.process.blacklist is DEPRECATED and will be removed in a future release, use --collector.process.exclude")
|
||||
*processExclude = *processOldExclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.process.blacklist and --collector.process.exclude are mutually exclusive")
|
||||
}
|
||||
}
|
||||
if *processOldInclude != "" {
|
||||
if !processIncludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.process.whitelist is DEPRECATED and will be removed in a future release, use --collector.process.include")
|
||||
*processInclude = *processOldInclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.process.whitelist and --collector.process.include are mutually exclusive")
|
||||
}
|
||||
}
|
||||
|
||||
if *processInclude == ".*" && *processExclude == "" {
|
||||
_ = level.Warn(logger).Log("msg", "No filters specified for process collector. This will generate a very large number of metrics!")
|
||||
}
|
||||
|
||||
return &processCollector{
|
||||
logger: logger,
|
||||
StartTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "start_time"),
|
||||
"Time of process start.",
|
||||
@@ -65,43 +123,43 @@ func newProcessCollector() (Collector, error) {
|
||||
),
|
||||
CPUTimeTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_time_total"),
|
||||
"Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user). An instruction is the basic unit of execution in a computer, a thread is the object that executes instructions, and a process is the object created when a program is run. Code executed to handle some hardware interrupts and trap conditions is included in this count.",
|
||||
"Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user).",
|
||||
[]string{"process", "process_id", "creating_process_id", "mode"},
|
||||
nil,
|
||||
),
|
||||
HandleCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "handle_count"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "handles"),
|
||||
"Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
IOBytesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "io_bytes_total"),
|
||||
"Bytes issued to I/O operations in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ",
|
||||
"Bytes issued to I/O operations in different modes (read, write, other).",
|
||||
[]string{"process", "process_id", "creating_process_id", "mode"},
|
||||
nil,
|
||||
),
|
||||
IOOperationsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "io_operations_total"),
|
||||
"I/O operations issued in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ",
|
||||
"I/O operations issued in different modes (read, write, other).",
|
||||
[]string{"process", "process_id", "creating_process_id", "mode"},
|
||||
nil,
|
||||
),
|
||||
PageFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"),
|
||||
"Page faults by the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. This can cause the page not to be fetched from disk if it is on the standby list and hence already in main memory, or if it is in use by another process with which the page is shared.",
|
||||
"Page faults by the threads executing in this process.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
PageFileBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes"),
|
||||
"Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.",
|
||||
"Current number of bytes this process has used in the paging file(s).",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
PoolBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_bytes"),
|
||||
"Pool Bytes is the last observed number of bytes in the paged or nonpaged pool. The nonpaged pool is an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. The paged pool is an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. Nonpaged pool bytes is calculated differently than paged pool bytes, so it might not equal the total of paged pool bytes.",
|
||||
"Pool Bytes is the last observed number of bytes in the paged or nonpaged pool.",
|
||||
[]string{"process", "process_id", "creating_process_id", "pool"},
|
||||
nil,
|
||||
),
|
||||
@@ -118,25 +176,37 @@ func newProcessCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
ThreadCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "thread_count"),
|
||||
"Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.",
|
||||
prometheus.BuildFQName(Namespace, subsystem, "threads"),
|
||||
"Number of threads currently active in this process.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
VirtualBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"),
|
||||
"Current size, in bytes, of the virtual address space that the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.",
|
||||
"Current size, in bytes, of the virtual address space that the process is using.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
WorkingSetPrivate: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "working_set_private_bytes"),
|
||||
"Size of the working set, in bytes, that is use for this process only and not shared nor shareable by other processes.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
WorkingSetPeak: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "working_set_peak_bytes"),
|
||||
"Maximum size, in bytes, of the Working Set of this process at any point in time. The Working Set is the set of memory pages touched recently by the threads in the process.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
WorkingSet: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "working_set"),
|
||||
"Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.",
|
||||
prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes"),
|
||||
"Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
processWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processWhitelist)),
|
||||
processBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processBlacklist)),
|
||||
processIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processInclude)),
|
||||
processExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processExclude)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -179,21 +249,21 @@ type WorkerProcess struct {
|
||||
|
||||
func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
data := make([]perflibProcess, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Process"], &data)
|
||||
err := unmarshalObject(ctx.perfObjects["Process"], &data, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dst_wp []WorkerProcess
|
||||
q_wp := queryAll(&dst_wp)
|
||||
q_wp := queryAll(&dst_wp, c.logger)
|
||||
if err := wmi.QueryNamespace(q_wp, &dst_wp, "root\\WebAdministration"); err != nil {
|
||||
log.Debugf("Could not query WebAdministration namespace for IIS worker processes: %v. Skipping", err)
|
||||
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("Could not query WebAdministration namespace for IIS worker processes: %v. Skipping", err))
|
||||
}
|
||||
|
||||
for _, process := range data {
|
||||
if process.Name == "_Total" ||
|
||||
c.processBlacklistPattern.MatchString(process.Name) ||
|
||||
!c.processWhitelistPattern.MatchString(process.Name) {
|
||||
c.processExcludePattern.MatchString(process.Name) ||
|
||||
!c.processIncludePattern.MatchString(process.Name) {
|
||||
continue
|
||||
}
|
||||
// Duplicate processes are suffixed # and an index number. Remove those.
|
||||
@@ -380,6 +450,24 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WorkingSetPrivate,
|
||||
prometheus.GaugeValue,
|
||||
process.WorkingSetPrivate,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WorkingSetPeak,
|
||||
prometheus.GaugeValue,
|
||||
process.WorkingSetPeak,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WorkingSet,
|
||||
prometheus.GaugeValue,
|
||||
|
||||
14
collector/process_test.go
Normal file
14
collector/process_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkProcessCollector(b *testing.B) {
|
||||
// Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all processes.
|
||||
localProcessInclude := ".+"
|
||||
processInclude = &localProcessInclude
|
||||
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newProcessCollector)
|
||||
}
|
||||
193
collector/prometheus.go
Normal file
193
collector/prometheus.go
Normal file
@@ -0,0 +1,193 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// Base metrics returned by Prometheus
|
||||
|
||||
var (
|
||||
scrapeDurationDesc = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, "exporter", "collector_duration_seconds"),
|
||||
"windows_exporter: Duration of a collection.",
|
||||
[]string{"collector"},
|
||||
nil,
|
||||
)
|
||||
scrapeSuccessDesc = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, "exporter", "collector_success"),
|
||||
"windows_exporter: Whether the collector was successful.",
|
||||
[]string{"collector"},
|
||||
nil,
|
||||
)
|
||||
scrapeTimeoutDesc = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, "exporter", "collector_timeout"),
|
||||
"windows_exporter: Whether the collector timed out.",
|
||||
[]string{"collector"},
|
||||
nil,
|
||||
)
|
||||
snapshotDuration = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, "exporter", "perflib_snapshot_duration_seconds"),
|
||||
"Duration of perflib snapshot capture",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
)
|
||||
|
||||
// Prometheus implements prometheus.Collector for a set of Windows collectors.
|
||||
type Prometheus struct {
|
||||
maxScrapeDuration time.Duration
|
||||
collectors map[string]Collector
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
// NewPrometheus returns a new Prometheus where the set of collectors must
|
||||
// return metrics within the given timeout.
|
||||
func NewPrometheus(timeout time.Duration, cs map[string]Collector, logger log.Logger) *Prometheus {
|
||||
return &Prometheus{
|
||||
maxScrapeDuration: timeout,
|
||||
collectors: cs,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// Describe sends all the descriptors of the collectors included to
|
||||
// the provided channel.
|
||||
func (coll *Prometheus) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- scrapeDurationDesc
|
||||
ch <- scrapeSuccessDesc
|
||||
}
|
||||
|
||||
type collectorOutcome int
|
||||
|
||||
const (
|
||||
pending collectorOutcome = iota
|
||||
success
|
||||
failed
|
||||
)
|
||||
|
||||
// Collect sends the collected metrics from each of the collectors to
|
||||
// prometheus.
|
||||
func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) {
|
||||
t := time.Now()
|
||||
cs := make([]string, 0, len(coll.collectors))
|
||||
for name := range coll.collectors {
|
||||
cs = append(cs, name)
|
||||
}
|
||||
scrapeContext, err := PrepareScrapeContext(cs)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
snapshotDuration,
|
||||
prometheus.GaugeValue,
|
||||
time.Since(t).Seconds(),
|
||||
)
|
||||
if err != nil {
|
||||
ch <- prometheus.NewInvalidMetric(scrapeSuccessDesc, fmt.Errorf("failed to prepare scrape: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(len(coll.collectors))
|
||||
collectorOutcomes := make(map[string]collectorOutcome)
|
||||
for name := range coll.collectors {
|
||||
collectorOutcomes[name] = pending
|
||||
}
|
||||
|
||||
metricsBuffer := make(chan prometheus.Metric)
|
||||
l := sync.Mutex{}
|
||||
finished := false
|
||||
go func() {
|
||||
for m := range metricsBuffer {
|
||||
l.Lock()
|
||||
if !finished {
|
||||
ch <- m
|
||||
}
|
||||
l.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
for name, c := range coll.collectors {
|
||||
go func(name string, c Collector) {
|
||||
defer wg.Done()
|
||||
outcome := execute(name, c, scrapeContext, metricsBuffer, coll.logger)
|
||||
l.Lock()
|
||||
if !finished {
|
||||
collectorOutcomes[name] = outcome
|
||||
}
|
||||
l.Unlock()
|
||||
}(name, c)
|
||||
}
|
||||
|
||||
allDone := make(chan struct{})
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(allDone)
|
||||
close(metricsBuffer)
|
||||
}()
|
||||
|
||||
// Wait until either all collectors finish, or timeout expires
|
||||
select {
|
||||
case <-allDone:
|
||||
case <-time.After(coll.maxScrapeDuration):
|
||||
}
|
||||
|
||||
l.Lock()
|
||||
finished = true
|
||||
|
||||
remainingCollectorNames := make([]string, 0)
|
||||
for name, outcome := range collectorOutcomes {
|
||||
var successValue, timeoutValue float64
|
||||
if outcome == pending {
|
||||
timeoutValue = 1.0
|
||||
remainingCollectorNames = append(remainingCollectorNames, name)
|
||||
}
|
||||
if outcome == success {
|
||||
successValue = 1.0
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
scrapeSuccessDesc,
|
||||
prometheus.GaugeValue,
|
||||
successValue,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
scrapeTimeoutDesc,
|
||||
prometheus.GaugeValue,
|
||||
timeoutValue,
|
||||
name,
|
||||
)
|
||||
}
|
||||
|
||||
if len(remainingCollectorNames) > 0 {
|
||||
_ = level.Warn(coll.logger).Log("msg", fmt.Sprintf("Collection timed out, still waiting for %v", remainingCollectorNames))
|
||||
}
|
||||
|
||||
l.Unlock()
|
||||
}
|
||||
|
||||
func execute(name string, c Collector, ctx *ScrapeContext, ch chan<- prometheus.Metric, logger log.Logger) collectorOutcome {
|
||||
t := time.Now()
|
||||
err := c.Collect(ctx, ch)
|
||||
duration := time.Since(t).Seconds()
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
scrapeDurationDesc,
|
||||
prometheus.GaugeValue,
|
||||
duration,
|
||||
name,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
_ = level.Error(logger).Log("msg", fmt.Sprintf("collector %s failed after %fs", name, duration), "err", err)
|
||||
return failed
|
||||
}
|
||||
_ = level.Debug(logger).Log("msg", fmt.Sprintf("collector %s succeeded after %fs.", name, duration))
|
||||
return success
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
@@ -5,20 +6,19 @@ package collector
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("remote_fx", NewRemoteFx, "RemoteFX Network", "RemoteFX Graphics")
|
||||
}
|
||||
|
||||
// A RemoteFxNetworkCollector is a Prometheus collector for
|
||||
// WMI Win32_PerfRawData_Counters_RemoteFXNetwork & Win32_PerfRawData_Counters_RemoteFXGraphics metrics
|
||||
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxnetwork/
|
||||
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxgraphics/
|
||||
|
||||
type RemoteFxCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
// net
|
||||
BaseTCPRTT *prometheus.Desc
|
||||
BaseUDPRTT *prometheus.Desc
|
||||
@@ -41,10 +41,12 @@ type RemoteFxCollector struct {
|
||||
SourceFramesPerSecond *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewRemoteFx ...
|
||||
func NewRemoteFx() (Collector, error) {
|
||||
// newRemoteFx ...
|
||||
func newRemoteFx(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "remote_fx"
|
||||
return &RemoteFxCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
|
||||
// net
|
||||
BaseTCPRTT: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_base_tcp_rtt_seconds"),
|
||||
@@ -60,7 +62,7 @@ func NewRemoteFx() (Collector, error) {
|
||||
),
|
||||
CurrentTCPBandwidth: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_bandwidth"),
|
||||
"TCP Bandwidth detected in bytes per seccond.",
|
||||
"TCP Bandwidth detected in bytes per second.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
@@ -157,11 +159,11 @@ func NewRemoteFx() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *RemoteFxCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collectRemoteFXNetworkCount(ctx, ch); err != nil {
|
||||
log.Error("failed collecting terminal services session count metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectRemoteFXGraphicsCounters(ctx, ch); err != nil {
|
||||
log.Error("failed collecting terminal services session count metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -183,7 +185,7 @@ type perflibRemoteFxNetwork struct {
|
||||
|
||||
func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
dst := make([]perflibRemoteFxNetwork, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["RemoteFX Network"], &dst)
|
||||
err := unmarshalObject(ctx.perfObjects["RemoteFX Network"], &dst, c.logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -273,7 +275,7 @@ type perflibRemoteFxGraphics struct {
|
||||
|
||||
func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
dst := make([]perflibRemoteFxGraphics, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["RemoteFX Graphics"], &dst)
|
||||
err := unmarshalObject(ctx.perfObjects["RemoteFX Graphics"], &dst, c.logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -345,7 +347,3 @@ func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext,
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func milliSecToSec(t float64) float64 {
|
||||
return t / 1000
|
||||
}
|
||||
|
||||
9
collector/remote_fx_test.go
Normal file
9
collector/remote_fx_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkRemoteFXCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "remote_fx", newRemoteFx)
|
||||
}
|
||||
401
collector/scheduled_task.go
Normal file
401
collector/scheduled_task.go
Normal file
@@ -0,0 +1,401 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
ole "github.com/go-ole/go-ole"
|
||||
"github.com/go-ole/go-ole/oleutil"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagScheduledTaskOldExclude = "collector.scheduled_task.blacklist"
|
||||
FlagScheduledTaskOldInclude = "collector.scheduled_task.whitelist"
|
||||
|
||||
FlagScheduledTaskExclude = "collector.scheduled_task.exclude"
|
||||
FlagScheduledTaskInclude = "collector.scheduled_task.include"
|
||||
)
|
||||
|
||||
var (
|
||||
taskOldExclude *string
|
||||
taskOldInclude *string
|
||||
|
||||
taskExclude *string
|
||||
taskInclude *string
|
||||
|
||||
taskIncludeSet bool
|
||||
taskExcludeSet bool
|
||||
)
|
||||
|
||||
type ScheduledTaskCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
LastResult *prometheus.Desc
|
||||
MissedRuns *prometheus.Desc
|
||||
State *prometheus.Desc
|
||||
|
||||
taskIncludePattern *regexp.Regexp
|
||||
taskExcludePattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// TaskState ...
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/taskschd/ne-taskschd-task_state
|
||||
type TaskState uint
|
||||
|
||||
type TaskResult uint
|
||||
|
||||
const (
|
||||
TASK_STATE_UNKNOWN TaskState = iota
|
||||
TASK_STATE_DISABLED
|
||||
TASK_STATE_QUEUED
|
||||
TASK_STATE_READY
|
||||
TASK_STATE_RUNNING
|
||||
TASK_RESULT_SUCCESS TaskResult = 0x0
|
||||
)
|
||||
|
||||
// RegisteredTask ...
|
||||
type ScheduledTask struct {
|
||||
Name string
|
||||
Path string
|
||||
Enabled bool
|
||||
State TaskState
|
||||
MissedRunsCount float64
|
||||
LastTaskResult TaskResult
|
||||
}
|
||||
|
||||
type ScheduledTasks []ScheduledTask
|
||||
|
||||
// newScheduledTask ...
|
||||
func newScheduledTaskFlags(app *kingpin.Application) {
|
||||
taskInclude = app.Flag(
|
||||
FlagScheduledTaskInclude,
|
||||
"Regexp of tasks to include. Task path must both match include and not match exclude to be included.",
|
||||
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
|
||||
taskIncludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
taskExclude = app.Flag(
|
||||
FlagScheduledTaskExclude,
|
||||
"Regexp of tasks to exclude. Task path must both match include and not match exclude to be included.",
|
||||
).Default("").PreAction(func(c *kingpin.ParseContext) error {
|
||||
taskExcludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
taskOldInclude = app.Flag(
|
||||
FlagScheduledTaskOldInclude,
|
||||
"DEPRECATED: Use --collector.scheduled_task.include",
|
||||
).Hidden().String()
|
||||
taskOldExclude = app.Flag(
|
||||
FlagScheduledTaskOldExclude,
|
||||
"DEPRECATED: Use --collector.scheduled_task.exclude",
|
||||
).Hidden().String()
|
||||
}
|
||||
|
||||
// newScheduledTask ...
|
||||
func newScheduledTask(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "scheduled_task"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
if *taskOldExclude != "" {
|
||||
if !taskExcludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.scheduled_task.blacklist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.exclude")
|
||||
*taskExclude = *taskOldExclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.scheduled_task.blacklist and --collector.scheduled_task.exclude are mutually exclusive")
|
||||
}
|
||||
}
|
||||
if *taskOldInclude != "" {
|
||||
if !taskIncludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.scheduled_task.whitelist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.include")
|
||||
*taskInclude = *taskOldInclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.scheduled_task.whitelist and --collector.scheduled_task.include are mutually exclusive")
|
||||
}
|
||||
}
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED)
|
||||
if err != nil {
|
||||
code := err.(*ole.OleError).Code()
|
||||
if code != ole.S_OK && code != S_FALSE {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
defer ole.CoUninitialize()
|
||||
|
||||
return &ScheduledTaskCollector{
|
||||
logger: logger,
|
||||
LastResult: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "last_result"),
|
||||
"The result that was returned the last time the registered task was run",
|
||||
[]string{"task"},
|
||||
nil,
|
||||
),
|
||||
|
||||
MissedRuns: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "missed_runs"),
|
||||
"The number of times the registered task missed a scheduled run",
|
||||
[]string{"task"},
|
||||
nil,
|
||||
),
|
||||
|
||||
State: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "state"),
|
||||
"The current state of a scheduled task",
|
||||
[]string{"task", "state"},
|
||||
nil,
|
||||
),
|
||||
|
||||
taskIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskInclude)),
|
||||
taskExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskExclude)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *ScheduledTaskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("failed collecting user metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var TASK_STATES = []string{"disabled", "queued", "ready", "running", "unknown"}
|
||||
|
||||
func (c *ScheduledTaskCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
scheduledTasks, err := getScheduledTasks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, task := range scheduledTasks {
|
||||
if c.taskExcludePattern.MatchString(task.Path) ||
|
||||
!c.taskIncludePattern.MatchString(task.Path) {
|
||||
continue
|
||||
}
|
||||
|
||||
lastResult := 0.0
|
||||
if task.LastTaskResult == TASK_RESULT_SUCCESS {
|
||||
lastResult = 1.0
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.LastResult,
|
||||
prometheus.GaugeValue,
|
||||
lastResult,
|
||||
task.Path,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MissedRuns,
|
||||
prometheus.GaugeValue,
|
||||
task.MissedRunsCount,
|
||||
task.Path,
|
||||
)
|
||||
|
||||
for _, state := range TASK_STATES {
|
||||
var stateValue float64
|
||||
|
||||
if strings.ToLower(task.State.String()) == state {
|
||||
stateValue = 1.0
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.State,
|
||||
prometheus.GaugeValue,
|
||||
stateValue,
|
||||
task.Path,
|
||||
state,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
const SCHEDULED_TASK_PROGRAM_ID = "Schedule.Service.1"
|
||||
|
||||
// S_FALSE is returned by CoInitialize if it was already called on this thread.
|
||||
const S_FALSE = 0x00000001
|
||||
|
||||
func getScheduledTasks() (scheduledTasks ScheduledTasks, err error) {
|
||||
schedClassID, err := ole.ClassIDFrom(SCHEDULED_TASK_PROGRAM_ID)
|
||||
if err != nil {
|
||||
return scheduledTasks, err
|
||||
}
|
||||
|
||||
taskSchedulerObj, err := ole.CreateInstance(schedClassID, nil)
|
||||
if err != nil || taskSchedulerObj == nil {
|
||||
return scheduledTasks, err
|
||||
}
|
||||
defer taskSchedulerObj.Release()
|
||||
|
||||
taskServiceObj := taskSchedulerObj.MustQueryInterface(ole.IID_IDispatch)
|
||||
_, err = oleutil.CallMethod(taskServiceObj, "Connect")
|
||||
if err != nil {
|
||||
return scheduledTasks, err
|
||||
}
|
||||
defer taskServiceObj.Release()
|
||||
|
||||
res, err := oleutil.CallMethod(taskServiceObj, "GetFolder", `\`)
|
||||
if err != nil {
|
||||
return scheduledTasks, err
|
||||
}
|
||||
|
||||
rootFolderObj := res.ToIDispatch()
|
||||
defer rootFolderObj.Release()
|
||||
|
||||
err = fetchTasksRecursively(rootFolderObj, &scheduledTasks)
|
||||
|
||||
return scheduledTasks, err
|
||||
}
|
||||
|
||||
func fetchTasksInFolder(folder *ole.IDispatch, scheduledTasks *ScheduledTasks) error {
|
||||
res, err := oleutil.CallMethod(folder, "GetTasks", 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tasks := res.ToIDispatch()
|
||||
defer tasks.Release()
|
||||
|
||||
err = oleutil.ForEach(tasks, func(v *ole.VARIANT) error {
|
||||
task := v.ToIDispatch()
|
||||
defer task.Release()
|
||||
|
||||
parsedTask, err := parseTask(task)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*scheduledTasks = append(*scheduledTasks, parsedTask)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func fetchTasksRecursively(folder *ole.IDispatch, scheduledTasks *ScheduledTasks) error {
|
||||
if err := fetchTasksInFolder(folder, scheduledTasks); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := oleutil.CallMethod(folder, "GetFolders", 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subFolders := res.ToIDispatch()
|
||||
defer subFolders.Release()
|
||||
|
||||
err = oleutil.ForEach(subFolders, func(v *ole.VARIANT) error {
|
||||
subFolder := v.ToIDispatch()
|
||||
defer subFolder.Release()
|
||||
return fetchTasksRecursively(subFolder, scheduledTasks)
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func parseTask(task *ole.IDispatch) (scheduledTask ScheduledTask, err error) {
|
||||
taskNameVar, err := oleutil.GetProperty(task, "Name")
|
||||
if err != nil {
|
||||
return scheduledTask, err
|
||||
}
|
||||
defer func() {
|
||||
if tempErr := taskNameVar.Clear(); tempErr != nil {
|
||||
err = tempErr
|
||||
}
|
||||
}()
|
||||
|
||||
taskPathVar, err := oleutil.GetProperty(task, "Path")
|
||||
if err != nil {
|
||||
return scheduledTask, err
|
||||
}
|
||||
defer func() {
|
||||
if tempErr := taskPathVar.Clear(); tempErr != nil {
|
||||
err = tempErr
|
||||
}
|
||||
}()
|
||||
|
||||
taskEnabledVar, err := oleutil.GetProperty(task, "Enabled")
|
||||
if err != nil {
|
||||
return scheduledTask, err
|
||||
}
|
||||
defer func() {
|
||||
if tempErr := taskEnabledVar.Clear(); tempErr != nil {
|
||||
err = tempErr
|
||||
}
|
||||
}()
|
||||
|
||||
taskStateVar, err := oleutil.GetProperty(task, "State")
|
||||
if err != nil {
|
||||
return scheduledTask, err
|
||||
}
|
||||
defer func() {
|
||||
if tempErr := taskStateVar.Clear(); tempErr != nil {
|
||||
err = tempErr
|
||||
}
|
||||
}()
|
||||
|
||||
taskNumberOfMissedRunsVar, err := oleutil.GetProperty(task, "NumberOfMissedRuns")
|
||||
if err != nil {
|
||||
return scheduledTask, err
|
||||
}
|
||||
defer func() {
|
||||
if tempErr := taskNumberOfMissedRunsVar.Clear(); tempErr != nil {
|
||||
err = tempErr
|
||||
}
|
||||
}()
|
||||
|
||||
taskLastTaskResultVar, err := oleutil.GetProperty(task, "LastTaskResult")
|
||||
if err != nil {
|
||||
return scheduledTask, err
|
||||
}
|
||||
defer func() {
|
||||
if tempErr := taskLastTaskResultVar.Clear(); tempErr != nil {
|
||||
err = tempErr
|
||||
}
|
||||
}()
|
||||
|
||||
scheduledTask.Name = taskNameVar.ToString()
|
||||
scheduledTask.Path = strings.ReplaceAll(taskPathVar.ToString(), "\\", "/")
|
||||
scheduledTask.Enabled = taskEnabledVar.Value().(bool)
|
||||
scheduledTask.State = TaskState(taskStateVar.Val)
|
||||
scheduledTask.MissedRunsCount = float64(taskNumberOfMissedRunsVar.Val)
|
||||
scheduledTask.LastTaskResult = TaskResult(taskLastTaskResultVar.Val)
|
||||
|
||||
return scheduledTask, err
|
||||
}
|
||||
|
||||
func (t TaskState) String() string {
|
||||
switch t {
|
||||
case TASK_STATE_UNKNOWN:
|
||||
return "Unknown"
|
||||
case TASK_STATE_DISABLED:
|
||||
return "Disabled"
|
||||
case TASK_STATE_QUEUED:
|
||||
return "Queued"
|
||||
case TASK_STATE_READY:
|
||||
return "Ready"
|
||||
case TASK_STATE_RUNNING:
|
||||
return "Running"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
9
collector/scheduled_task_test.go
Normal file
9
collector/scheduled_task_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkScheduledTaskCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "scheduled_task", newScheduledTask)
|
||||
}
|
||||
@@ -1,30 +1,36 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"fmt"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("service", NewserviceCollector)
|
||||
}
|
||||
const (
|
||||
FlagServiceWhereClause = "collector.service.services-where"
|
||||
FlagServiceUseAPI = "collector.service.use-api"
|
||||
)
|
||||
|
||||
var (
|
||||
serviceWhereClause = kingpin.Flag(
|
||||
"collector.service.services-where",
|
||||
"WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.",
|
||||
).Default("").String()
|
||||
serviceWhereClause *string
|
||||
useAPI *bool
|
||||
)
|
||||
|
||||
// A serviceCollector is a Prometheus collector for WMI Win32_Service metrics
|
||||
type serviceCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
Information *prometheus.Desc
|
||||
State *prometheus.Desc
|
||||
StartMode *prometheus.Desc
|
||||
@@ -33,15 +39,33 @@ type serviceCollector struct {
|
||||
queryWhereClause string
|
||||
}
|
||||
|
||||
// NewserviceCollector ...
|
||||
func NewserviceCollector() (Collector, error) {
|
||||
// newServiceCollectorFlags ...
|
||||
func newServiceCollectorFlags(app *kingpin.Application) {
|
||||
serviceWhereClause = app.Flag(
|
||||
FlagServiceWhereClause,
|
||||
"WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.",
|
||||
).Default("").String()
|
||||
useAPI = app.Flag(
|
||||
FlagServiceUseAPI,
|
||||
"Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.",
|
||||
).Default("false").Bool()
|
||||
}
|
||||
|
||||
// newserviceCollector ...
|
||||
func newserviceCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "service"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
if *serviceWhereClause == "" {
|
||||
log.Warn("No where-clause specified for service collector. This will generate a very large number of metrics!")
|
||||
_ = level.Warn(logger).Log("msg", "No where-clause specified for service collector. This will generate a very large number of metrics!")
|
||||
}
|
||||
if *useAPI {
|
||||
_ = level.Warn(logger).Log("msg", "API collection is enabled.")
|
||||
}
|
||||
|
||||
return &serviceCollector{
|
||||
logger: logger,
|
||||
|
||||
Information: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "info"),
|
||||
"A metric with a constant '1' value labeled with service information",
|
||||
@@ -73,9 +97,16 @@ func NewserviceCollector() (Collector, error) {
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *serviceCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting service metrics:", desc, err)
|
||||
return err
|
||||
if *useAPI {
|
||||
if err := c.collectAPI(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting API service metrics:", "err", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := c.collectWMI(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("msg", "failed collecting WMI service metrics:", "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -103,6 +134,15 @@ var (
|
||||
"paused",
|
||||
"unknown",
|
||||
}
|
||||
apiStateValues = map[uint]string{
|
||||
windows.SERVICE_CONTINUE_PENDING: "continue pending",
|
||||
windows.SERVICE_PAUSE_PENDING: "pause pending",
|
||||
windows.SERVICE_PAUSED: "paused",
|
||||
windows.SERVICE_RUNNING: "running",
|
||||
windows.SERVICE_START_PENDING: "start pending",
|
||||
windows.SERVICE_STOP_PENDING: "stop pending",
|
||||
windows.SERVICE_STOPPED: "stopped",
|
||||
}
|
||||
allStartModes = []string{
|
||||
"boot",
|
||||
"system",
|
||||
@@ -110,6 +150,13 @@ var (
|
||||
"manual",
|
||||
"disabled",
|
||||
}
|
||||
apiStartModeValues = map[uint32]string{
|
||||
windows.SERVICE_AUTO_START: "auto",
|
||||
windows.SERVICE_BOOT_START: "boot",
|
||||
windows.SERVICE_DEMAND_START: "manual",
|
||||
windows.SERVICE_DISABLED: "disabled",
|
||||
windows.SERVICE_SYSTEM_START: "system",
|
||||
}
|
||||
allStatuses = []string{
|
||||
"ok",
|
||||
"error",
|
||||
@@ -126,14 +173,14 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
func (c *serviceCollector) collectWMI(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_Service
|
||||
q := queryAllWhere(&dst, c.queryWhereClause)
|
||||
q := queryAllWhere(&dst, c.queryWhereClause, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
for _, service := range dst {
|
||||
pid := strconv.FormatUint(uint64(service.ProcessId), 10)
|
||||
pid := fmt.Sprintf("%d", uint64(service.ProcessId))
|
||||
|
||||
runAs := ""
|
||||
if service.StartName != nil {
|
||||
@@ -191,5 +238,95 @@ func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Des
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *serviceCollector) collectAPI(ch chan<- prometheus.Metric) error {
|
||||
svcmgrConnection, err := mgr.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer svcmgrConnection.Disconnect() //nolint:errcheck
|
||||
|
||||
// List All Services from the Services Manager.
|
||||
serviceList, err := svcmgrConnection.ListServices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Iterate through the Services List.
|
||||
for _, service := range serviceList {
|
||||
// Get UTF16 service name.
|
||||
serviceName, err := syscall.UTF16PtrFromString(service)
|
||||
if err != nil {
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Service %s get name error: %#v", service, err))
|
||||
continue
|
||||
}
|
||||
|
||||
// Open connection for service handler.
|
||||
serviceHandle, err := windows.OpenService(svcmgrConnection.Handle, serviceName, windows.GENERIC_READ)
|
||||
if err != nil {
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Open service %s error: %#v", service, err))
|
||||
continue
|
||||
}
|
||||
|
||||
// Create handle for each service.
|
||||
serviceManager := &mgr.Service{Name: service, Handle: serviceHandle}
|
||||
defer serviceManager.Close()
|
||||
|
||||
// Get Service Configuration.
|
||||
serviceConfig, err := serviceManager.Config()
|
||||
if err != nil {
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get ervice %s config error: %#v", service, err))
|
||||
continue
|
||||
}
|
||||
|
||||
// Get Service Current Status.
|
||||
serviceStatus, err := serviceManager.Query()
|
||||
if err != nil {
|
||||
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get service %s status error: %#v", service, err))
|
||||
continue
|
||||
}
|
||||
|
||||
pid := fmt.Sprintf("%d", uint64(serviceStatus.ProcessId))
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Information,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
strings.ToLower(service),
|
||||
serviceConfig.DisplayName,
|
||||
pid,
|
||||
serviceConfig.ServiceStartName,
|
||||
)
|
||||
|
||||
for _, state := range apiStateValues {
|
||||
isCurrentState := 0.0
|
||||
if state == apiStateValues[uint(serviceStatus.State)] {
|
||||
isCurrentState = 1.0
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.State,
|
||||
prometheus.GaugeValue,
|
||||
isCurrentState,
|
||||
strings.ToLower(service),
|
||||
state,
|
||||
)
|
||||
}
|
||||
|
||||
for _, startMode := range apiStartModeValues {
|
||||
isCurrentStartMode := 0.0
|
||||
if startMode == apiStartModeValues[serviceConfig.StartType] {
|
||||
isCurrentStartMode = 1.0
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StartMode,
|
||||
prometheus.GaugeValue,
|
||||
isCurrentStartMode,
|
||||
strings.ToLower(service),
|
||||
startMode,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
9
collector/service_test.go
Normal file
9
collector/service_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkServiceCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "service", newserviceCollector)
|
||||
}
|
||||
@@ -1,25 +1,41 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
"regexp"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("smtp", NewSMTPCollector, "SMTP Server")
|
||||
}
|
||||
const (
|
||||
FlagSmtpServerOldExclude = "collector.smtp.server-blacklist"
|
||||
FlagSmtpServerOldInclude = "collector.smtp.server-whitelist"
|
||||
|
||||
FlagSmtpServerExclude = "collector.smtp.server-exclude"
|
||||
FlagSmtpServerInclude = "collector.smtp.server-include"
|
||||
)
|
||||
|
||||
var (
|
||||
serverWhitelist = kingpin.Flag("collector.smtp.server-whitelist", "Regexp of virtual servers to whitelist. Server name must both match whitelist and not match blacklist to be included.").Default(".+").String()
|
||||
serverBlacklist = kingpin.Flag("collector.smtp.server-blacklist", "Regexp of virtual servers to blacklist. Server name must both match whitelist and not match blacklist to be included.").String()
|
||||
serverOldInclude *string
|
||||
serverOldExclude *string
|
||||
|
||||
serverInclude *string
|
||||
serverExclude *string
|
||||
|
||||
serverIncludeSet bool
|
||||
serverExcludeSet bool
|
||||
)
|
||||
|
||||
type SMTPCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
BadmailedMessagesBadPickupFileTotal *prometheus.Desc
|
||||
BadmailedMessagesGeneralFailureTotal *prometheus.Desc
|
||||
BadmailedMessagesHopCountExceededTotal *prometheus.Desc
|
||||
@@ -63,15 +79,62 @@ type SMTPCollector struct {
|
||||
RemoteRetryQueueLength *prometheus.Desc
|
||||
RoutingTableLookupsTotal *prometheus.Desc
|
||||
|
||||
serverWhitelistPattern *regexp.Regexp
|
||||
serverBlacklistPattern *regexp.Regexp
|
||||
serverIncludePattern *regexp.Regexp
|
||||
serverExcludePattern *regexp.Regexp
|
||||
}
|
||||
|
||||
func NewSMTPCollector() (Collector, error) {
|
||||
log.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.")
|
||||
func newSMTPCollectorFlags(app *kingpin.Application) {
|
||||
serverInclude = app.Flag(
|
||||
FlagSmtpServerInclude,
|
||||
"Regexp of virtual servers to include. Server name must both match include and not match exclude to be included.",
|
||||
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
|
||||
serverIncludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
serverExclude = app.Flag(
|
||||
FlagSmtpServerExclude,
|
||||
"Regexp of virtual servers to exclude. Server name must both match include and not match exclude to be included.",
|
||||
).Default("").PreAction(func(c *kingpin.ParseContext) error {
|
||||
serverExcludeSet = true
|
||||
return nil
|
||||
}).String()
|
||||
|
||||
serverOldInclude = app.Flag(
|
||||
FlagSmtpServerOldInclude,
|
||||
"DEPRECATED: Use --collector.smtp.server-include",
|
||||
).Hidden().String()
|
||||
serverOldExclude = app.Flag(
|
||||
FlagSmtpServerOldExclude,
|
||||
"DEPRECATED: Use --collector.smtp.server-exclude",
|
||||
).Hidden().String()
|
||||
}
|
||||
|
||||
func newSMTPCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "smtp"
|
||||
logger = log.With(logger, "collector", subsystem)
|
||||
|
||||
_ = level.Info(logger).Log("msg", "smtp collector is in an experimental state! Metrics for this collector have not been tested.")
|
||||
|
||||
if *serverOldExclude != "" {
|
||||
if !serverExcludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.smtp.server-blacklist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-exclude")
|
||||
*serverExclude = *serverOldExclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.smtp.server-blacklist and --collector.smtp.server-exclude are mutually exclusive")
|
||||
}
|
||||
}
|
||||
if *serverOldInclude != "" {
|
||||
if !serverIncludeSet {
|
||||
_ = level.Warn(logger).Log("msg", "--collector.smtp.server-whitelist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-include")
|
||||
*serverInclude = *serverOldInclude
|
||||
} else {
|
||||
return nil, errors.New("--collector.smtp.server-whitelist and --collector.smtp.server-include are mutually exclusive")
|
||||
}
|
||||
}
|
||||
|
||||
return &SMTPCollector{
|
||||
logger: logger,
|
||||
BadmailedMessagesBadPickupFileTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_bad_pickup_file_total"),
|
||||
"Total number of malformed pickup messages sent to badmail",
|
||||
@@ -325,8 +388,8 @@ func NewSMTPCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
|
||||
serverWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverWhitelist)),
|
||||
serverBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverBlacklist)),
|
||||
serverIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverInclude)),
|
||||
serverExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverExclude)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -334,7 +397,7 @@ func NewSMTPCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *SMTPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting smtp metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting smtp metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -390,14 +453,14 @@ type PerflibSMTPServer struct {
|
||||
|
||||
func (c *SMTPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []PerflibSMTPServer
|
||||
if err := unmarshalObject(ctx.perfObjects["SMTP Server"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["SMTP Server"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, server := range dst {
|
||||
if server.Name == "_Total" ||
|
||||
c.serverBlacklistPattern.MatchString(server.Name) ||
|
||||
!c.serverWhitelistPattern.MatchString(server.Name) {
|
||||
c.serverExcludePattern.MatchString(server.Name) ||
|
||||
!c.serverIncludePattern.MatchString(server.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
9
collector/smtp_test.go
Normal file
9
collector/smtp_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkSmtpCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "smtp", newSMTPCollector)
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("system", NewSystemCollector, "System")
|
||||
}
|
||||
|
||||
// A SystemCollector is a Prometheus collector for WMI metrics
|
||||
type SystemCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
ContextSwitchesTotal *prometheus.Desc
|
||||
ExceptionDispatchesTotal *prometheus.Desc
|
||||
ProcessorQueueLength *prometheus.Desc
|
||||
@@ -21,11 +21,12 @@ type SystemCollector struct {
|
||||
Threads *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewSystemCollector ...
|
||||
func NewSystemCollector() (Collector, error) {
|
||||
// newSystemCollector ...
|
||||
func newSystemCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "system"
|
||||
|
||||
return &SystemCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
ContextSwitchesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"),
|
||||
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
|
||||
@@ -69,7 +70,7 @@ func NewSystemCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *SystemCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting system metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting system metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -88,7 +89,7 @@ type system struct {
|
||||
|
||||
func (c *SystemCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []system
|
||||
if err := unmarshalObject(ctx.perfObjects["System"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["System"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
9
collector/system_test.go
Normal file
9
collector/system_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkSystemCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "system", newSystemCollector)
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("tcp", NewTCPCollector, "TCPv4", "TCPv6")
|
||||
}
|
||||
|
||||
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics
|
||||
type TCPCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
ConnectionFailures *prometheus.Desc
|
||||
ConnectionsActive *prometheus.Desc
|
||||
ConnectionsEstablished *prometheus.Desc
|
||||
@@ -24,19 +24,20 @@ type TCPCollector struct {
|
||||
SegmentsSentTotal *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewTCPCollector ...
|
||||
func NewTCPCollector() (Collector, error) {
|
||||
// newTCPCollector ...
|
||||
func newTCPCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "tcp"
|
||||
|
||||
return &TCPCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
ConnectionFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connection_failures"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connection_failures_total"),
|
||||
"(TCP.ConnectionFailures)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
ConnectionsActive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_active"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_active_total"),
|
||||
"(TCP.ConnectionsActive)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
@@ -48,13 +49,13 @@ func NewTCPCollector() (Collector, error) {
|
||||
nil,
|
||||
),
|
||||
ConnectionsPassive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_passive"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_passive_total"),
|
||||
"(TCP.ConnectionsPassive)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
ConnectionsReset: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_reset"),
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_reset_total"),
|
||||
"(TCP.ConnectionsReset)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
@@ -90,7 +91,7 @@ func NewTCPCollector() (Collector, error) {
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting tcp metrics:", desc, err)
|
||||
_ = level.Error(c.logger).Log("failed collecting tcp metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -172,7 +173,7 @@ func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
|
||||
var dst []tcp
|
||||
|
||||
// TCPv4 counters
|
||||
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) != 0 {
|
||||
@@ -180,7 +181,7 @@ func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
|
||||
}
|
||||
|
||||
// TCPv6 counters
|
||||
if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst); err != nil {
|
||||
if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst, c.logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) != 0 {
|
||||
|
||||
9
collector/tcp_test.go
Normal file
9
collector/tcp_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkTCPCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "tcp", newTCPCollector)
|
||||
}
|
||||
665
collector/teradici_pcoip.go
Normal file
665
collector/teradici_pcoip.go
Normal file
@@ -0,0 +1,665 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
// A teradiciPcoipCollector is a Prometheus collector for WMI metrics:
|
||||
// win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics
|
||||
// win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics
|
||||
// win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics
|
||||
// win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics
|
||||
// win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics
|
||||
|
||||
type teradiciPcoipCollector struct {
|
||||
logger log.Logger
|
||||
|
||||
AudioBytesReceived *prometheus.Desc
|
||||
AudioBytesSent *prometheus.Desc
|
||||
AudioRXBWkbitPersec *prometheus.Desc
|
||||
AudioTXBWkbitPersec *prometheus.Desc
|
||||
AudioTXBWLimitkbitPersec *prometheus.Desc
|
||||
|
||||
BytesReceived *prometheus.Desc
|
||||
BytesSent *prometheus.Desc
|
||||
PacketsReceived *prometheus.Desc
|
||||
PacketsSent *prometheus.Desc
|
||||
RXPacketsLost *prometheus.Desc
|
||||
SessionDurationSeconds *prometheus.Desc
|
||||
TXPacketsLost *prometheus.Desc
|
||||
|
||||
ImagingActiveMinimumQuality *prometheus.Desc
|
||||
ImagingApex2800Offload *prometheus.Desc
|
||||
ImagingBytesReceived *prometheus.Desc
|
||||
ImagingBytesSent *prometheus.Desc
|
||||
ImagingDecoderCapabilitykbitPersec *prometheus.Desc
|
||||
ImagingEncodedFramesPersec *prometheus.Desc
|
||||
ImagingMegapixelPersec *prometheus.Desc
|
||||
ImagingNegativeAcknowledgements *prometheus.Desc
|
||||
ImagingRXBWkbitPersec *prometheus.Desc
|
||||
ImagingSVGAdevTapframesPersec *prometheus.Desc
|
||||
ImagingTXBWkbitPersec *prometheus.Desc
|
||||
|
||||
RoundTripLatencyms *prometheus.Desc
|
||||
RXBWkbitPersec *prometheus.Desc
|
||||
RXBWPeakkbitPersec *prometheus.Desc
|
||||
RXPacketLossPercent *prometheus.Desc
|
||||
RXPacketLossPercent_Base *prometheus.Desc
|
||||
TXBWActiveLimitkbitPersec *prometheus.Desc
|
||||
TXBWkbitPersec *prometheus.Desc
|
||||
TXBWLimitkbitPersec *prometheus.Desc
|
||||
TXPacketLossPercent *prometheus.Desc
|
||||
TXPacketLossPercent_Base *prometheus.Desc
|
||||
|
||||
USBBytesReceived *prometheus.Desc
|
||||
USBBytesSent *prometheus.Desc
|
||||
USBRXBWkbitPersec *prometheus.Desc
|
||||
USBTXBWkbitPersec *prometheus.Desc
|
||||
}
|
||||
|
||||
// newTeradiciPcoipCollector constructs a new teradiciPcoipCollector
|
||||
func newTeradiciPcoipCollector(logger log.Logger) (Collector, error) {
|
||||
const subsystem = "teradici_pcoip"
|
||||
return &teradiciPcoipCollector{
|
||||
logger: log.With(logger, "collector", subsystem),
|
||||
AudioBytesReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "audio_bytes_received_total"),
|
||||
"(AudioBytesReceived)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AudioBytesSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "audio_bytes_sent_total"),
|
||||
"(AudioBytesSent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AudioRXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "audio_rx_bw_kbit_persec"),
|
||||
"(AudioRXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AudioTXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "audio_tx_bw_kbit_persec"),
|
||||
"(AudioTXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
AudioTXBWLimitkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "audio_tx_bw_limit_kbit_persec"),
|
||||
"(AudioTXBWLimitkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
|
||||
BytesReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"),
|
||||
"(BytesReceived)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
BytesSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"),
|
||||
"(BytesSent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PacketsReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"),
|
||||
"(PacketsReceived)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PacketsSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_sent_total"),
|
||||
"(PacketsSent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
RXPacketsLost: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "rx_packets_lost_total"),
|
||||
"(RXPacketsLost)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SessionDurationSeconds: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "session_duration_seconds_total"),
|
||||
"(SessionDurationSeconds)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TXPacketsLost: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "tx_packets_lost_total"),
|
||||
"(TXPacketsLost)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
|
||||
ImagingActiveMinimumQuality: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_active_min_quality"),
|
||||
"(ImagingActiveMinimumQuality)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingApex2800Offload: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_apex2800_offload"),
|
||||
"(ImagingApex2800Offload)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingBytesReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_bytes_received_total"),
|
||||
"(ImagingBytesReceived)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingBytesSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_bytes_sent_total"),
|
||||
"(ImagingBytesSent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingDecoderCapabilitykbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_decoder_capability_kbit_persec"),
|
||||
"(ImagingDecoderCapabilitykbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingEncodedFramesPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_encoded_frames_persec"),
|
||||
"(ImagingEncodedFramesPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingMegapixelPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_megapixel_persec"),
|
||||
"(ImagingMegapixelPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingNegativeAcknowledgements: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_negative_acks_total"),
|
||||
"(ImagingNegativeAcknowledgements)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingRXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_rx_bw_kbit_persec"),
|
||||
"(ImagingRXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingSVGAdevTapframesPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_svga_devtap_frames_persec"),
|
||||
"(ImagingSVGAdevTapframesPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ImagingTXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "imaging_tx_bw_kbit_persec"),
|
||||
"(ImagingTXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
|
||||
RoundTripLatencyms: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "round_trip_latency_ms"),
|
||||
"(RoundTripLatencyms)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
RXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "rx_bw_kbit_persec"),
|
||||
"(RXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
RXBWPeakkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "rx_bw_peak_kbit_persec"),
|
||||
"(RXBWPeakkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
RXPacketLossPercent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "rx_packet_loss_percent"),
|
||||
"(RXPacketLossPercent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
RXPacketLossPercent_Base: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "rx_packet_loss_percent_base"),
|
||||
"(RXPacketLossPercent_Base)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TXBWActiveLimitkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "tx_bw_active_limit_kbit_persec"),
|
||||
"(TXBWActiveLimitkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "tx_bw_kbit_persec"),
|
||||
"(TXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TXBWLimitkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "tx_bw_limit_kbit_persec"),
|
||||
"(TXBWLimitkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TXPacketLossPercent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "tx_packet_loss_percent"),
|
||||
"(TXPacketLossPercent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TXPacketLossPercent_Base: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "tx_packet_loss_percent_base"),
|
||||
"(TXPacketLossPercent_Base)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
|
||||
USBBytesReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "usb_bytes_received_total"),
|
||||
"(USBBytesReceived)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
USBBytesSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "usb_bytes_sent_total"),
|
||||
"(USBBytesSent)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
USBRXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "usb_rx_bw_kbit_persec"),
|
||||
"(USBRXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
USBTXBWkbitPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "usb_tx_bw_kbit_persec"),
|
||||
"(USBTXBWkbitPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *teradiciPcoipCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collectAudio(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("failed collecting teradici session audio metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectGeneral(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("failed collecting teradici session general metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectImaging(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("failed collecting teradici session imaging metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectNetwork(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("failed collecting teradici session network metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectUsb(ch); err != nil {
|
||||
_ = level.Error(c.logger).Log("failed collecting teradici session USB metrics", "desc", desc, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics struct {
|
||||
AudioBytesReceived uint64
|
||||
AudioBytesSent uint64
|
||||
AudioRXBWkbitPersec uint64
|
||||
AudioTXBWkbitPersec uint64
|
||||
AudioTXBWLimitkbitPersec uint64
|
||||
}
|
||||
|
||||
type win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics struct {
|
||||
BytesReceived uint64
|
||||
BytesSent uint64
|
||||
PacketsReceived uint64
|
||||
PacketsSent uint64
|
||||
RXPacketsLost uint64
|
||||
SessionDurationSeconds uint64
|
||||
TXPacketsLost uint64
|
||||
}
|
||||
|
||||
type win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics struct {
|
||||
ImagingActiveMinimumQuality uint32
|
||||
ImagingApex2800Offload uint32
|
||||
ImagingBytesReceived uint64
|
||||
ImagingBytesSent uint64
|
||||
ImagingDecoderCapabilitykbitPersec uint32
|
||||
ImagingEncodedFramesPersec uint32
|
||||
ImagingMegapixelPersec uint32
|
||||
ImagingNegativeAcknowledgements uint32
|
||||
ImagingRXBWkbitPersec uint64
|
||||
ImagingSVGAdevTapframesPersec uint32
|
||||
ImagingTXBWkbitPersec uint64
|
||||
}
|
||||
|
||||
type win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics struct {
|
||||
RoundTripLatencyms uint32
|
||||
RXBWkbitPersec uint64
|
||||
RXBWPeakkbitPersec uint32
|
||||
RXPacketLossPercent uint32
|
||||
RXPacketLossPercent_Base uint32
|
||||
TXBWActiveLimitkbitPersec uint32
|
||||
TXBWkbitPersec uint64
|
||||
TXBWLimitkbitPersec uint32
|
||||
TXPacketLossPercent uint32
|
||||
TXPacketLossPercent_Base uint32
|
||||
}
|
||||
|
||||
type win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics struct {
|
||||
USBBytesReceived uint64
|
||||
USBBytesSent uint64
|
||||
USBRXBWkbitPersec uint64
|
||||
USBTXBWkbitPersec uint64
|
||||
}
|
||||
|
||||
func (c *teradiciPcoipCollector) collectAudio(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AudioBytesReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AudioBytesReceived),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AudioBytesSent,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].AudioBytesSent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AudioRXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].AudioRXBWkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AudioTXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].AudioTXBWkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AudioTXBWLimitkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].AudioTXBWLimitkbitPersec),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *teradiciPcoipCollector) collectGeneral(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].BytesReceived),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesSent,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].BytesSent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].PacketsReceived),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsSent,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].PacketsSent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RXPacketsLost,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].RXPacketsLost),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SessionDurationSeconds,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].SessionDurationSeconds),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TXPacketsLost,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].TXPacketsLost),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *teradiciPcoipCollector) collectImaging(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingActiveMinimumQuality,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingActiveMinimumQuality),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingApex2800Offload,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingApex2800Offload),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingBytesReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].ImagingBytesReceived),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingBytesSent,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].ImagingBytesSent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingDecoderCapabilitykbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingDecoderCapabilitykbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingEncodedFramesPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingEncodedFramesPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingMegapixelPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingMegapixelPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingNegativeAcknowledgements,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].ImagingNegativeAcknowledgements),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingRXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingRXBWkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingSVGAdevTapframesPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingSVGAdevTapframesPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ImagingTXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ImagingTXBWkbitPersec),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *teradiciPcoipCollector) collectNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RoundTripLatencyms,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].RoundTripLatencyms),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].RXBWkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RXBWPeakkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].RXBWPeakkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RXPacketLossPercent,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].RXPacketLossPercent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RXPacketLossPercent_Base,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].RXPacketLossPercent_Base),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TXBWActiveLimitkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TXBWActiveLimitkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TXBWkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TXBWLimitkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TXBWLimitkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TXPacketLossPercent,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TXPacketLossPercent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TXPacketLossPercent_Base,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TXPacketLossPercent_Base),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *teradiciPcoipCollector) collectUsb(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics
|
||||
q := queryAll(&dst, c.logger)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.USBBytesReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].USBBytesReceived),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.USBBytesSent,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].USBBytesSent),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.USBRXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].USBRXBWkbitPersec),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.USBTXBWkbitPersec,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].USBTXBWkbitPersec),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
9
collector/teradici_pcoip_test.go
Normal file
9
collector/teradici_pcoip_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkTeradiciPcoipCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "teradici_pcoip", newTeradiciPcoipCollector)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user