mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-08 05:56:37 +00:00
Compare commits
665 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cecc735df | ||
|
|
4635be8c0c | ||
|
|
4cc7d108e3 | ||
|
|
d878423cb6 | ||
|
|
a93bbe4ac2 | ||
|
|
33efbdfbcb | ||
|
|
8db705e67a | ||
|
|
7044b556c2 | ||
|
|
fa8d28c181 | ||
|
|
64c8423e61 | ||
|
|
e2e1141973 | ||
|
|
31bb6d03ee | ||
|
|
caee5a05fe | ||
|
|
578b16b448 | ||
|
|
1da96a4f3c | ||
|
|
fddb92a9d5 | ||
|
|
2cda7b3f4d | ||
|
|
b44b0413bb | ||
|
|
f4e360218f | ||
|
|
4efb502aab | ||
|
|
a4a5ac464a | ||
|
|
1b438cdb82 | ||
|
|
f0d0545d34 | ||
|
|
d05effdda5 | ||
|
|
2d29f0004b | ||
|
|
d94640b6f8 | ||
|
|
26e05e9d07 | ||
|
|
9eec34d2f1 | ||
|
|
b8b164bfca | ||
|
|
7775ef95e6 | ||
|
|
eeaefba0d7 | ||
|
|
b2ab542b6d | ||
|
|
f85866ce1e | ||
|
|
9e24ce8f74 | ||
|
|
9c65b7464f | ||
|
|
c242fae84c | ||
|
|
c85cfaadde | ||
|
|
d6c24d1500 | ||
|
|
8b515ba54a | ||
|
|
a2575b93a9 | ||
|
|
965be334bc | ||
|
|
1239fbf719 | ||
|
|
a49dee606b | ||
|
|
c713bed4e3 | ||
|
|
99b6d215a2 | ||
|
|
6d91cdc9fc | ||
|
|
c9ebc3e153 | ||
|
|
c99cf180d0 | ||
|
|
6e14d4e53f | ||
|
|
48e7c34539 | ||
|
|
6497a1a5cc | ||
|
|
4e1987686b | ||
|
|
dc4bc8e163 | ||
|
|
b8747045ce | ||
|
|
00781dbbee | ||
|
|
195cfa8d5c | ||
|
|
be25d79b71 | ||
|
|
9bf84fb10c | ||
|
|
b977c8484b | ||
|
|
13ebec0195 | ||
|
|
cc89ae33a4 | ||
|
|
215032a111 | ||
|
|
a2fe96fbc8 | ||
|
|
7d8cf59dac | ||
|
|
de8a1ebbfe | ||
|
|
5ff820cfd0 | ||
|
|
8f6a1e3f07 | ||
|
|
f6b91e5cb0 | ||
|
|
f21c119c74 | ||
|
|
e7464d9fcf | ||
|
|
87d1a59a57 | ||
|
|
b1c272a996 | ||
|
|
fdf6f33941 | ||
|
|
72e7096110 | ||
|
|
658fbd92ab | ||
|
|
d503ae05d4 | ||
|
|
c8b06e86b0 | ||
|
|
21a64b1a62 | ||
|
|
6a15aff837 | ||
|
|
802f0df07a | ||
|
|
08c67def1e | ||
|
|
65c9009db6 | ||
|
|
8e2e867b11 | ||
|
|
7a201e0c16 | ||
|
|
0ebb2d36e8 | ||
|
|
3a2c61c19d | ||
|
|
8a1972162a | ||
|
|
032b1f5e88 | ||
|
|
1daaccceaf | ||
|
|
154dec5f4c | ||
|
|
dbb890c00f | ||
|
|
1515623618 | ||
|
|
96c1412a5b | ||
|
|
e0bdc9828c | ||
|
|
6e9daff6ed | ||
|
|
91da7562e1 | ||
|
|
c238bbcaf2 | ||
|
|
c382d0c217 | ||
|
|
9d1c9fb012 | ||
|
|
f3ef7583fe | ||
|
|
f37d4d7921 | ||
|
|
39ab9faa6a | ||
|
|
ac7c98e57e | ||
|
|
377fec7b55 | ||
|
|
548b970288 | ||
|
|
a02d0257b3 | ||
|
|
477ec0df50 | ||
|
|
2a88229a0e | ||
|
|
3cbf5dc085 | ||
|
|
c4a4da07f8 | ||
|
|
e2ea99fadd | ||
|
|
6eebfcce57 | ||
|
|
f97ac3fb66 | ||
|
|
7f7239f404 | ||
|
|
8d1d552351 | ||
|
|
233470cdf0 | ||
|
|
67fca296bf | ||
|
|
143ab2247a | ||
|
|
7635e6e094 | ||
|
|
9541560e43 | ||
|
|
941019ebc9 | ||
|
|
5ef7c1f0e9 | ||
|
|
9b5568354c | ||
|
|
eab87292c1 | ||
|
|
6ca67f7aa2 | ||
|
|
688ea45e7e | ||
|
|
4032b7f610 | ||
|
|
e2ceb0d46d | ||
|
|
d07845ca08 | ||
|
|
b5284aca85 | ||
|
|
5c1f19d4bc | ||
|
|
c83da9a2f0 | ||
|
|
b09b8a9c36 | ||
|
|
265c12b28e | ||
|
|
2be970e652 | ||
|
|
2103e7e1b5 | ||
|
|
09c0e47fde | ||
|
|
e19b8959c4 | ||
|
|
21a7beaee6 | ||
|
|
a32f83a6de | ||
|
|
f70fa009de | ||
|
|
546e5de5e1 | ||
|
|
415c72d457 | ||
|
|
bd7d7be6ea | ||
|
|
b4c0874ca4 | ||
|
|
6ede10e29a | ||
|
|
69d2673e07 | ||
|
|
2eee8b33e7 | ||
|
|
f260a8f9fc | ||
|
|
969a0ce861 | ||
|
|
5398e91752 | ||
|
|
3868c97686 | ||
|
|
856389e107 | ||
|
|
44f4918219 | ||
|
|
fd20f6f16a | ||
|
|
971cab5184 | ||
|
|
22eec4cd73 | ||
|
|
f850a84140 | ||
|
|
0be1708e06 | ||
|
|
52b66bfb84 | ||
|
|
008786366c | ||
|
|
504b506f46 | ||
|
|
f100ffe892 | ||
|
|
7beb08f6c3 | ||
|
|
ac53f5227a | ||
|
|
1915d784bf | ||
|
|
760b6d299a | ||
|
|
cb97e88b12 | ||
|
|
aac09e1146 | ||
|
|
1e52be0f35 | ||
|
|
a3fc99f3fd | ||
|
|
9138f6c8a4 | ||
|
|
edceb96040 | ||
|
|
df286798a7 | ||
|
|
e76b739e30 | ||
|
|
49d9097bf9 | ||
|
|
63e7fa3054 | ||
|
|
48cb97d7d3 | ||
|
|
7feafc1238 | ||
|
|
d4b48e52e6 | ||
|
|
f1b2b319f5 | ||
|
|
b22380ea06 | ||
|
|
a78e4a1af6 | ||
|
|
ce6c719a7a | ||
|
|
73bfd00cbe | ||
|
|
f62077014f | ||
|
|
5a872a227c | ||
|
|
9bed4826d6 | ||
|
|
470f5d5852 | ||
|
|
aa8453f9d6 | ||
|
|
61ec692534 | ||
|
|
8f177f03c3 | ||
|
|
53bbee75f0 | ||
|
|
1c75398d4b | ||
|
|
189ae539b5 | ||
|
|
5d83b29a2e | ||
|
|
ac9303350a | ||
|
|
e9feac83ef | ||
|
|
caa2ae74f1 | ||
|
|
afab42ec5a | ||
|
|
aa1e4e8906 | ||
|
|
8a33796bd3 | ||
|
|
52a360211e | ||
|
|
c6b6a239aa | ||
|
|
13f2b3d083 | ||
|
|
32721b3f16 | ||
|
|
268a47ff3d | ||
|
|
9922f1265a | ||
|
|
39686130c6 | ||
|
|
ff68ef102f | ||
|
|
db9fc9fafe | ||
|
|
038eede644 | ||
|
|
ab05f43716 | ||
|
|
089acc5b88 | ||
|
|
4d39014e33 | ||
|
|
57973dbc38 | ||
|
|
a08394e089 | ||
|
|
620dc84246 | ||
|
|
b7798918f4 | ||
|
|
1836cd1ad0 | ||
|
|
84eadf5085 | ||
|
|
ffd59537e8 | ||
|
|
e3a7fab98a | ||
|
|
5bb7e6086f | ||
|
|
91c07686bd | ||
|
|
a8a28053ba | ||
|
|
9f982575ac | ||
|
|
7ea04d25c6 | ||
|
|
430fdb0aef | ||
|
|
78f5fb295c | ||
|
|
6824d3f799 | ||
|
|
552e9d8cd2 | ||
|
|
0711268d3c | ||
|
|
7331dc2394 | ||
|
|
569f5450cd | ||
|
|
a08474b4f9 | ||
|
|
d3c54d4a01 | ||
|
|
e041eec500 | ||
|
|
b64e00e778 | ||
|
|
3859a3eeb4 | ||
|
|
f0d5026d7d | ||
|
|
b0d55b1d5f | ||
|
|
fa4bf71578 | ||
|
|
3187cbcc64 | ||
|
|
29521701bb | ||
|
|
1365aec747 | ||
|
|
5c38ce78b2 | ||
|
|
f316d27324 | ||
|
|
e9fdfdc1eb | ||
|
|
8de5ef0353 | ||
|
|
9c0be5fd48 | ||
|
|
d3254118de | ||
|
|
a41abdf22d | ||
|
|
6832fd7fd7 | ||
|
|
5e7462a70e | ||
|
|
e8864c766e | ||
|
|
07fff6afc2 | ||
|
|
083537a96a | ||
|
|
6aa0ac5706 | ||
|
|
7d2d7f3d1c | ||
|
|
f8c298e038 | ||
|
|
4e9fa4fd8e | ||
|
|
d8524c505b | ||
|
|
ca6eb75685 | ||
|
|
5631166075 | ||
|
|
1d027579d2 | ||
|
|
23e1a86aa7 | ||
|
|
f8b8b2c546 | ||
|
|
d78230f67b | ||
|
|
f7426e9fad | ||
|
|
fdec95bc99 | ||
|
|
75ae769b6e | ||
|
|
4add010b8d | ||
|
|
7530e7b400 | ||
|
|
9473265ffa | ||
|
|
0ec4e9d90f | ||
|
|
7876a465ca | ||
|
|
f9361bb684 | ||
|
|
f5b9ba35d0 | ||
|
|
7c178e5ced | ||
|
|
134bae514d | ||
|
|
a4beb4c187 | ||
|
|
884cac808a | ||
|
|
117ba941df | ||
|
|
8d61595607 | ||
|
|
68f5c61de8 | ||
|
|
ca5124fdf9 | ||
|
|
e2b48497f4 | ||
|
|
b1eaf00e74 | ||
|
|
34da140f87 | ||
|
|
7a3a978d79 | ||
|
|
e9b8f82b2c | ||
|
|
b0a1a38829 | ||
|
|
f77bdcfa09 | ||
|
|
2fb5b89d92 | ||
|
|
65c8fa4304 | ||
|
|
8f7031861a | ||
|
|
a78c707f47 | ||
|
|
eb1b1ccb54 | ||
|
|
8447758db5 | ||
|
|
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 | ||
|
|
a89b53779d | ||
|
|
9d1628a329 | ||
|
|
fc33fa320b |
6
.editorconfig
Normal file
6
.editorconfig
Normal file
@@ -0,0 +1,6 @@
|
||||
root = true
|
||||
|
||||
[*.wxs]
|
||||
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
71
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
71
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: 🐞 Bug
|
||||
description: Something is not working as indended.
|
||||
labels: [ 🐞 bug ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thanks for taking the time to fill out this bug report!
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: A concise description of what you're experiencing.
|
||||
placeholder: |
|
||||
When I do <X>, <Y> happens and I see the error message attached below:
|
||||
```...```
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A concise description of what you expected to happen.
|
||||
placeholder: When I do <X>, <Z> should happen instead.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps To Reproduce
|
||||
description: Steps to reproduce the behavior.
|
||||
placeholder: |
|
||||
1. In this environment...
|
||||
2. With this config...
|
||||
3. Run '...'
|
||||
4. See error...
|
||||
render: Markdown
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
examples:
|
||||
- **windows_exporter Version**: 0.26
|
||||
- **Windows Server Version**: 2019
|
||||
value: |
|
||||
- windows_exporter Version:
|
||||
- Windows Server Version:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: windows_exporter logs
|
||||
description: |
|
||||
Log of windows_exporter.
|
||||
⚠️ Without proving logs, we unable to assist here. ⚠️
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
41
.github/ISSUE_TEMPLATE/enhancement.yaml
vendored
Normal file
41
.github/ISSUE_TEMPLATE/enhancement.yaml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: ✨ Enhancement / Feature / Task
|
||||
description: Some feature is missing or incomplete.
|
||||
labels: [ ✨ enhancement ]
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: Without specifying a solution, describe what the project is missing today.
|
||||
placeholder: |
|
||||
The rotating project logo has a fixed size and color.
|
||||
There is no way to make it larger and more shiny.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: Describe the proposed solution to the problem above.
|
||||
placeholder: |
|
||||
- Implement 2 new flags CLI: ```--logo-color=FFD700``` and ```--logo-size=100```
|
||||
- Let these flags control the size of the rotating project logo.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional information
|
||||
placeholder: |
|
||||
We considered adjusting the logo size to the phase of the moon, but there was no
|
||||
reliable data source in air-gapped environments.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Acceptance Criteria
|
||||
placeholder: |
|
||||
- [ ] As a user, I can control the size of the rotating logo using a CLI flag.
|
||||
- [ ] As a user, I can control the color of the rotating logo using a CLI flag.
|
||||
- [ ] Defaults are reasonably set.
|
||||
- [ ] New settings are appropriately documented.
|
||||
- [ ] No breaking change for current users of the rotating logo feature.
|
||||
validations:
|
||||
required: false
|
||||
27
.github/ISSUE_TEMPLATE/question.yaml
vendored
Normal file
27
.github/ISSUE_TEMPLATE/question.yaml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: ❓ Question
|
||||
description: Something is not clear.
|
||||
labels: [ ❓ question ]
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: Without specifying a solution, describe what the project is missing today.
|
||||
placeholder: |
|
||||
The rotating project logo has a fixed size and color.
|
||||
There is no way to make it larger and more shiny.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
examples:
|
||||
- **windows_exporter Version**: 0.26
|
||||
- **Windows Server Version**: 2019
|
||||
value: |
|
||||
- windows_exporter Version:
|
||||
- Windows Server Version:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
9
.github/dependabot.yml
vendored
9
.github/dependabot.yml
vendored
@@ -1,6 +1,15 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
labels:
|
||||
- "🛠️ dependencies"
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
labels:
|
||||
- "🛠️ dependencies"
|
||||
|
||||
23
.github/release.yml
vendored
Normal file
23
.github/release.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
changelog:
|
||||
exclude:
|
||||
labels:
|
||||
- chore
|
||||
categories:
|
||||
- title: 💥 Breaking Changes
|
||||
labels:
|
||||
- 💥 breaking-change
|
||||
- title: ✨ Exciting New Features
|
||||
labels:
|
||||
- ✨ enhancement
|
||||
- title: 🐞 Bug Fixes
|
||||
labels:
|
||||
- 🐞 bug
|
||||
- title: 🛠️ Dependencies
|
||||
labels:
|
||||
- 🛠️ dependencies
|
||||
- title: 📖 Documentation
|
||||
labels:
|
||||
- 📖 docs
|
||||
- title: Other Changes
|
||||
labels:
|
||||
- "*"
|
||||
129
.github/workflows/ci.yml
vendored
129
.github/workflows/ci.yml
vendored
@@ -1,129 +0,0 @@
|
||||
name: windows_exporter CI/CD
|
||||
|
||||
# Trigger on pull requests and releases
|
||||
# Deployments will only occur for releases (see `if` clauses in the build job).
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
- edited
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17.5'
|
||||
|
||||
- name: Test
|
||||
run: make test
|
||||
|
||||
- name: Install e2e deps
|
||||
run: |
|
||||
go get -u github.com/prometheus/promu@v0.11.1
|
||||
go get -u 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
|
||||
|
||||
lint:
|
||||
runs-on: windows-2019
|
||||
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@v2
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17.5'
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
with:
|
||||
version: v1.43
|
||||
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
|
||||
|
||||
build:
|
||||
runs-on: windows-2019
|
||||
needs:
|
||||
- test
|
||||
- lint
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# fetch-depth required for gitversion in `Build` step
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17.5'
|
||||
|
||||
- name: Install Build deps
|
||||
run: |
|
||||
go get -u github.com/prometheus/promu@v0.11.1
|
||||
go get -u github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.2.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"
|
||||
|
||||
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") {
|
||||
Move-Item output\$Arch\windows_exporter.exe output\windows_exporter-$Version-$Arch.exe
|
||||
}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
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: 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 $_}
|
||||
57
.github/workflows/container_description.yml
vendored
Normal file
57
.github/workflows/container_description.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
name: Push README to Docker Hub
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "README.md"
|
||||
- "README-containers.md"
|
||||
- ".github/workflows/container_description.yml"
|
||||
branches: [ main, master ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
PushDockerHubReadme:
|
||||
runs-on: ubuntu-latest
|
||||
name: Push README to Docker Hub
|
||||
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
|
||||
steps:
|
||||
- name: git checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- name: Set docker hub repo name
|
||||
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
|
||||
- name: Push README to Dockerhub
|
||||
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
|
||||
env:
|
||||
DOCKER_USER: ${{ secrets.DOCKER_HUB_LOGIN }}
|
||||
DOCKER_PASS: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
with:
|
||||
destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
|
||||
provider: dockerhub
|
||||
short_description: ${{ env.DOCKER_REPO_NAME }}
|
||||
# Empty string results in README-containers.md being pushed if it
|
||||
# exists. Otherwise, README.md is pushed.
|
||||
readme_file: ''
|
||||
|
||||
PushQuayIoReadme:
|
||||
runs-on: ubuntu-latest
|
||||
name: Push README to quay.io
|
||||
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
|
||||
steps:
|
||||
- name: git checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- name: Set quay.io org name
|
||||
run: echo "DOCKER_REPO=$(echo quay.io/${GITHUB_REPOSITORY_OWNER} | tr -d '-')" >> $GITHUB_ENV
|
||||
- name: Set quay.io repo name
|
||||
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
|
||||
- name: Push README to quay.io
|
||||
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
|
||||
env:
|
||||
DOCKER_APIKEY: ${{ secrets.QUAY_IO_API_TOKEN }}
|
||||
with:
|
||||
destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
|
||||
provider: quay
|
||||
# Empty string results in README-containers.md being pushed if it
|
||||
# exists. Otherwise, README.md is pushed.
|
||||
readme_file: ''
|
||||
104
.github/workflows/lint.yml
vendored
Normal file
104
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
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@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- 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"
|
||||
|
||||
# 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@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- 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"
|
||||
|
||||
# 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
|
||||
|
||||
- name: Upload windows_exporter.exe
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: windows_exporter.amd64.exe
|
||||
path: 'windows_exporter.exe'
|
||||
retention-days: 7
|
||||
if-no-files-found: error
|
||||
|
||||
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@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: v1.58
|
||||
args: "--timeout=5m --out-format github-actions,colored-line-number"
|
||||
46
.github/workflows/pr-check.yaml
vendored
Normal file
46
.github/workflows/pr-check.yaml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Validate Pull Request
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- labeled
|
||||
- unlabeled
|
||||
|
||||
jobs:
|
||||
required-labels-missing:
|
||||
name: required labels missing
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check
|
||||
if: >-
|
||||
!contains(github.event.pull_request.labels.*.name, '💥 breaking-change')
|
||||
&& !contains(github.event.pull_request.labels.*.name, '✨ enhancement')
|
||||
&& !contains(github.event.pull_request.labels.*.name, '🐞 bug')
|
||||
&& !contains(github.event.pull_request.labels.*.name, '📖 docs')
|
||||
&& !contains(github.event.pull_request.labels.*.name, 'chore')
|
||||
&& !contains(github.event.pull_request.labels.*.name, '🛠️ dependencies')
|
||||
run: >-
|
||||
echo One of the following labels is missing on this PR:
|
||||
breaking-change
|
||||
enhancement
|
||||
bug
|
||||
docs
|
||||
chore
|
||||
&& exit 1
|
||||
title:
|
||||
name: check title prefix
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: check
|
||||
run: |
|
||||
PR_TITLE_PREFIX=$(echo "$PR_TITLE" | cut -d':' -f1)
|
||||
if [[ ! -d "pkg/collector/$PR_TITLE_PREFIX" ]] || [[ "$PR_TITLE_PREFIX" == "chore" ]] || [[ "$PR_TITLE_PREFIX" == "*" ]]; then
|
||||
echo "PR title must start with an name of an collector package"
|
||||
echo "Example: 'logical_disk: description'"
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
165
.github/workflows/release.yml
vendored
Normal file
165
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
name: Releases
|
||||
|
||||
# Trigger on releases.
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
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@v4
|
||||
with:
|
||||
# fetch-depth required for gitversion in `Build` step
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
# https://github.com/pl4nty/Windows-Containers/blob/Main/helpful_tools/Install-BuildKit-GitHubActions/workflow.yaml
|
||||
- name: Setup containerd
|
||||
run: |
|
||||
$version = "1.7.20"
|
||||
curl.exe -L https://github.com/containerd/containerd/releases/download/v$version/containerd-$version-windows-amd64.tar.gz -o containerd.tar.gz
|
||||
tar.exe xvf containerd.tar.gz
|
||||
.\bin\containerd.exe --register-service
|
||||
Start-Service containerd
|
||||
- name: Setup BuildKit
|
||||
run: |
|
||||
$version = "v0.15.0"
|
||||
curl.exe -L https://github.com/moby/buildkit/releases/download/$version/buildkit-$version.windows-amd64.tar.gz -o buildkit.tar.gz
|
||||
tar.exe xvf buildkit.tar.gz
|
||||
|
||||
.\bin\buildkitd.exe --register-service
|
||||
Start-Service buildkitd
|
||||
- name: Setup Docker Buildx
|
||||
run: |
|
||||
$version = "v0.16.1"
|
||||
curl.exe -L https://github.com/docker/buildx/releases/download/$version/buildx-$version.windows-amd64.exe -o $env:ProgramData\Docker\cli-plugins\docker-buildx.exe
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: remote
|
||||
endpoint: npipe:////./pipe/buildkitd
|
||||
|
||||
- name: Install WiX
|
||||
run: dotnet tool install --global wix
|
||||
|
||||
- name: Install WiX extensions
|
||||
run: |
|
||||
wix extension add -g WixToolset.Util.wixext
|
||||
wix extension add -g WixToolset.Firewall.wixext
|
||||
|
||||
- name: Install Build 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"
|
||||
|
||||
# GOPATH\bin dir must be added to PATH else the `promu` commands won't be found
|
||||
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$Version = git describe --tag
|
||||
$Version = $Version -replace 'v', ''
|
||||
# '+' symbols are invalid characters in image tags
|
||||
$Version = $Version -replace '\+', '_'
|
||||
$Version | Set-Content VERSION -PassThru
|
||||
|
||||
make build-all
|
||||
|
||||
# GH requires all files to have different names, so add version/arch to differentiate
|
||||
foreach($Arch in "amd64", "arm64") {
|
||||
Move-Item output\$Arch\windows_exporter.exe output\windows_exporter-$Version-$Arch.exe
|
||||
}
|
||||
|
||||
Get-ChildItem -Path output
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows_exporter_binaries
|
||||
path: output\windows_exporter-*.exe
|
||||
|
||||
- name: Build Release Artifacts
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$Version = Get-Content VERSION
|
||||
|
||||
foreach($Arch in "amd64", "arm64") {
|
||||
Write-Host "Building windows_exporter $Version msi for $Arch"
|
||||
.\installer\build.ps1 -PathToExecutable .\output\windows_exporter-$Version-$Arch.exe -Version $Version -Arch "$Arch"
|
||||
}
|
||||
|
||||
Move-Item installer\*.msi output\
|
||||
Get-ChildItem -Path output\
|
||||
|
||||
promu checksum output\
|
||||
|
||||
- name: Build Docker Artifacts
|
||||
run: make build-all
|
||||
env:
|
||||
VERSION: >-
|
||||
${{
|
||||
startsWith(github.ref, 'refs/tags/') && 'latest' ||
|
||||
(
|
||||
github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || github.ref_name
|
||||
)
|
||||
}}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_LOGIN }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
#- name: Login to quay.io
|
||||
# if: ${{ github.event_name != 'pull_request' }}
|
||||
# uses: docker/login-action@v3
|
||||
# with:
|
||||
# registry: quay.io
|
||||
# username: 'robot'
|
||||
# password: ${{ secrets.QUAY_IO_API_TOKEN }}
|
||||
|
||||
- name: Login to GitHub container registry
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@v3
|
||||
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 }}
|
||||
VERSION: ${{ startsWith(github.ref, 'refs/tags/') && 'latest' || github.ref_name }}
|
||||
run: |
|
||||
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@v4
|
||||
- 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
|
||||
21
.github/workflows/stale.yml
vendored
Normal file
21
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: 'Close stale issues and PRs'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
stale-issue-message: 'This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.'
|
||||
exempt-issue-labels: 'lifecycle/frozen'
|
||||
days-before-stale: 90
|
||||
days-before-close: 30
|
||||
enable-statistics: false
|
||||
operations-per-run: 500
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,3 +6,6 @@ output/
|
||||
.vscode
|
||||
.idea
|
||||
*.syso
|
||||
installer/*.msi
|
||||
installer/*.wixpdb
|
||||
local/
|
||||
108
.golangci.yaml
108
.golangci.yaml
@@ -1,19 +1,105 @@
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- deadcode
|
||||
- errcheck
|
||||
- revive
|
||||
- govet
|
||||
- gofmt
|
||||
- ineffassign
|
||||
- structcheck
|
||||
- unconvert
|
||||
- varcheck
|
||||
enable-all: true
|
||||
disable:
|
||||
- asasalint
|
||||
- asciicheck
|
||||
- bidichk
|
||||
- bodyclose
|
||||
- canonicalheader
|
||||
- containedctx
|
||||
- contextcheck
|
||||
- copyloopvar
|
||||
- cyclop
|
||||
- decorder
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- dupword
|
||||
- durationcheck
|
||||
- err113
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- exhaustruct
|
||||
- exportloopref
|
||||
- fatcontext
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
- funlen
|
||||
- gci
|
||||
- ginkgolinter
|
||||
- gocheckcompilerdirectives
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gochecksumtype
|
||||
- gocognit
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godot
|
||||
- godox
|
||||
- gofumpt
|
||||
- goheader
|
||||
- goimports
|
||||
- gomoddirectives
|
||||
- gomodguard
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
- gosmopolitan
|
||||
- grouper
|
||||
- importas
|
||||
- inamedparam
|
||||
- interfacebloat
|
||||
- intrange
|
||||
- ireturn
|
||||
- lll
|
||||
- maintidx
|
||||
- makezero
|
||||
- mirror
|
||||
- misspell
|
||||
- mnd
|
||||
- musttag
|
||||
- nakedret
|
||||
- nestif
|
||||
- nlreturn
|
||||
- noctx
|
||||
- nolintlint
|
||||
- nonamedreturns
|
||||
- nosprintfhostport
|
||||
- paralleltest
|
||||
- predeclared
|
||||
- protogetter
|
||||
- reassign
|
||||
- rowserrcheck
|
||||
- sloglint
|
||||
- spancheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- tagalign
|
||||
- tagliatelle
|
||||
- tenv
|
||||
- testableexamples
|
||||
- testifylint
|
||||
- testpackage
|
||||
- thelper
|
||||
- tparallel
|
||||
- usestdlibvars
|
||||
- varnamelen
|
||||
- wastedassign
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
- wsl
|
||||
- zerologlint
|
||||
- execinquery
|
||||
- gomnd
|
||||
|
||||
issues:
|
||||
exclude:
|
||||
- don't use underscores in Go names
|
||||
- don't use an underscore in package name
|
||||
- exported type .+ should have comment or be unexported
|
||||
exclude-rules:
|
||||
- # Golint has many capitalisation complaints on WMI class names
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
## Prometheus Community Code of Conduct
|
||||
# Prometheus Community Code of Conduct
|
||||
|
||||
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).
|
||||
|
||||
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:ltsc2022"
|
||||
FROM $BASE
|
||||
|
||||
ENV PATH="C:\Windows\system32;C:\Windows;"
|
||||
COPY output/amd64/windows_exporter.exe /windows_exporter.exe
|
||||
ENTRYPOINT ["windows_exporter.exe"]
|
||||
22
Dockerfile.cross
Normal file
22
Dockerfile.cross
Normal file
@@ -0,0 +1,22 @@
|
||||
# Build this Docker Image on any platform with
|
||||
# docker buildx build -t a --platform=windows/amd64 .
|
||||
|
||||
ARG BASE=mcr.microsoft.com/oss/kubernetes/windows-host-process-containers-base-image:v1.0.0
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:1.21 as builder
|
||||
ARG TARGETARCH
|
||||
ARG TARGETOS
|
||||
|
||||
# Get dependencies
|
||||
WORKDIR /w
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
RUN go install github.com/prometheus/promu@latest
|
||||
|
||||
# Build windows_exporter
|
||||
COPY . ./
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make windows_exporter.exe
|
||||
|
||||
FROM $BASE
|
||||
COPY --from=builder /w/windows_exporter.exe /windows_exporter.exe
|
||||
ENTRYPOINT ["windows_exporter.exe"]
|
||||
@@ -2,6 +2,7 @@ Maintainers in alphabetical order
|
||||
|
||||
* [Ben Reedy](https://github.com/breed808) - breed808@breed808.com
|
||||
* [Calle Pettersson](https://github.com/carlpett) - calle@cape.nu
|
||||
* [Jan-Otto Kröpke](https://github.com/jkroepke) - github@jkroepke.de
|
||||
|
||||
Alumni
|
||||
|
||||
|
||||
80
Makefile
80
Makefile
@@ -1,15 +1,35 @@
|
||||
export GOOS=windows
|
||||
GOOS ?= windows
|
||||
VERSION ?= $(shell cat VERSION)
|
||||
DOCKER ?= docker
|
||||
|
||||
# DOCKER_REPO is the official image repository name at docker.io, quay.io.
|
||||
DOCKER_REPO ?= prometheuscommunity
|
||||
DOCKER_IMAGE_NAME ?= windows-exporter
|
||||
|
||||
# ALL_DOCKER_REPOS is the list of repositories to push the image to. ghcr.io requires that org name be the same as the image repo name.
|
||||
ALL_DOCKER_REPOS ?= docker.io/$(DOCKER_REPO) ghcr.io/prometheus-community # quay.io/$(DOCKER_REPO)
|
||||
|
||||
# Image Variables for host process Container
|
||||
# Windows image build is heavily influenced by https://github.com/kubernetes/kubernetes/blob/master/cluster/images/etcd/Makefile
|
||||
OS ?= ltsc2019
|
||||
ALL_OS ?= ltsc2019 ltsc2022
|
||||
BASE_IMAGE ?= mcr.microsoft.com/windows/nanoserver
|
||||
|
||||
.PHONY: build
|
||||
build: windows_exporter.exe
|
||||
windows_exporter.exe: **/*.go
|
||||
build: generate windows_exporter.exe
|
||||
|
||||
windows_exporter.exe: pkg/**/*.go
|
||||
promu build -v
|
||||
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
test:
|
||||
go test -v ./...
|
||||
|
||||
bench:
|
||||
go test -v -bench='benchmark(cpu|logicaldisk|logon|memory|net|process|service|system|tcp|time)collector' ./...
|
||||
go test -v -bench='benchmarkcollector' ./pkg/collector/{cpu,logical_disk,physical_disk,logon,memory,net,printer,process,service,system,tcp,time}
|
||||
|
||||
lint:
|
||||
golangci-lint -c .golangci.yaml run
|
||||
@@ -18,11 +38,59 @@ lint:
|
||||
e2e-test: windows_exporter.exe
|
||||
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 .
|
||||
|
||||
crossbuild:
|
||||
crossbuild: generate
|
||||
# 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=386 promu build --prefix=output/386
|
||||
GOARCH=arm64 promu build --prefix=output/arm64
|
||||
|
||||
.PHONY: package
|
||||
package: crossbuild
|
||||
powershell -NonInteractive -ExecutionPolicy Bypass -File .\installer\build.ps1 -PathToExecutable .\output\amd64\windows_exporter.exe -Version $(shell git describe --tags --abbrev=0)
|
||||
|
||||
build-image: crossbuild
|
||||
$(DOCKER) build --build-arg=BASE=$(BASE_IMAGE):$(OS) -f Dockerfile -t local/$(DOCKER_IMAGE_NAME):$(VERSION)-$(OS) .
|
||||
|
||||
build-hostprocess:
|
||||
$(DOCKER) buildx build --build-arg=BASE=mcr.microsoft.com/oss/kubernetes/windows-host-process-containers-base-image:v1.0.0 -f Dockerfile -t local/$(DOCKER_IMAGE_NAME):$(VERSION)-hostprocess .
|
||||
|
||||
sub-build-%:
|
||||
$(MAKE) OS=$* build-image
|
||||
|
||||
build-all: $(addprefix sub-build-,$(ALL_OS)) build-hostprocess
|
||||
|
||||
push:
|
||||
set -x; \
|
||||
for docker_repo in ${DOCKER_REPO}; do \
|
||||
for osversion in ${ALL_OS}; do \
|
||||
$(DOCKER) tag local/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion} $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
|
||||
$(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); \
|
||||
done
|
||||
|
||||
# We can't load the image into the local docker store, so we have to build and push it in one go
|
||||
push-hostprocess:
|
||||
set -x; \
|
||||
for docker_repo in ${DOCKER_REPO}; do \
|
||||
$(DOCKER) buildx build --push --build-arg=BASE=mcr.microsoft.com/oss/kubernetes/windows-host-process-containers-base-image:v1.0.0 -f Dockerfile -t $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION)-hostprocess .; \
|
||||
done
|
||||
|
||||
.PHONY: push-all
|
||||
push-all: build-all
|
||||
$(MAKE) DOCKER_REPO="$(ALL_DOCKER_REPOS)" push # push-hostprocess - disabled until it works on Windows
|
||||
|
||||
# Mandatory target for container description sync action
|
||||
.PHONY: docker-repo-name
|
||||
docker-repo-name:
|
||||
@echo "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)"
|
||||
|
||||
116
README.md
116
README.md
@@ -1,21 +1,22 @@
|
||||
# windows_exporter
|
||||
|
||||
[](https://ci.appveyor.com/project/prometheus-community/windows-exporter)
|
||||

|
||||
|
||||
A Prometheus exporter for Windows machines.
|
||||
|
||||
|
||||
## Collectors
|
||||
|
||||
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 | ✓
|
||||
[cpu_info](docs/collector.cpu_info.md) | CPU Information |
|
||||
[cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) | ✓
|
||||
[container](docs/collector.container.md) | Container metrics |
|
||||
[diskdrive](docs/collector.diskdrive.md) | Diskdrive metrics |
|
||||
[dfsr](docs/collector.dfsr.md) | DFSR metrics |
|
||||
[dhcp](docs/collector.dhcp.md) | DHCP Server |
|
||||
[dns](docs/collector.dns.md) | DNS Server |
|
||||
@@ -23,9 +24,15 @@ Name | Description | Enabled by default
|
||||
[fsrmquota](docs/collector.fsrmquota.md) | Microsoft File Server Resource Manager (FSRM) Quotas collector |
|
||||
[hyperv](docs/collector.hyperv.md) | Hyper-V hosts |
|
||||
[iis](docs/collector.iis.md) | IIS sites and applications |
|
||||
[license](docs/collector.license.md) | Windows license status |
|
||||
[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 |
|
||||
@@ -38,16 +45,23 @@ Name | Description | Enabled by default
|
||||
[netframework_clrsecurity](docs/collector.netframework_clrsecurity.md) | .NET Framework Security Check metrics |
|
||||
[net](docs/collector.net.md) | Network interface I/O | ✓
|
||||
[os](docs/collector.os.md) | OS metrics (memory, processes, users) | ✓
|
||||
[physical_disk](docs/collector.physical_disk.md) | physical disk metrics | ✓
|
||||
[printer](docs/collector.printer.md) | Printer metrics |
|
||||
[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 | ✓
|
||||
[smb](docs/collector.smb.md) | SMB Server |
|
||||
[smbclient](docs/collector.smbclient.md) | SMB Client |
|
||||
[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.
|
||||
@@ -71,15 +85,17 @@ This can be useful for having different Prometheus servers collect specific metr
|
||||
|
||||
windows_exporter accepts flags to configure certain behaviours. The ones configuring the global behaviour of the exporter are listed below, while collector-specific ones are documented in the respective collector documentation above.
|
||||
|
||||
Flag | Description | Default value
|
||||
---------|-------------|--------------------
|
||||
`--telemetry.addr` | host:port for exporter. | `:9182`
|
||||
`--telemetry.path` | URL path for surfacing collected metrics. | `/metrics`
|
||||
`--telemetry.max-requests` | Maximum number of concurrent requests. 0 to disable. | `5`
|
||||
`--collectors.enabled` | Comma-separated list of collectors to use. Use `[defaults]` as a placeholder 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
|
||||
| Flag | Description | Default value |
|
||||
|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
||||
| `--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 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).
|
||||
@@ -88,15 +104,17 @@ Each release provides a .msi installer. The installer will setup the windows_exp
|
||||
|
||||
If the installer is run without any parameters, the exporter will run with default settings for enabled collectors, ports, etc. The following parameters are available:
|
||||
|
||||
Name | Description
|
||||
-----|------------
|
||||
`ENABLED_COLLECTORS` | As the `--collectors.enabled` flag, provide a comma-separated list of enabled collectors
|
||||
`LISTEN_ADDR` | The IP address to bind to. Defaults to 0.0.0.0
|
||||
`LISTEN_PORT` | The port to bind to. Defaults to 9182.
|
||||
`METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics`
|
||||
`TEXTFILE_DIR` | As the `--collector.textfile.directory` flag, provide a directory to read text files with metrics from
|
||||
`REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (whitelist). Defaults to an empty string (any remote address).
|
||||
`EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string.
|
||||
| Name | Description |
|
||||
|----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `ENABLED_COLLECTORS` | As the `--collectors.enabled` flag, provide a comma-separated list of enabled collectors |
|
||||
| `LISTEN_ADDR` | The IP address to bind to. Defaults to an empty string. (any local address) |
|
||||
| `LISTEN_PORT` | The port to bind to. Defaults to `9182`. |
|
||||
| `METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics` |
|
||||
| `TEXTFILE_DIRS` | As the `--collector.textfile.directories` 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 (allow list). Defaults to an empty string (any remote address). |
|
||||
| `EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string. |
|
||||
| `ADD_FIREWALL_EXCEPTION` | Setup an firewall exception for windows_exporter. Defaults to `yes`. |
|
||||
| `ENABLE_V1_PERFORMANCE_COUNTERS` | Enables V1 performance counter on modern systems. Defaults to `yes`. |
|
||||
|
||||
Parameters are sent to the installer via `msiexec`. Example invocations:
|
||||
|
||||
@@ -109,14 +127,56 @@ Example service collector with a custom query.
|
||||
msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,service --% EXTRA_FLAGS="--collector.service.services-where ""Name LIKE 'sql%'"""
|
||||
```
|
||||
|
||||
On some older versions of Windows you may need to surround parameter values with double quotes to get the install command parsing properly:
|
||||
On some older versions of Windows,
|
||||
you may need to surround parameter values with double quotes to get the installation command parsing properly:
|
||||
```powershell
|
||||
msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,thermalzone" TEXTFILE_DIR="C:\custom_metrics\"
|
||||
msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,textfile,thermalzone" TEXTFILE_DIRS="C:\custom_metrics\"
|
||||
```
|
||||
|
||||
To install the exporter with creating a firewall exception, use the following command:
|
||||
|
||||
```powershell
|
||||
msiexec /i <path-to-msi-file> ADD_FIREWALL_EXCEPTION=yes
|
||||
```
|
||||
|
||||
To repair an installation, e.g force re-creating Windows service:
|
||||
|
||||
```powershell
|
||||
msiexec /fa <path-to-msi-file>
|
||||
```
|
||||
|
||||
|
||||
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%'"""
|
||||
```
|
||||
|
||||
## Docker Implementation
|
||||
|
||||
The windows_exporter can be run as a Docker container. The Docker image is available on
|
||||
|
||||
* [Docker Hub](https://hub.docker.com/r/prometheuscommunity/windows-exporter): `docker.io/prometheuscommunity/windows-exporter`
|
||||
* [GitHub Container Registry](https://github.com/prometheus-community/windows_exporter/pkgs/container/windows-exporter): `ghcr.io/prometheus-community/windows-exporter`
|
||||
<!-- * [quay.io Registry](https://quay.io/repository/prometheuscommunity/windows-exporter): `quay.io/prometheuscommunity/windows-exporter` -->
|
||||
|
||||
### Tags
|
||||
|
||||
The Docker image is tagged with the version of the exporter. The `latest` tag is also available and points to the latest release.
|
||||
|
||||
Additionally, a flavor `hostprocess` with `-hostprocess` as suffix is based on the https://github.com/microsoft/windows-host-process-containers-base-image
|
||||
which is designed to run as a Windows host process container. The size of that images is smaller than the default one.
|
||||
|
||||
## Kubernetes Implementation
|
||||
|
||||
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.
|
||||
`windows_exporter` supports Windows Server versions 2016 and later, and desktop Windows version 10 and 11 (21H2 or later).
|
||||
|
||||
Windows Server 2012 and 2012R2 are supported as best-effort only, but not guaranteed to work.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -136,7 +196,7 @@ 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.
|
||||
|
||||
@@ -145,12 +205,16 @@ When there are multiple processes with the same name, WMI represents those after
|
||||
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:
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
The Prometheus security policy, including how to report vulnerabilities, can be
|
||||
found here:
|
||||
|
||||
https://prometheus.io/docs/operating/security/
|
||||
<https://prometheus.io/docs/operating/security/>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkADCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "ad", NewADCollector)
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"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
|
||||
}
|
||||
|
||||
// newADFSCollector constructs a new adfsCollector
|
||||
func newADFSCollector() (Collector, error) {
|
||||
const subsystem = "adfs"
|
||||
|
||||
return &adfsCollector{
|
||||
adLoginConnectionFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "ad_login_connection_failures_total"),
|
||||
"Total number of connection failures to an Active Directory domain controller",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
certificateAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "certificate_authentications_total"),
|
||||
"Total number of User Certificate authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
deviceAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "device_authentications_total"),
|
||||
"Total number of Device authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
extranetAccountLockouts: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "extranet_account_lockouts_total"),
|
||||
"Total number of Extranet Account Lockouts",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
federatedAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "federated_authentications_total"),
|
||||
"Total number of authentications from a federated source",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
passportAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "passport_authentications_total"),
|
||||
"Total number of Microsoft Passport SSO authentications",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
passiveRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "passive_requests_total"),
|
||||
"Total number of passive (browser-based) requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
passwordChangeFailed: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "password_change_failed_total"),
|
||||
"Total number of failed password changes",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
passwordChangeSucceeded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "password_change_succeeded_total"),
|
||||
"Total number of successful password changes",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
tokenRequests: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "token_requests_total"),
|
||||
"Total number of token requests",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
windowsIntegratedAuthentications: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "windows_integrated_authentications_total"),
|
||||
"Total number of Windows integrated authentications (Kerberos/NTLM)",
|
||||
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"`
|
||||
}
|
||||
|
||||
func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
var adfsData []perflibADFS
|
||||
err := unmarshalObject(ctx.perfObjects["AD FS"], &adfsData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.adLoginConnectionFailures,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].AdLoginConnectionFailures,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.certificateAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].CertificateAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.deviceAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].DeviceAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.extranetAccountLockouts,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].ExtranetAccountLockouts,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.federatedAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].FederatedAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.passportAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].PassportAuthentications,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.passiveRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].PassiveRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.passwordChangeFailed,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].PasswordChangeFailed,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.passwordChangeSucceeded,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].PasswordChangeSucceeded,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.tokenRequests,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].TokenRequests,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.windowsIntegratedAuthentications,
|
||||
prometheus.CounterValue,
|
||||
adfsData[0].WindowsIntegratedAuthentications,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkADFSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "adfs", newADFSCollector)
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/leoluk/perflib_exporter/perflib"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
// ...
|
||||
const (
|
||||
// TODO: Make package-local
|
||||
Namespace = "windows"
|
||||
|
||||
// Conversion factors
|
||||
ticksToSecondsScaleFactor = 1 / 1e7
|
||||
windowsEpoch = 116444736000000000
|
||||
)
|
||||
|
||||
// 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 {
|
||||
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)
|
||||
return 0
|
||||
}
|
||||
defer func() {
|
||||
err = k.Close()
|
||||
if err != nil {
|
||||
log.Warnf("Failed to close registry key: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
currentv, _, err := k.GetStringValue("CurrentVersion")
|
||||
if err != nil {
|
||||
log.Warn("Couldn't open registry to determine current Windows version:", err)
|
||||
return 0
|
||||
}
|
||||
|
||||
currentv_flt, err := strconv.ParseFloat(currentv, 64)
|
||||
|
||||
log.Debugf("Detected Windows version %f\n", currentv_flt)
|
||||
|
||||
return currentv_flt
|
||||
}
|
||||
|
||||
type collectorBuilder func() (Collector, error)
|
||||
|
||||
var (
|
||||
builders = make(map[string]collectorBuilder)
|
||||
perfCounterDependencies = make(map[string]string)
|
||||
)
|
||||
|
||||
func registerCollector(name string, builder collectorBuilder, perfCounterNames ...string) {
|
||||
builders[name] = builder
|
||||
addPerfCounterDependencies(name, perfCounterNames)
|
||||
}
|
||||
|
||||
func addPerfCounterDependencies(name string, perfCounterNames []string) {
|
||||
perfIndicies := make([]string, 0, len(perfCounterNames))
|
||||
for _, cn := range perfCounterNames {
|
||||
perfIndicies = append(perfIndicies, MapCounterToIndex(cn))
|
||||
}
|
||||
perfCounterDependencies[name] = strings.Join(perfIndicies, " ")
|
||||
}
|
||||
|
||||
func Available() []string {
|
||||
cs := make([]string, 0, len(builders))
|
||||
for c := range builders {
|
||||
cs = append(cs, c)
|
||||
}
|
||||
return cs
|
||||
}
|
||||
func Build(collector string) (Collector, error) {
|
||||
builder, exists := builders[collector]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("Unknown collector %q", collector)
|
||||
}
|
||||
return builder()
|
||||
}
|
||||
func getPerfQuery(collectors []string) string {
|
||||
parts := make([]string, 0, len(collectors))
|
||||
for _, c := range collectors {
|
||||
if p := perfCounterDependencies[c]; p != "" {
|
||||
parts = append(parts, p)
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
// Collector is the interface a collector has to implement.
|
||||
type Collector interface {
|
||||
// Get new metrics and expose them via prometheus registry.
|
||||
Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (err error)
|
||||
}
|
||||
|
||||
type ScrapeContext struct {
|
||||
perfObjects map[string]*perflib.PerfObject
|
||||
}
|
||||
|
||||
// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape
|
||||
func PrepareScrapeContext(collectors []string) (*ScrapeContext, error) {
|
||||
q := getPerfQuery(collectors) // TODO: Memoize
|
||||
objs, err := getPerflibSnapshot(q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ScrapeContext{objs}, nil
|
||||
}
|
||||
func boolToFloat(b bool) float64 {
|
||||
if b {
|
||||
return 1.0
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func find(slice []string, val string) bool {
|
||||
for _, item := range slice {
|
||||
if item == val {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Used by more complex collectors where user input specifies enabled child collectors.
|
||||
// Splits provided child collectors and deduplicate.
|
||||
func expandEnabledChildCollectors(enabled string) []string {
|
||||
separated := strings.Split(enabled, ",")
|
||||
unique := map[string]bool{}
|
||||
for _, s := range separated {
|
||||
if s != "" {
|
||||
unique[s] = true
|
||||
}
|
||||
}
|
||||
result := make([]string, 0, len(unique))
|
||||
for s := range unique {
|
||||
result = append(result, s)
|
||||
}
|
||||
// Ensure result is ordered, to prevent test failure
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func TestExpandChildCollectors(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
input string
|
||||
expectedOutput []string
|
||||
}{
|
||||
{
|
||||
name: "simple",
|
||||
input: "testing1,testing2,testing3",
|
||||
expectedOutput: []string{"testing1", "testing2", "testing3"},
|
||||
},
|
||||
{
|
||||
name: "duplicate",
|
||||
input: "testing1,testing2,testing2,testing3",
|
||||
expectedOutput: []string{"testing1", "testing2", "testing3"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
output := expandEnabledChildCollectors(c.input)
|
||||
if !reflect.DeepEqual(output, c.expectedOutput) {
|
||||
t.Errorf("Output mismatch, expected %+v, got %+v", c.expectedOutput, output)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkCollector(b *testing.B, name string, collectFunc func() (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()
|
||||
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,290 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("container", NewContainerMetricsCollector)
|
||||
}
|
||||
|
||||
// A ContainerMetricsCollector is a Prometheus collector for containers metrics
|
||||
type ContainerMetricsCollector struct {
|
||||
// Presence
|
||||
ContainerAvailable *prometheus.Desc
|
||||
|
||||
// Number of containers
|
||||
ContainersCount *prometheus.Desc
|
||||
// memory
|
||||
UsageCommitBytes *prometheus.Desc
|
||||
UsageCommitPeakBytes *prometheus.Desc
|
||||
UsagePrivateWorkingSetBytes *prometheus.Desc
|
||||
|
||||
// CPU
|
||||
RuntimeTotal *prometheus.Desc
|
||||
RuntimeUser *prometheus.Desc
|
||||
RuntimeKernel *prometheus.Desc
|
||||
|
||||
// Network
|
||||
BytesReceived *prometheus.Desc
|
||||
BytesSent *prometheus.Desc
|
||||
PacketsReceived *prometheus.Desc
|
||||
PacketsSent *prometheus.Desc
|
||||
DroppedPacketsIncoming *prometheus.Desc
|
||||
DroppedPacketsOutgoing *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewContainerMetricsCollector constructs a new ContainerMetricsCollector
|
||||
func NewContainerMetricsCollector() (Collector, error) {
|
||||
const subsystem = "container"
|
||||
return &ContainerMetricsCollector{
|
||||
ContainerAvailable: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "available"),
|
||||
"Available",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
ContainersCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "count"),
|
||||
"Number of containers",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
UsageCommitBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "memory_usage_commit_bytes"),
|
||||
"Memory Usage Commit Bytes",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
UsageCommitPeakBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "memory_usage_commit_peak_bytes"),
|
||||
"Memory Usage Commit Peak Bytes",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
UsagePrivateWorkingSetBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "memory_usage_private_working_set_bytes"),
|
||||
"Memory Usage Private Working Set Bytes",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
RuntimeTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_total"),
|
||||
"Total Run time in Seconds",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
RuntimeUser: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_usermode"),
|
||||
"Run Time in User mode in Seconds",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
RuntimeKernel: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_kernelmode"),
|
||||
"Run time in Kernel mode in Seconds",
|
||||
[]string{"container_id"},
|
||||
nil,
|
||||
),
|
||||
BytesReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "network_receive_bytes_total"),
|
||||
"Bytes Received on Interface",
|
||||
[]string{"container_id", "interface"},
|
||||
nil,
|
||||
),
|
||||
BytesSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "network_transmit_bytes_total"),
|
||||
"Bytes Sent on Interface",
|
||||
[]string{"container_id", "interface"},
|
||||
nil,
|
||||
),
|
||||
PacketsReceived: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "network_receive_packets_total"),
|
||||
"Packets Received on Interface",
|
||||
[]string{"container_id", "interface"},
|
||||
nil,
|
||||
),
|
||||
PacketsSent: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "network_transmit_packets_total"),
|
||||
"Packets Sent on Interface",
|
||||
[]string{"container_id", "interface"},
|
||||
nil,
|
||||
),
|
||||
DroppedPacketsIncoming: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "network_receive_packets_dropped_total"),
|
||||
"Dropped Incoming Packets on Interface",
|
||||
[]string{"container_id", "interface"},
|
||||
nil,
|
||||
),
|
||||
DroppedPacketsOutgoing: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "network_transmit_packets_dropped_total"),
|
||||
"Dropped Outgoing Packets on Interface",
|
||||
[]string{"container_id", "interface"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// containerClose closes the container resource
|
||||
func containerClose(c hcsshim.Container) {
|
||||
err := c.Close()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
|
||||
// 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)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count := len(containers)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ContainersCount,
|
||||
prometheus.GaugeValue,
|
||||
float64(count),
|
||||
)
|
||||
if count == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, containerDetails := range containers {
|
||||
container, err := hcsshim.OpenContainer(containerDetails.ID)
|
||||
if container != nil {
|
||||
defer containerClose(container)
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("err in opening container: ", containerDetails.ID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
cstats, err := container.Statistics()
|
||||
if err != nil {
|
||||
log.Error("err in fetching container Statistics: ", containerDetails.ID, err)
|
||||
continue
|
||||
}
|
||||
containerIdWithPrefix := getContainerIdWithPrefix(containerDetails)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ContainerAvailable,
|
||||
prometheus.CounterValue,
|
||||
1,
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.UsageCommitBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(cstats.Memory.UsageCommitBytes),
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.UsageCommitPeakBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(cstats.Memory.UsageCommitPeakBytes),
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.UsagePrivateWorkingSetBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(cstats.Memory.UsagePrivateWorkingSetBytes),
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RuntimeTotal,
|
||||
prometheus.CounterValue,
|
||||
float64(cstats.Processor.TotalRuntime100ns)*ticksToSecondsScaleFactor,
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RuntimeUser,
|
||||
prometheus.CounterValue,
|
||||
float64(cstats.Processor.RuntimeUser100ns)*ticksToSecondsScaleFactor,
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RuntimeKernel,
|
||||
prometheus.CounterValue,
|
||||
float64(cstats.Processor.RuntimeKernel100ns)*ticksToSecondsScaleFactor,
|
||||
containerIdWithPrefix,
|
||||
)
|
||||
|
||||
if len(cstats.Network) == 0 {
|
||||
log.Info("No Network Stats for container: ", containerDetails.ID)
|
||||
continue
|
||||
}
|
||||
|
||||
networkStats := cstats.Network
|
||||
|
||||
for _, networkInterface := range networkStats {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.BytesReceived),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesSent,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.BytesSent),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsReceived,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.PacketsReceived),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsSent,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.PacketsSent),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DroppedPacketsIncoming,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.DroppedPacketsIncoming),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DroppedPacketsOutgoing,
|
||||
prometheus.CounterValue,
|
||||
float64(networkInterface.DroppedPacketsOutgoing),
|
||||
containerIdWithPrefix, networkInterface.EndpointId,
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getContainerIdWithPrefix(containerDetails hcsshim.ContainerProperties) string {
|
||||
switch containerDetails.Owner {
|
||||
case "containerd-shim-runhcs-v1.exe":
|
||||
return "containerd://" + containerDetails.ID
|
||||
default:
|
||||
// default to docker or if owner is not set
|
||||
return "docker://" + containerDetails.ID
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkContainerCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "container", NewContainerMetricsCollector)
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// A CpuInfoCollector is a Prometheus collector for a few WMI metrics in Win32_Processor
|
||||
type CpuInfoCollector struct {
|
||||
CpuInfo *prometheus.Desc
|
||||
}
|
||||
|
||||
func newCpuInfoCollector() (Collector, error) {
|
||||
return &CpuInfoCollector{
|
||||
CpuInfo: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, "", "cpu_info"),
|
||||
"Labeled CPU information as provided provided by Win32_Processor",
|
||||
[]string{
|
||||
"architecture",
|
||||
"device_id",
|
||||
"description",
|
||||
"family",
|
||||
"l2_cache_size",
|
||||
"l3_cache_size",
|
||||
"name"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type win32_Processor struct {
|
||||
Architecture uint32
|
||||
DeviceID string
|
||||
Description string
|
||||
Family uint16
|
||||
L2CacheSize uint32
|
||||
L3CacheSize uint32
|
||||
Name string
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CpuInfoCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []win32_Processor
|
||||
// We use a static query here because the provided methods in wmi.go all issue a SELECT *;
|
||||
// This results in the time consuming LoadPercentage field being read which seems to measure each CPU
|
||||
// serially over a 1 second interval, so the scrape time is at least 1s * num_sockets
|
||||
if err := wmi.Query(win32ProcessorQuery, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
// Some CPUs end up exposing trailing spaces for certain strings, so clean them up
|
||||
for _, processor := range dst {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CpuInfo,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
strconv.Itoa(int(processor.Architecture)),
|
||||
strings.TrimRight(processor.DeviceID, " "),
|
||||
strings.TrimRight(processor.Description, " "),
|
||||
strconv.Itoa(int(processor.Family)),
|
||||
strconv.Itoa(int(processor.L2CacheSize)),
|
||||
strconv.Itoa(int(processor.L3CacheSize)),
|
||||
strings.TrimRight(processor.Name, " "),
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkCPUCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "cpu", newCPUCollector)
|
||||
}
|
||||
108
collector/cs.go
108
collector/cs.go
@@ -1,108 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/prometheus-community/windows_exporter/headers/sysinfoapi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("cs", NewCSCollector)
|
||||
}
|
||||
|
||||
// A CSCollector is a Prometheus collector for WMI metrics
|
||||
type CSCollector struct {
|
||||
PhysicalMemoryBytes *prometheus.Desc
|
||||
LogicalProcessors *prometheus.Desc
|
||||
Hostname *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewCSCollector ...
|
||||
func NewCSCollector() (Collector, error) {
|
||||
const subsystem = "cs"
|
||||
|
||||
return &CSCollector{
|
||||
LogicalProcessors: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "logical_processors"),
|
||||
"ComputerSystem.NumberOfLogicalProcessors",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PhysicalMemoryBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "physical_memory_bytes"),
|
||||
"ComputerSystem.TotalPhysicalMemory",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
Hostname: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "hostname"),
|
||||
"Labeled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain",
|
||||
[]string{
|
||||
"hostname",
|
||||
"domain",
|
||||
"fqdn"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
// 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
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.LogicalProcessors,
|
||||
prometheus.GaugeValue,
|
||||
float64(systemInfo.NumberOfProcessors),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PhysicalMemoryBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(mem.TotalPhys),
|
||||
)
|
||||
|
||||
hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname)
|
||||
if err != nil {
|
||||
return 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,
|
||||
hostname,
|
||||
domain,
|
||||
fqdn,
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkCsCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "cs", NewCSCollector)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDFSRCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "dfsr", NewDFSRCollector)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDHCPCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "dhcp", NewDhcpCollector)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDNSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "dns", NewDNSCollector)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkExchangeCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "exchange", newExchangeCollector)
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("fsrmquota", newFSRMQuotaCollector)
|
||||
}
|
||||
|
||||
type FSRMQuotaCollector struct {
|
||||
QuotasCount *prometheus.Desc
|
||||
Path *prometheus.Desc
|
||||
PeakUsage *prometheus.Desc
|
||||
Size *prometheus.Desc
|
||||
Usage *prometheus.Desc
|
||||
|
||||
Description *prometheus.Desc
|
||||
Disabled *prometheus.Desc
|
||||
MatchesTemplate *prometheus.Desc
|
||||
SoftLimit *prometheus.Desc
|
||||
Template *prometheus.Desc
|
||||
}
|
||||
|
||||
func newFSRMQuotaCollector() (Collector, error) {
|
||||
const subsystem = "fsrmquota"
|
||||
return &FSRMQuotaCollector{
|
||||
QuotasCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "count"),
|
||||
"Number of Quotas",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PeakUsage: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "peak_usage_bytes"),
|
||||
"The highest amount of disk space usage charged to this quota. (PeakUsage)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Size: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "size_bytes"),
|
||||
"The size of the quota. (Size)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Usage: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "usage_bytes"),
|
||||
"The current amount of disk space usage charged to this quota. (Usage)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Description: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "description"),
|
||||
"Description of the quota (Description)",
|
||||
[]string{"path", "template", "description"},
|
||||
nil,
|
||||
),
|
||||
Disabled: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "disabled"),
|
||||
"If 1, the quota is disabled. The default value is 0. (Disabled)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
SoftLimit: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "softlimit"),
|
||||
"If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
Template: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "template"),
|
||||
"Quota template name. (Template)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
MatchesTemplate: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "matchestemplate"),
|
||||
"If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)",
|
||||
[]string{"path", "template"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *FSRMQuotaCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting fsrmquota metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MSFT_FSRMQuota docs:
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
|
||||
type MSFT_FSRMQuota struct {
|
||||
Name string
|
||||
|
||||
Path string
|
||||
PeakUsage uint64
|
||||
Size uint64
|
||||
Usage uint64
|
||||
Description string
|
||||
Template string
|
||||
//Threshold string
|
||||
Disabled bool
|
||||
MatchesTemplate bool
|
||||
SoftLimit bool
|
||||
}
|
||||
|
||||
func (c *FSRMQuotaCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []MSFT_FSRMQuota
|
||||
q := queryAll(&dst)
|
||||
|
||||
var count int
|
||||
|
||||
if err := wmi.QueryNamespace(q, &dst, "root/microsoft/windows/fsrm"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, quota := range dst {
|
||||
|
||||
count++
|
||||
path := quota.Path
|
||||
template := quota.Template
|
||||
Description := quota.Description
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PeakUsage,
|
||||
prometheus.GaugeValue,
|
||||
float64(quota.PeakUsage),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Size,
|
||||
prometheus.GaugeValue,
|
||||
float64(quota.Size),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Usage,
|
||||
prometheus.GaugeValue,
|
||||
float64(quota.Usage),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Description,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
path, template, Description,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Disabled,
|
||||
prometheus.GaugeValue,
|
||||
boolToFloat(quota.Disabled),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MatchesTemplate,
|
||||
prometheus.GaugeValue,
|
||||
boolToFloat(quota.MatchesTemplate),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SoftLimit,
|
||||
prometheus.GaugeValue,
|
||||
boolToFloat(quota.SoftLimit),
|
||||
path,
|
||||
template,
|
||||
)
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.QuotasCount,
|
||||
prometheus.GaugeValue,
|
||||
float64(count),
|
||||
)
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkFsrmQuotaCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "fsrmquota", newFSRMQuotaCollector)
|
||||
}
|
||||
1433
collector/hyperv.go
1433
collector/hyperv.go
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkHypervCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "hyperv", NewHyperVCollector)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkIISCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "iis", NewIISCollector)
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("logical_disk", NewLogicalDiskCollector, "LogicalDisk")
|
||||
}
|
||||
|
||||
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()
|
||||
)
|
||||
|
||||
// A LogicalDiskCollector is a Prometheus collector for perflib logicalDisk metrics
|
||||
type LogicalDiskCollector struct {
|
||||
RequestsQueued *prometheus.Desc
|
||||
ReadBytesTotal *prometheus.Desc
|
||||
ReadsTotal *prometheus.Desc
|
||||
WriteBytesTotal *prometheus.Desc
|
||||
WritesTotal *prometheus.Desc
|
||||
ReadTime *prometheus.Desc
|
||||
WriteTime *prometheus.Desc
|
||||
TotalSpace *prometheus.Desc
|
||||
FreeSpace *prometheus.Desc
|
||||
IdleTime *prometheus.Desc
|
||||
SplitIOs *prometheus.Desc
|
||||
ReadLatency *prometheus.Desc
|
||||
WriteLatency *prometheus.Desc
|
||||
ReadWriteLatency *prometheus.Desc
|
||||
|
||||
volumeWhitelistPattern *regexp.Regexp
|
||||
volumeBlacklistPattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewLogicalDiskCollector ...
|
||||
func NewLogicalDiskCollector() (Collector, error) {
|
||||
const subsystem = "logical_disk"
|
||||
|
||||
return &LogicalDiskCollector{
|
||||
RequestsQueued: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "requests_queued"),
|
||||
"The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)",
|
||||
[]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)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
ReadsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "reads_total"),
|
||||
"The number of read operations on the disk (LogicalDisk.DiskReadsPerSec)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WriteBytesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "write_bytes_total"),
|
||||
"The number of bytes transferred to the disk during write operations (LogicalDisk.DiskWriteBytesPerSec)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WritesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "writes_total"),
|
||||
"The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
ReadTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "read_seconds_total"),
|
||||
"Seconds that the disk was busy servicing read requests (LogicalDisk.PercentDiskReadTime)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WriteTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "write_seconds_total"),
|
||||
"Seconds that the disk was busy servicing write requests (LogicalDisk.PercentDiskWriteTime)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
FreeSpace: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "free_bytes"),
|
||||
"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, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
IdleTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "idle_seconds_total"),
|
||||
"Seconds that the disk was idle (LogicalDisk.PercentIdleTime)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
SplitIOs: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "split_ios_total"),
|
||||
"The number of I/Os to the disk were split into multiple I/Os (LogicalDisk.SplitIOPerSec)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
ReadLatency: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "read_latency_seconds_total"),
|
||||
"Shows the average time, in seconds, of a read operation from the disk (LogicalDisk.AvgDiskSecPerRead)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
WriteLatency: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "write_latency_seconds_total"),
|
||||
"Shows the average time, in seconds, of a write operation to the disk (LogicalDisk.AvgDiskSecPerWrite)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
ReadWriteLatency: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "read_write_latency_seconds_total"),
|
||||
"Shows the time, in seconds, of the average disk transfer (LogicalDisk.AvgDiskSecPerTransfer)",
|
||||
[]string{"volume"},
|
||||
nil,
|
||||
),
|
||||
|
||||
volumeWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeWhitelist)),
|
||||
volumeBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeBlacklist)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_PerfDisk_LogicalDisk docs:
|
||||
// - 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"`
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, volume := range dst {
|
||||
if volume.Name == "_Total" ||
|
||||
c.volumeBlacklistPattern.MatchString(volume.Name) ||
|
||||
!c.volumeWhitelistPattern.MatchString(volume.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RequestsQueued,
|
||||
prometheus.GaugeValue,
|
||||
volume.CurrentDiskQueueLength,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
volume.DiskReadBytesPerSec,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadsTotal,
|
||||
prometheus.CounterValue,
|
||||
volume.DiskReadsPerSec,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WriteBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
volume.DiskWriteBytesPerSec,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WritesTotal,
|
||||
prometheus.CounterValue,
|
||||
volume.DiskWritesPerSec,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadTime,
|
||||
prometheus.CounterValue,
|
||||
volume.PercentDiskReadTime,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WriteTime,
|
||||
prometheus.CounterValue,
|
||||
volume.PercentDiskWriteTime,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FreeSpace,
|
||||
prometheus.GaugeValue,
|
||||
volume.PercentFreeSpace_Base*1024*1024,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalSpace,
|
||||
prometheus.GaugeValue,
|
||||
volume.PercentFreeSpace*1024*1024,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IdleTime,
|
||||
prometheus.CounterValue,
|
||||
volume.PercentIdleTime,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SplitIOs,
|
||||
prometheus.CounterValue,
|
||||
volume.SplitIOPerSec,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadLatency,
|
||||
prometheus.CounterValue,
|
||||
volume.AvgDiskSecPerRead*ticksToSecondsScaleFactor,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WriteLatency,
|
||||
prometheus.CounterValue,
|
||||
volume.AvgDiskSecPerWrite*ticksToSecondsScaleFactor,
|
||||
volume.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ReadWriteLatency,
|
||||
prometheus.CounterValue,
|
||||
volume.AvgDiskSecPerTransfer*ticksToSecondsScaleFactor,
|
||||
volume.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
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.
|
||||
localVolumeWhitelist := ".+"
|
||||
volumeWhitelist = &localVolumeWhitelist
|
||||
|
||||
benchmarkCollector(b, "logical_disk", NewLogicalDiskCollector)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkLogonCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewLogonCollector)
|
||||
}
|
||||
@@ -1,503 +0,0 @@
|
||||
// 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/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("memory", NewMemoryCollector, "Memory")
|
||||
}
|
||||
|
||||
// A MemoryCollector is a Prometheus collector for perflib Memory metrics
|
||||
type MemoryCollector struct {
|
||||
AvailableBytes *prometheus.Desc
|
||||
CacheBytes *prometheus.Desc
|
||||
CacheBytesPeak *prometheus.Desc
|
||||
CacheFaultsTotal *prometheus.Desc
|
||||
CommitLimit *prometheus.Desc
|
||||
CommittedBytes *prometheus.Desc
|
||||
DemandZeroFaultsTotal *prometheus.Desc
|
||||
FreeAndZeroPageListBytes *prometheus.Desc
|
||||
FreeSystemPageTableEntries *prometheus.Desc
|
||||
ModifiedPageListBytes *prometheus.Desc
|
||||
PageFaultsTotal *prometheus.Desc
|
||||
SwapPageReadsTotal *prometheus.Desc
|
||||
SwapPagesReadTotal *prometheus.Desc
|
||||
SwapPagesWrittenTotal *prometheus.Desc
|
||||
SwapPageOperationsTotal *prometheus.Desc
|
||||
SwapPageWritesTotal *prometheus.Desc
|
||||
PoolNonpagedAllocsTotal *prometheus.Desc
|
||||
PoolNonpagedBytes *prometheus.Desc
|
||||
PoolPagedAllocsTotal *prometheus.Desc
|
||||
PoolPagedBytes *prometheus.Desc
|
||||
PoolPagedResidentBytes *prometheus.Desc
|
||||
StandbyCacheCoreBytes *prometheus.Desc
|
||||
StandbyCacheNormalPriorityBytes *prometheus.Desc
|
||||
StandbyCacheReserveBytes *prometheus.Desc
|
||||
SystemCacheResidentBytes *prometheus.Desc
|
||||
SystemCodeResidentBytes *prometheus.Desc
|
||||
SystemCodeTotalBytes *prometheus.Desc
|
||||
SystemDriverResidentBytes *prometheus.Desc
|
||||
SystemDriverTotalBytes *prometheus.Desc
|
||||
TransitionFaultsTotal *prometheus.Desc
|
||||
TransitionPagesRepurposedTotal *prometheus.Desc
|
||||
WriteCopiesTotal *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewMemoryCollector ...
|
||||
func NewMemoryCollector() (Collector, error) {
|
||||
const subsystem = "memory"
|
||||
|
||||
return &MemoryCollector{
|
||||
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"+
|
||||
" the standby (cached), free and zero page lists (AvailableBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CacheBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cache_bytes"),
|
||||
"(CacheBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CacheBytesPeak: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cache_bytes_peak"),
|
||||
"(CacheBytesPeak)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CacheFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cache_faults_total"),
|
||||
"(CacheFaultsPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CommitLimit: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "commit_limit"),
|
||||
"(CommitLimit)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CommittedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "committed_bytes"),
|
||||
"(CommittedBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
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)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
FreeAndZeroPageListBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "free_and_zero_page_list_bytes"),
|
||||
"(FreeAndZeroPageListBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
FreeSystemPageTableEntries: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "free_system_page_table_entries"),
|
||||
"(FreeSystemPageTableEntries)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ModifiedPageListBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "modified_page_list_bytes"),
|
||||
"(ModifiedPageListBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PageFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"),
|
||||
"(PageFaultsPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SwapPageReadsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "swap_page_reads_total"),
|
||||
"Number of disk page reads (a single read operation reading several pages is still only counted once) (PageReadsPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SwapPagesReadTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "swap_pages_read_total"),
|
||||
"Number of pages read across all page reads (ie counting all pages read even if they are read in a single operation) (PagesInputPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SwapPagesWrittenTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "swap_pages_written_total"),
|
||||
"Number of pages written across all page writes (ie counting all pages written even if they are written in a single operation) (PagesOutputPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SwapPageOperationsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "swap_page_operations_total"),
|
||||
"Total number of swap page read and writes (PagesPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SwapPageWritesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "swap_page_writes_total"),
|
||||
"Number of disk page writes (a single write operation writing several pages is still only counted once) (PageWritesPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PoolNonpagedAllocsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_allocs_total"),
|
||||
"The number of calls to allocate space in the nonpaged pool. The nonpaged pool is an area of system memory area for objects that cannot be written"+
|
||||
" to disk, and must remain in physical memory as long as they are allocated (PoolNonpagedAllocs)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PoolNonpagedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_bytes_total"),
|
||||
"(PoolNonpagedBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PoolPagedAllocsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_paged_allocs_total"),
|
||||
"(PoolPagedAllocs)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PoolPagedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_paged_bytes"),
|
||||
"(PoolPagedBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PoolPagedResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_paged_resident_bytes"),
|
||||
"(PoolPagedResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
StandbyCacheCoreBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "standby_cache_core_bytes"),
|
||||
"(StandbyCacheCoreBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
StandbyCacheNormalPriorityBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "standby_cache_normal_priority_bytes"),
|
||||
"(StandbyCacheNormalPriorityBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
StandbyCacheReserveBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "standby_cache_reserve_bytes"),
|
||||
"(StandbyCacheReserveBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemCacheResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_cache_resident_bytes"),
|
||||
"(SystemCacheResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemCodeResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_code_resident_bytes"),
|
||||
"(SystemCodeResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemCodeTotalBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_code_total_bytes"),
|
||||
"(SystemCodeTotalBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemDriverResidentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_driver_resident_bytes"),
|
||||
"(SystemDriverResidentBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemDriverTotalBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_driver_total_bytes"),
|
||||
"(SystemDriverTotalBytes)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TransitionFaultsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "transition_faults_total"),
|
||||
"(TransitionFaultsPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
TransitionPagesRepurposedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "transition_pages_repurposed_total"),
|
||||
"(TransitionPagesRePurposedPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
WriteCopiesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "write_copies_total"),
|
||||
"The number of page faults caused by attempting to write that were satisfied by copying the page from elsewhere in physical memory (WriteCopiesPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type memory struct {
|
||||
AvailableBytes float64 `perflib:"Available Bytes"`
|
||||
AvailableKBytes float64 `perflib:"Available KBytes"`
|
||||
AvailableMBytes float64 `perflib:"Available MBytes"`
|
||||
CacheBytes float64 `perflib:"Cache Bytes"`
|
||||
CacheBytesPeak float64 `perflib:"Cache Bytes Peak"`
|
||||
CacheFaultsPersec float64 `perflib:"Cache Faults/sec"`
|
||||
CommitLimit float64 `perflib:"Commit Limit"`
|
||||
CommittedBytes float64 `perflib:"Committed Bytes"`
|
||||
DemandZeroFaultsPersec float64 `perflib:"Demand Zero Faults/sec"`
|
||||
FreeAndZeroPageListBytes float64 `perflib:"Free & Zero Page List Bytes"`
|
||||
FreeSystemPageTableEntries float64 `perflib:"Free System Page Table Entries"`
|
||||
ModifiedPageListBytes float64 `perflib:"Modified Page List Bytes"`
|
||||
PageFaultsPersec float64 `perflib:"Page Faults/sec"`
|
||||
PageReadsPersec float64 `perflib:"Page Reads/sec"`
|
||||
PagesInputPersec float64 `perflib:"Pages Input/sec"`
|
||||
PagesOutputPersec float64 `perflib:"Pages Output/sec"`
|
||||
PagesPersec float64 `perflib:"Pages/sec"`
|
||||
PageWritesPersec float64 `perflib:"Page Writes/sec"`
|
||||
PoolNonpagedAllocs float64 `perflib:"Pool Nonpaged Allocs"`
|
||||
PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
|
||||
PoolPagedAllocs float64 `perflib:"Pool Paged Allocs"`
|
||||
PoolPagedBytes float64 `perflib:"Pool Paged Bytes"`
|
||||
PoolPagedResidentBytes float64 `perflib:"Pool Paged Resident Bytes"`
|
||||
StandbyCacheCoreBytes float64 `perflib:"Standby Cache Core Bytes"`
|
||||
StandbyCacheNormalPriorityBytes float64 `perflib:"Standby Cache Normal Priority Bytes"`
|
||||
StandbyCacheReserveBytes float64 `perflib:"Standby Cache Reserve Bytes"`
|
||||
SystemCacheResidentBytes float64 `perflib:"System Cache Resident Bytes"`
|
||||
SystemCodeResidentBytes float64 `perflib:"System Code Resident Bytes"`
|
||||
SystemCodeTotalBytes float64 `perflib:"System Code Total Bytes"`
|
||||
SystemDriverResidentBytes float64 `perflib:"System Driver Resident Bytes"`
|
||||
SystemDriverTotalBytes float64 `perflib:"System Driver Total Bytes"`
|
||||
TransitionFaultsPersec float64 `perflib:"Transition Faults/sec"`
|
||||
TransitionPagesRePurposedPersec float64 `perflib:"Transition Pages RePurposed/sec"`
|
||||
WriteCopiesPersec float64 `perflib:"Write Copies/sec"`
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AvailableBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].AvailableBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CacheBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].CacheBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CacheBytesPeak,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].CacheBytesPeak,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CacheFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].CacheFaultsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CommitLimit,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].CommitLimit,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CommittedBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].CommittedBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.DemandZeroFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].DemandZeroFaultsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FreeAndZeroPageListBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].FreeAndZeroPageListBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FreeSystemPageTableEntries,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].FreeSystemPageTableEntries,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ModifiedPageListBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].ModifiedPageListBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PageFaultsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPageReadsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PageReadsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPagesReadTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PagesInputPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPagesWrittenTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PagesOutputPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPageOperationsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PagesPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SwapPageWritesTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PageWritesPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolNonpagedAllocsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PoolNonpagedAllocs,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolNonpagedBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PoolNonpagedBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolPagedAllocsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PoolPagedAllocs,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolPagedBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PoolPagedBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolPagedResidentBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].PoolPagedResidentBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StandbyCacheCoreBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].StandbyCacheCoreBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StandbyCacheNormalPriorityBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].StandbyCacheNormalPriorityBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StandbyCacheReserveBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].StandbyCacheReserveBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SystemCacheResidentBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].SystemCacheResidentBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SystemCodeResidentBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].SystemCodeResidentBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SystemCodeTotalBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].SystemCodeTotalBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SystemDriverResidentBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].SystemDriverResidentBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SystemDriverTotalBytes,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].SystemDriverTotalBytes,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TransitionFaultsTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].TransitionFaultsPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TransitionPagesRepurposedTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].TransitionPagesRePurposedPersec,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WriteCopiesTotal,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].WriteCopiesPersec,
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMemoryCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "memory", NewMemoryCollector)
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("msmq", NewMSMQCollector)
|
||||
}
|
||||
|
||||
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()
|
||||
)
|
||||
|
||||
// A Win32_PerfRawData_MSMQ_MSMQQueueCollector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics
|
||||
type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct {
|
||||
BytesinJournalQueue *prometheus.Desc
|
||||
BytesinQueue *prometheus.Desc
|
||||
MessagesinJournalQueue *prometheus.Desc
|
||||
MessagesinQueue *prometheus.Desc
|
||||
|
||||
queryWhereClause string
|
||||
}
|
||||
|
||||
// NewWin32_PerfRawData_MSMQ_MSMQQueueCollector ...
|
||||
func NewMSMQCollector() (Collector, error) {
|
||||
const subsystem = "msmq"
|
||||
|
||||
if *msmqWhereClause == "" {
|
||||
log.Warn("No where-clause specified for msmq collector. This will generate a very large number of metrics!")
|
||||
}
|
||||
|
||||
return &Win32_PerfRawData_MSMQ_MSMQQueueCollector{
|
||||
BytesinJournalQueue: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_in_journal_queue"),
|
||||
"Size of queue journal in bytes",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
BytesinQueue: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_in_queue"),
|
||||
"Size of queue in bytes",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
MessagesinJournalQueue: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "messages_in_journal_queue"),
|
||||
"Count messages in queue journal",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
MessagesinQueue: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "messages_in_queue"),
|
||||
"Count messages in queue",
|
||||
[]string{"name"},
|
||||
nil,
|
||||
),
|
||||
queryWhereClause: *msmqWhereClause,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_MSMQ_MSMQQueue struct {
|
||||
Name string
|
||||
|
||||
BytesinJournalQueue uint64
|
||||
BytesinQueue uint64
|
||||
MessagesinJournalQueue uint64
|
||||
MessagesinQueue uint64
|
||||
}
|
||||
|
||||
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)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, msmq := range dst {
|
||||
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,
|
||||
float64(msmq.MessagesinQueue),
|
||||
strings.ToLower(msmq.Name),
|
||||
)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMsmqCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewMSMQCollector)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMSSQLCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "mssql", NewMSSQLCollector)
|
||||
}
|
||||
260
collector/net.go
260
collector/net.go
@@ -1,260 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("net", NewNetworkCollector, "Network Interface")
|
||||
}
|
||||
|
||||
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()
|
||||
nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
|
||||
)
|
||||
|
||||
// A NetworkCollector is a Prometheus collector for Perflib Network Interface metrics
|
||||
type NetworkCollector struct {
|
||||
BytesReceivedTotal *prometheus.Desc
|
||||
BytesSentTotal *prometheus.Desc
|
||||
BytesTotal *prometheus.Desc
|
||||
PacketsOutboundDiscarded *prometheus.Desc
|
||||
PacketsOutboundErrors *prometheus.Desc
|
||||
PacketsTotal *prometheus.Desc
|
||||
PacketsReceivedDiscarded *prometheus.Desc
|
||||
PacketsReceivedErrors *prometheus.Desc
|
||||
PacketsReceivedTotal *prometheus.Desc
|
||||
PacketsReceivedUnknown *prometheus.Desc
|
||||
PacketsSentTotal *prometheus.Desc
|
||||
CurrentBandwidth *prometheus.Desc
|
||||
|
||||
nicWhitelistPattern *regexp.Regexp
|
||||
nicBlacklistPattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewNetworkCollector ...
|
||||
func NewNetworkCollector() (Collector, error) {
|
||||
const subsystem = "net"
|
||||
|
||||
return &NetworkCollector{
|
||||
BytesReceivedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"),
|
||||
"(Network.BytesReceivedPerSec)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
BytesSentTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"),
|
||||
"(Network.BytesSentPerSec)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
BytesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "bytes_total"),
|
||||
"(Network.BytesTotalPerSec)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsOutboundDiscarded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded_total"),
|
||||
"(Network.PacketsOutboundDiscarded)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsOutboundErrors: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_errors_total"),
|
||||
"(Network.PacketsOutboundErrors)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsReceivedDiscarded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_received_discarded_total"),
|
||||
"(Network.PacketsReceivedDiscarded)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsReceivedErrors: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_received_errors_total"),
|
||||
"(Network.PacketsReceivedErrors)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsReceivedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"),
|
||||
"(Network.PacketsReceivedPerSec)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsReceivedUnknown: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_received_unknown_total"),
|
||||
"(Network.PacketsReceivedUnknown)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_total"),
|
||||
"(Network.PacketsPerSec)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
PacketsSentTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "packets_sent_total"),
|
||||
"(Network.PacketsSentPerSec)",
|
||||
[]string{"nic"},
|
||||
nil,
|
||||
),
|
||||
CurrentBandwidth: prometheus.NewDesc(
|
||||
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)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mangleNetworkName mangles Network Adapter name (non-alphanumeric to _)
|
||||
// that is used in networkInterface.
|
||||
func mangleNetworkName(name string) string {
|
||||
return nicNameToUnderscore.ReplaceAllString(name, "_")
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_Tcpip_NetworkInterface docs:
|
||||
// - https://technet.microsoft.com/en-us/security/aa394340(v=vs.80)
|
||||
type networkInterface struct {
|
||||
BytesReceivedPerSec float64 `perflib:"Bytes Received/sec"`
|
||||
BytesSentPerSec float64 `perflib:"Bytes Sent/sec"`
|
||||
BytesTotalPerSec float64 `perflib:"Bytes Total/sec"`
|
||||
Name string
|
||||
PacketsOutboundDiscarded float64 `perflib:"Packets Outbound Discarded"`
|
||||
PacketsOutboundErrors float64 `perflib:"Packets Outbound Errors"`
|
||||
PacketsPerSec float64 `perflib:"Packets/sec"`
|
||||
PacketsReceivedDiscarded float64 `perflib:"Packets Received Discarded"`
|
||||
PacketsReceivedErrors float64 `perflib:"Packets Received Errors"`
|
||||
PacketsReceivedPerSec float64 `perflib:"Packets Received/sec"`
|
||||
PacketsReceivedUnknown float64 `perflib:"Packets Received Unknown"`
|
||||
PacketsSentPerSec float64 `perflib:"Packets Sent/sec"`
|
||||
CurrentBandwidth float64 `perflib:"Current Bandwidth"`
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, nic := range dst {
|
||||
if c.nicBlacklistPattern.MatchString(nic.Name) ||
|
||||
!c.nicWhitelistPattern.MatchString(nic.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
name := mangleNetworkName(nic.Name)
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Counters
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesReceivedTotal,
|
||||
prometheus.CounterValue,
|
||||
nic.BytesReceivedPerSec,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesSentTotal,
|
||||
prometheus.CounterValue,
|
||||
nic.BytesSentPerSec,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesTotal,
|
||||
prometheus.CounterValue,
|
||||
nic.BytesTotalPerSec,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsOutboundDiscarded,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsOutboundDiscarded,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsOutboundErrors,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsOutboundErrors,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsTotal,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsPerSec,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsReceivedDiscarded,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsReceivedDiscarded,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsReceivedErrors,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsReceivedErrors,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsReceivedTotal,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsReceivedPerSec,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsReceivedUnknown,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsReceivedUnknown,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PacketsSentTotal,
|
||||
prometheus.CounterValue,
|
||||
nic.PacketsSentPerSec,
|
||||
name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentBandwidth,
|
||||
prometheus.GaugeValue,
|
||||
nic.CurrentBandwidth/8,
|
||||
name,
|
||||
)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
NumberofExcepsThrown *prometheus.Desc
|
||||
NumberofFilters *prometheus.Desc
|
||||
NumberofFinallys *prometheus.Desc
|
||||
ThrowToCatchDepth *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRExceptionsCollector ...
|
||||
func NewNETFramework_NETCLRExceptionsCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrexceptions"
|
||||
return &NETFramework_NETCLRExceptionsCollector{
|
||||
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.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberofFilters: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "exceptions_filters_total"),
|
||||
"Displays the total number of .NET exception filters executed. An exception filter evaluates regardless of whether an exception is handled.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberofFinallys: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "exceptions_finallys_total"),
|
||||
"Displays the total number of finally blocks executed. Only the finally blocks executed for an exception are counted; finally blocks on normal code paths are not counted by this counter.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
ThrowToCatchDepth: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "throw_to_catch_depth_total"),
|
||||
"Displays the total number of stack frames traversed, from the frame that threw the exception to the frame that handled the exception.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
|
||||
Name string
|
||||
|
||||
NumberofExcepsThrown uint32
|
||||
NumberofExcepsThrownPersec uint32
|
||||
NumberofFiltersPersec uint32
|
||||
NumberofFinallysPersec uint32
|
||||
ThrowToCatchDepthPersec uint32
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRExceptionsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofExcepsThrown,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberofExcepsThrown),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofFilters,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberofFiltersPersec),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofFinallys,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberofFinallysPersec),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ThrowToCatchDepth,
|
||||
prometheus.CounterValue,
|
||||
float64(process.ThrowToCatchDepthPersec),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNetFrameworkNETCLRExceptionsCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRExceptionsCollector)
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
NumberofCCWs *prometheus.Desc
|
||||
Numberofmarshalling *prometheus.Desc
|
||||
NumberofStubs *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRInteropCollector ...
|
||||
func NewNETFramework_NETCLRInteropCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrinterop"
|
||||
return &NETFramework_NETCLRInteropCollector{
|
||||
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.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
Numberofmarshalling: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "interop_marshalling_total"),
|
||||
"Displays the total number of times arguments and return values have been marshaled from managed to unmanaged code, and vice versa, since the application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberofStubs: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "interop_stubs_created_total"),
|
||||
"Displays the current number of stubs created by the common language runtime. Stubs are responsible for marshaling arguments and return values from managed to unmanaged code, and vice versa, during a COM interop call or a platform invoke call.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
|
||||
Name string
|
||||
|
||||
NumberofCCWs uint32
|
||||
Numberofmarshalling uint32
|
||||
NumberofStubs uint32
|
||||
NumberofTLBexportsPersec uint32
|
||||
NumberofTLBimportsPersec uint32
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRInteropCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofCCWs,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberofCCWs),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Numberofmarshalling,
|
||||
prometheus.CounterValue,
|
||||
float64(process.Numberofmarshalling),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofStubs,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberofStubs),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRInteropCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRInteropCollector)
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
NumberofMethodsJitted *prometheus.Desc
|
||||
TimeinJit *prometheus.Desc
|
||||
StandardJitFailures *prometheus.Desc
|
||||
TotalNumberofILBytesJitted *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRJitCollector ...
|
||||
func NewNETFramework_NETCLRJitCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrjit"
|
||||
return &NETFramework_NETCLRJitCollector{
|
||||
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.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TimeinJit: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "jit_time_percent"),
|
||||
"Displays the percentage of time spent in JIT compilation. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
StandardJitFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "jit_standard_failures_total"),
|
||||
"Displays the peak number of methods the JIT compiler has failed to compile since the application started. This failure can occur if the MSIL cannot be verified or if there is an internal error in the JIT compiler.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalNumberofILBytesJitted: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "jit_il_bytes_total"),
|
||||
"Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by the just-in-time (JIT) compiler since the application started",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRJit struct {
|
||||
Name string
|
||||
|
||||
Frequency_PerfTime uint32
|
||||
ILBytesJittedPersec uint32
|
||||
NumberofILBytesJitted uint32
|
||||
NumberofMethodsJitted uint32
|
||||
PercentTimeinJit uint32
|
||||
StandardJitFailures uint32
|
||||
TotalNumberofILBytesJitted uint32
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRJitCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRJit
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofMethodsJitted,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberofMethodsJitted),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TimeinJit,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.PercentTimeinJit)/float64(process.Frequency_PerfTime),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StandardJitFailures,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.StandardJitFailures),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalNumberofILBytesJitted,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalNumberofILBytesJitted),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRJitCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRJitCollector)
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
BytesinLoaderHeap *prometheus.Desc
|
||||
Currentappdomains *prometheus.Desc
|
||||
CurrentAssemblies *prometheus.Desc
|
||||
CurrentClassesLoaded *prometheus.Desc
|
||||
TotalAppdomains *prometheus.Desc
|
||||
Totalappdomainsunloaded *prometheus.Desc
|
||||
TotalAssemblies *prometheus.Desc
|
||||
TotalClassesLoaded *prometheus.Desc
|
||||
TotalNumberofLoadFailures *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRLoadingCollector ...
|
||||
func NewNETFramework_NETCLRLoadingCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrloading"
|
||||
return &NETFramework_NETCLRLoadingCollector{
|
||||
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.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
Currentappdomains: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "appdomains_loaded_current"),
|
||||
"Displays the current number of application domains loaded in this application.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
CurrentAssemblies: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "assemblies_loaded_current"),
|
||||
"Displays the current number of assemblies loaded across all application domains in the currently running application. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
CurrentClassesLoaded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "classes_loaded_current"),
|
||||
"Displays the current number of classes loaded in all assemblies.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalAppdomains: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "appdomains_loaded_total"),
|
||||
"Displays the peak number of application domains loaded since the application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
Totalappdomainsunloaded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "appdomains_unloaded_total"),
|
||||
"Displays the total number of application domains unloaded since the application started. If an application domain is loaded and unloaded multiple times, this counter increments each time the application domain is unloaded.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalAssemblies: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "assemblies_loaded_total"),
|
||||
"Displays the total number of assemblies loaded since the application started. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalClassesLoaded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "classes_loaded_total"),
|
||||
"Displays the cumulative number of classes loaded in all assemblies since the application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalNumberofLoadFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "class_load_failures_total"),
|
||||
"Displays the peak number of classes that have failed to load since the application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
|
||||
Name string
|
||||
|
||||
AssemblySearchLength uint32
|
||||
BytesinLoaderHeap uint64
|
||||
Currentappdomains uint32
|
||||
CurrentAssemblies uint32
|
||||
CurrentClassesLoaded uint32
|
||||
PercentTimeLoading uint64
|
||||
Rateofappdomains uint32
|
||||
Rateofappdomainsunloaded uint32
|
||||
RateofAssemblies uint32
|
||||
RateofClassesLoaded uint32
|
||||
RateofLoadFailures uint32
|
||||
TotalAppdomains uint32
|
||||
Totalappdomainsunloaded uint32
|
||||
TotalAssemblies uint32
|
||||
TotalClassesLoaded uint32
|
||||
TotalNumberofLoadFailures uint32
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRLoadingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BytesinLoaderHeap,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.BytesinLoaderHeap),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Currentappdomains,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Currentappdomains),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentAssemblies,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.CurrentAssemblies),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentClassesLoaded,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.CurrentClassesLoaded),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalAppdomains,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalAppdomains),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Totalappdomainsunloaded,
|
||||
prometheus.CounterValue,
|
||||
float64(process.Totalappdomainsunloaded),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalAssemblies,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalAssemblies),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalClassesLoaded,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalClassesLoaded),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalNumberofLoadFailures,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalNumberofLoadFailures),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRLoadingCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRLoadingCollector)
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
CurrentQueueLength *prometheus.Desc
|
||||
NumberofcurrentlogicalThreads *prometheus.Desc
|
||||
NumberofcurrentphysicalThreads *prometheus.Desc
|
||||
Numberofcurrentrecognizedthreads *prometheus.Desc
|
||||
Numberoftotalrecognizedthreads *prometheus.Desc
|
||||
QueueLengthPeak *prometheus.Desc
|
||||
TotalNumberofContentions *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRLocksAndThreadsCollector ...
|
||||
func NewNETFramework_NETCLRLocksAndThreadsCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrlocksandthreads"
|
||||
return &NETFramework_NETCLRLocksAndThreadsCollector{
|
||||
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.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberofcurrentlogicalThreads: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "current_logical_threads"),
|
||||
"Displays the number of current managed thread objects in the application. This counter maintains the count of both running and stopped threads. ",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberofcurrentphysicalThreads: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "physical_threads_current"),
|
||||
"Displays the number of native operating system threads created and owned by the common language runtime to act as underlying threads for managed thread objects. This counter's value does not include the threads used by the runtime in its internal operations; it is a subset of the threads in the operating system process.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
Numberofcurrentrecognizedthreads: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "recognized_threads_current"),
|
||||
"Displays the number of threads that are currently recognized by the runtime. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
Numberoftotalrecognizedthreads: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "recognized_threads_total"),
|
||||
"Displays the total number of threads that have been recognized by the runtime since the application started. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
QueueLengthPeak: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "queue_length_total"),
|
||||
"Displays the total number of threads that waited to acquire a managed lock since the application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalNumberofContentions: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "contentions_total"),
|
||||
"Displays the total number of times that threads in the runtime have attempted to acquire a managed lock unsuccessfully.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
|
||||
Name string
|
||||
|
||||
ContentionRatePersec uint32
|
||||
CurrentQueueLength uint32
|
||||
NumberofcurrentlogicalThreads uint32
|
||||
NumberofcurrentphysicalThreads uint32
|
||||
Numberofcurrentrecognizedthreads uint32
|
||||
Numberoftotalrecognizedthreads uint32
|
||||
QueueLengthPeak uint32
|
||||
QueueLengthPersec uint32
|
||||
RateOfRecognizedThreadsPersec uint32
|
||||
TotalNumberofContentions uint32
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRLocksAndThreadsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentQueueLength,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.CurrentQueueLength),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofcurrentlogicalThreads,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.NumberofcurrentlogicalThreads),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofcurrentphysicalThreads,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.NumberofcurrentphysicalThreads),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Numberofcurrentrecognizedthreads,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Numberofcurrentrecognizedthreads),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Numberoftotalrecognizedthreads,
|
||||
prometheus.CounterValue,
|
||||
float64(process.Numberoftotalrecognizedthreads),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.QueueLengthPeak,
|
||||
prometheus.CounterValue,
|
||||
float64(process.QueueLengthPeak),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalNumberofContentions,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalNumberofContentions),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRLocksAndThreadsCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRLocksAndThreadsCollector)
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
AllocatedBytes *prometheus.Desc
|
||||
FinalizationSurvivors *prometheus.Desc
|
||||
HeapSize *prometheus.Desc
|
||||
PromotedBytes *prometheus.Desc
|
||||
NumberGCHandles *prometheus.Desc
|
||||
NumberCollections *prometheus.Desc
|
||||
NumberInducedGC *prometheus.Desc
|
||||
NumberofPinnedObjects *prometheus.Desc
|
||||
NumberofSinkBlocksinuse *prometheus.Desc
|
||||
NumberTotalCommittedBytes *prometheus.Desc
|
||||
NumberTotalreservedBytes *prometheus.Desc
|
||||
TimeinGC *prometheus.Desc
|
||||
PromotedFinalizationMemoryfromGen0 *prometheus.Desc
|
||||
PromotedMemoryfromGen0 *prometheus.Desc
|
||||
PromotedMemoryfromGen1 *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRMemoryCollector ...
|
||||
func NewNETFramework_NETCLRMemoryCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrmemory"
|
||||
return &NETFramework_NETCLRMemoryCollector{
|
||||
AllocatedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "allocated_bytes_total"),
|
||||
"Displays the total number of bytes allocated on the garbage collection heap.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
FinalizationSurvivors: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "finalization_survivors"),
|
||||
"Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
HeapSize: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "heap_size_bytes"),
|
||||
"Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated.",
|
||||
[]string{"process", "area"},
|
||||
nil,
|
||||
),
|
||||
PromotedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "promoted_bytes"),
|
||||
"Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection.",
|
||||
[]string{"process", "area"},
|
||||
nil,
|
||||
),
|
||||
NumberGCHandles: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "number_gc_handles"),
|
||||
"Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberCollections: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "collections_total"),
|
||||
"Displays the number of times the generation objects are garbage collected since the application started.",
|
||||
[]string{"process", "area"},
|
||||
nil,
|
||||
),
|
||||
NumberInducedGC: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "induced_gc_total"),
|
||||
"Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberofPinnedObjects: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "number_pinned_objects"),
|
||||
"Displays the number of pinned objects encountered in the last garbage collection.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberofSinkBlocksinuse: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "number_sink_blocksinuse"),
|
||||
"Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberTotalCommittedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "committed_bytes"),
|
||||
"Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
NumberTotalreservedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "reserved_bytes"),
|
||||
"Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TimeinGC: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gc_time_percent"),
|
||||
"Displays the percentage of time that was spent performing a garbage collection in the last sample.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
ProcessID uint64
|
||||
PromotedFinalizationMemoryfromGen0 uint64
|
||||
PromotedMemoryfromGen0 uint64
|
||||
PromotedMemoryfromGen1 uint64
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRMemoryCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AllocatedBytes,
|
||||
prometheus.CounterValue,
|
||||
float64(process.AllocatedBytesPersec),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FinalizationSurvivors,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.FinalizationSurvivors),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HeapSize,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Gen0heapsize),
|
||||
process.Name,
|
||||
"Gen0",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PromotedBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Gen0PromotedBytesPerSec),
|
||||
process.Name,
|
||||
"Gen0",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HeapSize,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Gen1heapsize),
|
||||
process.Name,
|
||||
"Gen1",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PromotedBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Gen1PromotedBytesPerSec),
|
||||
process.Name,
|
||||
"Gen1",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HeapSize,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Gen2heapsize),
|
||||
process.Name,
|
||||
"Gen2",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HeapSize,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.LargeObjectHeapsize),
|
||||
process.Name,
|
||||
"LOH",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberGCHandles,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.NumberGCHandles),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberCollections,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberGen0Collections),
|
||||
process.Name,
|
||||
"Gen0",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberCollections,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberGen1Collections),
|
||||
process.Name,
|
||||
"Gen1",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberCollections,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberGen2Collections),
|
||||
process.Name,
|
||||
"Gen2",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberInducedGC,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberInducedGC),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofPinnedObjects,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.NumberofPinnedObjects),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberofSinkBlocksinuse,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.NumberofSinkBlocksinuse),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberTotalCommittedBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.NumberTotalcommittedBytes),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberTotalreservedBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.NumberTotalreservedBytes),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TimeinGC,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.PercentTimeinGC)/float64(process.Frequency_PerfTime),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRMemoryCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRMemoryCollector)
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
Channels *prometheus.Desc
|
||||
ContextBoundClassesLoaded *prometheus.Desc
|
||||
ContextBoundObjects *prometheus.Desc
|
||||
ContextProxies *prometheus.Desc
|
||||
Contexts *prometheus.Desc
|
||||
TotalRemoteCalls *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRRemotingCollector ...
|
||||
func NewNETFramework_NETCLRRemotingCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrremoting"
|
||||
return &NETFramework_NETCLRRemotingCollector{
|
||||
Channels: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "channels_total"),
|
||||
"Displays the total number of remoting channels registered across all application domains since application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
ContextBoundClassesLoaded: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "context_bound_classes_loaded"),
|
||||
"Displays the current number of context-bound classes that are loaded.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
ContextBoundObjects: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "context_bound_objects_total"),
|
||||
"Displays the total number of context-bound objects allocated.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
ContextProxies: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "context_proxies_total"),
|
||||
"Displays the total number of remoting proxy objects in this process since it started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
Contexts: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "contexts"),
|
||||
"Displays the current number of remoting contexts in the application.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalRemoteCalls: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "remote_calls_total"),
|
||||
"Displays the total number of remote procedure calls invoked since the application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
|
||||
Name string
|
||||
|
||||
Channels uint32
|
||||
ContextBoundClassesLoaded uint32
|
||||
ContextBoundObjectsAllocPersec uint32
|
||||
ContextProxies uint32
|
||||
Contexts uint32
|
||||
RemoteCallsPersec uint32
|
||||
TotalRemoteCalls uint32
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRRemotingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Channels,
|
||||
prometheus.CounterValue,
|
||||
float64(process.Channels),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ContextBoundClassesLoaded,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.ContextBoundClassesLoaded),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ContextBoundObjects,
|
||||
prometheus.CounterValue,
|
||||
float64(process.ContextBoundObjectsAllocPersec),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ContextProxies,
|
||||
prometheus.CounterValue,
|
||||
float64(process.ContextProxies),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Contexts,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.Contexts),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalRemoteCalls,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalRemoteCalls),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRRemotingCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRRemotingCollector)
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
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 {
|
||||
NumberLinkTimeChecks *prometheus.Desc
|
||||
TimeinRTchecks *prometheus.Desc
|
||||
StackWalkDepth *prometheus.Desc
|
||||
TotalRuntimeChecks *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewNETFramework_NETCLRSecurityCollector ...
|
||||
func NewNETFramework_NETCLRSecurityCollector() (Collector, error) {
|
||||
const subsystem = "netframework_clrsecurity"
|
||||
return &NETFramework_NETCLRSecurityCollector{
|
||||
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.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TimeinRTchecks: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "rt_checks_time_percent"),
|
||||
"Displays the percentage of time spent performing runtime code access security checks in the last sample.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
StackWalkDepth: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "stack_walk_depth"),
|
||||
"Displays the depth of the stack during that last runtime code access security check.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
TotalRuntimeChecks: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "runtime_checks_total"),
|
||||
"Displays the total number of runtime code access security checks performed since the application started.",
|
||||
[]string{"process"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
|
||||
Name string
|
||||
|
||||
Frequency_PerfTime uint32
|
||||
NumberLinkTimeChecks uint32
|
||||
PercentTimeinRTchecks uint32
|
||||
PercentTimeSigAuthenticating uint64
|
||||
StackWalkDepth uint32
|
||||
TotalRuntimeChecks uint32
|
||||
}
|
||||
|
||||
func (c *NETFramework_NETCLRSecurityCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Global_" {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NumberLinkTimeChecks,
|
||||
prometheus.CounterValue,
|
||||
float64(process.NumberLinkTimeChecks),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TimeinRTchecks,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.PercentTimeinRTchecks)/float64(process.Frequency_PerfTime),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StackWalkDepth,
|
||||
prometheus.GaugeValue,
|
||||
float64(process.StackWalkDepth),
|
||||
process.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalRuntimeChecks,
|
||||
prometheus.CounterValue,
|
||||
float64(process.TotalRuntimeChecks),
|
||||
process.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkNETFrameworkNETCLRSecurityCollector(b *testing.B) {
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", NewNETFramework_NETCLRSecurityCollector)
|
||||
}
|
||||
322
collector/os.go
322
collector/os.go
@@ -1,322 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("os", NewOSCollector, "Paging File")
|
||||
}
|
||||
|
||||
// A OSCollector is a Prometheus collector for WMI metrics
|
||||
type OSCollector struct {
|
||||
OSInformation *prometheus.Desc
|
||||
PhysicalMemoryFreeBytes *prometheus.Desc
|
||||
PagingFreeBytes *prometheus.Desc
|
||||
VirtualMemoryFreeBytes *prometheus.Desc
|
||||
ProcessesLimit *prometheus.Desc
|
||||
ProcessMemoryLimitBytes *prometheus.Desc
|
||||
Processes *prometheus.Desc
|
||||
Users *prometheus.Desc
|
||||
PagingLimitBytes *prometheus.Desc
|
||||
VirtualMemoryBytes *prometheus.Desc
|
||||
VisibleMemoryBytes *prometheus.Desc
|
||||
Time *prometheus.Desc
|
||||
Timezone *prometheus.Desc
|
||||
}
|
||||
|
||||
type pagingFileCounter struct {
|
||||
Name string
|
||||
Usage float64 `perflib:"% Usage"`
|
||||
UsagePeak float64 `perflib:"% Usage Peak"`
|
||||
}
|
||||
|
||||
// NewOSCollector ...
|
||||
func NewOSCollector() (Collector, error) {
|
||||
const subsystem = "os"
|
||||
|
||||
return &OSCollector{
|
||||
OSInformation: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "info"),
|
||||
"OperatingSystem.Caption, OperatingSystem.Version",
|
||||
[]string{"product", "version"},
|
||||
nil,
|
||||
),
|
||||
PagingLimitBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "paging_limit_bytes"),
|
||||
"OperatingSystem.SizeStoredInPagingFiles",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PagingFreeBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "paging_free_bytes"),
|
||||
"OperatingSystem.FreeSpaceInPagingFiles",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
PhysicalMemoryFreeBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "physical_memory_free_bytes"),
|
||||
"OperatingSystem.FreePhysicalMemory",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
Time: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "time"),
|
||||
"OperatingSystem.LocalDateTime",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
Timezone: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "timezone"),
|
||||
"OperatingSystem.LocalDateTime",
|
||||
[]string{"timezone"},
|
||||
nil,
|
||||
),
|
||||
Processes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processes"),
|
||||
"OperatingSystem.NumberOfProcesses",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ProcessesLimit: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processes_limit"),
|
||||
"OperatingSystem.MaxNumberOfProcesses",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ProcessMemoryLimitBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "process_memory_limit_bytes"),
|
||||
"OperatingSystem.MaxProcessMemorySize",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
Users: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "users"),
|
||||
"OperatingSystem.NumberOfUsers",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
VirtualMemoryBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_bytes"),
|
||||
"OperatingSystem.TotalVirtualMemorySize",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
VisibleMemoryBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "visible_memory_bytes"),
|
||||
"OperatingSystem.TotalVisibleMemorySize",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
VirtualMemoryFreeBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_free_bytes"),
|
||||
"OperatingSystem.FreeVirtualMemory",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 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(ctx, ch); err != nil {
|
||||
log.Error("failed collecting os metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_OperatingSystem docs:
|
||||
// - https://msdn.microsoft.com/en-us/library/aa394239 - Win32_OperatingSystem class
|
||||
type Win32_OperatingSystem struct {
|
||||
Caption string
|
||||
FreePhysicalMemory uint64
|
||||
FreeSpaceInPagingFiles uint64
|
||||
FreeVirtualMemory uint64
|
||||
LocalDateTime time.Time
|
||||
MaxNumberOfProcesses uint32
|
||||
MaxProcessMemorySize uint64
|
||||
NumberOfProcesses uint32
|
||||
NumberOfUsers uint32
|
||||
SizeStoredInPagingFiles uint64
|
||||
TotalVirtualMemorySize uint64
|
||||
TotalVisibleMemorySize uint64
|
||||
Version string
|
||||
}
|
||||
|
||||
func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
nwgi, err := netapi32.GetWorkstationInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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, _, err := memManKey.GetStringsValue("ExistingPageFiles")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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); 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,
|
||||
fmt.Sprintf("Microsoft %s", pn), // Caption
|
||||
fmt.Sprintf("%d.%d.%s", nwgi.VersionMajor, nwgi.VersionMinor, bn), // Version
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PhysicalMemoryFreeBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(gmse.AvailPhys),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Time,
|
||||
prometheus.GaugeValue,
|
||||
float64(currentTime.Unix()),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Timezone,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
timezoneName,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PagingFreeBytes,
|
||||
prometheus.GaugeValue,
|
||||
pfb,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualMemoryFreeBytes,
|
||||
prometheus.GaugeValue,
|
||||
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(4294967295),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessMemoryLimitBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(gmse.TotalVirtual),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Processes,
|
||||
prometheus.GaugeValue,
|
||||
float64(gpi.ProcessCount),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Users,
|
||||
prometheus.GaugeValue,
|
||||
float64(nwgi.LoggedOnUsers),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PagingLimitBytes,
|
||||
prometheus.GaugeValue,
|
||||
fsipf,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualMemoryBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(gmse.TotalPageFile),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VisibleMemoryBytes,
|
||||
prometheus.GaugeValue,
|
||||
float64(gmse.TotalPhys),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkOSCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "os", NewOSCollector)
|
||||
}
|
||||
@@ -1,427 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("process", newProcessCollector, "Process")
|
||||
}
|
||||
|
||||
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()
|
||||
)
|
||||
|
||||
type processCollector struct {
|
||||
StartTime *prometheus.Desc
|
||||
CPUTimeTotal *prometheus.Desc
|
||||
HandleCount *prometheus.Desc
|
||||
IOBytesTotal *prometheus.Desc
|
||||
IOOperationsTotal *prometheus.Desc
|
||||
PageFaultsTotal *prometheus.Desc
|
||||
PageFileBytes *prometheus.Desc
|
||||
PoolBytes *prometheus.Desc
|
||||
PriorityBase *prometheus.Desc
|
||||
PrivateBytes *prometheus.Desc
|
||||
ThreadCount *prometheus.Desc
|
||||
VirtualBytes *prometheus.Desc
|
||||
WorkingSetPrivate *prometheus.Desc
|
||||
WorkingSetPeak *prometheus.Desc
|
||||
WorkingSet *prometheus.Desc
|
||||
|
||||
processWhitelistPattern *regexp.Regexp
|
||||
processBlacklistPattern *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewProcessCollector ...
|
||||
func newProcessCollector() (Collector, error) {
|
||||
const subsystem = "process"
|
||||
|
||||
if *processWhitelist == ".*" && *processBlacklist == "" {
|
||||
log.Warn("No filters specified for process collector. This will generate a very large number of metrics!")
|
||||
}
|
||||
|
||||
return &processCollector{
|
||||
StartTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "start_time"),
|
||||
"Time of process start.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
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).",
|
||||
[]string{"process", "process_id", "creating_process_id", "mode"},
|
||||
nil,
|
||||
),
|
||||
HandleCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "handle_count"),
|
||||
"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).",
|
||||
[]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).",
|
||||
[]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.",
|
||||
[]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).",
|
||||
[]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.",
|
||||
[]string{"process", "process_id", "creating_process_id", "pool"},
|
||||
nil,
|
||||
),
|
||||
PriorityBase: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "priority_base"),
|
||||
"Current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process base priority of the process.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
PrivateBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "private_bytes"),
|
||||
"Current number of bytes this process has allocated that cannot be shared with other processes.",
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
ThreadCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "thread_count"),
|
||||
"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.",
|
||||
[]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_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)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type perflibProcess struct {
|
||||
Name string
|
||||
PercentProcessorTime float64 `perflib:"% Processor Time"`
|
||||
PercentPrivilegedTime float64 `perflib:"% Privileged Time"`
|
||||
PercentUserTime float64 `perflib:"% User Time"`
|
||||
CreatingProcessID float64 `perflib:"Creating Process ID"`
|
||||
ElapsedTime float64 `perflib:"Elapsed Time"`
|
||||
HandleCount float64 `perflib:"Handle Count"`
|
||||
IDProcess float64 `perflib:"ID Process"`
|
||||
IODataBytesPerSec float64 `perflib:"IO Data Bytes/sec"`
|
||||
IODataOperationsPerSec float64 `perflib:"IO Data Operations/sec"`
|
||||
IOOtherBytesPerSec float64 `perflib:"IO Other Bytes/sec"`
|
||||
IOOtherOperationsPerSec float64 `perflib:"IO Other Operations/sec"`
|
||||
IOReadBytesPerSec float64 `perflib:"IO Read Bytes/sec"`
|
||||
IOReadOperationsPerSec float64 `perflib:"IO Read Operations/sec"`
|
||||
IOWriteBytesPerSec float64 `perflib:"IO Write Bytes/sec"`
|
||||
IOWriteOperationsPerSec float64 `perflib:"IO Write Operations/sec"`
|
||||
PageFaultsPerSec float64 `perflib:"Page Faults/sec"`
|
||||
PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"`
|
||||
PageFileBytes float64 `perflib:"Page File Bytes"`
|
||||
PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
|
||||
PoolPagedBytes float64 `perflib:"Pool Paged Bytes"`
|
||||
PriorityBase float64 `perflib:"Priority Base"`
|
||||
PrivateBytes float64 `perflib:"Private Bytes"`
|
||||
ThreadCount float64 `perflib:"Thread Count"`
|
||||
VirtualBytesPeak float64 `perflib:"Virtual Bytes Peak"`
|
||||
VirtualBytes float64 `perflib:"Virtual Bytes"`
|
||||
WorkingSetPrivate float64 `perflib:"Working Set - Private"`
|
||||
WorkingSetPeak float64 `perflib:"Working Set Peak"`
|
||||
WorkingSet float64 `perflib:"Working Set"`
|
||||
}
|
||||
|
||||
type WorkerProcess struct {
|
||||
AppPoolName string
|
||||
ProcessId uint64
|
||||
}
|
||||
|
||||
func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
data := make([]perflibProcess, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Process"], &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dst_wp []WorkerProcess
|
||||
q_wp := queryAll(&dst_wp)
|
||||
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)
|
||||
}
|
||||
|
||||
for _, process := range data {
|
||||
if process.Name == "_Total" ||
|
||||
c.processBlacklistPattern.MatchString(process.Name) ||
|
||||
!c.processWhitelistPattern.MatchString(process.Name) {
|
||||
continue
|
||||
}
|
||||
// Duplicate processes are suffixed # and an index number. Remove those.
|
||||
processName := strings.Split(process.Name, "#")[0]
|
||||
pid := strconv.FormatUint(uint64(process.IDProcess), 10)
|
||||
cpid := strconv.FormatUint(uint64(process.CreatingProcessID), 10)
|
||||
|
||||
for _, wp := range dst_wp {
|
||||
if wp.ProcessId == uint64(process.IDProcess) {
|
||||
processName = strings.Join([]string{processName, wp.AppPoolName}, "_")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StartTime,
|
||||
prometheus.GaugeValue,
|
||||
process.ElapsedTime,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HandleCount,
|
||||
prometheus.GaugeValue,
|
||||
process.HandleCount,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CPUTimeTotal,
|
||||
prometheus.CounterValue,
|
||||
process.PercentPrivilegedTime,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"privileged",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CPUTimeTotal,
|
||||
prometheus.CounterValue,
|
||||
process.PercentUserTime,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"user",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOOtherBytesPerSec,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"other",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOOperationsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOOtherOperationsPerSec,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"other",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOReadBytesPerSec,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"read",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOOperationsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOReadOperationsPerSec,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"read",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOWriteBytesPerSec,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"write",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOOperationsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOWriteOperationsPerSec,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"write",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFaultsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.PageFaultsPerSec,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFileBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PageFileBytes,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PoolNonpagedBytes,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"nonpaged",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PoolPagedBytes,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
"paged",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PriorityBase,
|
||||
prometheus.GaugeValue,
|
||||
process.PriorityBase,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PrivateBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PrivateBytes,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ThreadCount,
|
||||
prometheus.GaugeValue,
|
||||
process.ThreadCount,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.VirtualBytes,
|
||||
processName,
|
||||
pid,
|
||||
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,
|
||||
process.WorkingSet,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkProcessCollector(b *testing.B) {
|
||||
// Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all processes.
|
||||
localProcessWhitelist := ".+"
|
||||
processWhitelist = &localProcessWhitelist
|
||||
|
||||
// No context name required as collector source is WMI
|
||||
benchmarkCollector(b, "", newProcessCollector)
|
||||
}
|
||||
@@ -1,352 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"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 {
|
||||
// net
|
||||
BaseTCPRTT *prometheus.Desc
|
||||
BaseUDPRTT *prometheus.Desc
|
||||
CurrentTCPBandwidth *prometheus.Desc
|
||||
CurrentTCPRTT *prometheus.Desc
|
||||
CurrentUDPBandwidth *prometheus.Desc
|
||||
CurrentUDPRTT *prometheus.Desc
|
||||
TotalReceivedBytes *prometheus.Desc
|
||||
TotalSentBytes *prometheus.Desc
|
||||
UDPPacketsReceivedPersec *prometheus.Desc
|
||||
UDPPacketsSentPersec *prometheus.Desc
|
||||
|
||||
//gfx
|
||||
AverageEncodingTime *prometheus.Desc
|
||||
FrameQuality *prometheus.Desc
|
||||
FramesSkippedPerSecondInsufficientResources *prometheus.Desc
|
||||
GraphicsCompressionratio *prometheus.Desc
|
||||
InputFramesPerSecond *prometheus.Desc
|
||||
OutputFramesPerSecond *prometheus.Desc
|
||||
SourceFramesPerSecond *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewRemoteFx ...
|
||||
func NewRemoteFx() (Collector, error) {
|
||||
const subsystem = "remote_fx"
|
||||
return &RemoteFxCollector{
|
||||
// net
|
||||
BaseTCPRTT: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_base_tcp_rtt_seconds"),
|
||||
"Base TCP round-trip time (RTT) detected in seconds",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
BaseUDPRTT: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_base_udp_rtt_seconds"),
|
||||
"Base UDP round-trip time (RTT) detected in seconds.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
CurrentTCPBandwidth: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_bandwidth"),
|
||||
"TCP Bandwidth detected in bytes per second.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
CurrentTCPRTT: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_rtt_seconds"),
|
||||
"Average TCP round-trip time (RTT) detected in seconds.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
CurrentUDPBandwidth: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_current_udp_bandwidth"),
|
||||
"UDP Bandwidth detected in bytes per second.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
CurrentUDPRTT: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_current_udp_rtt_seconds"),
|
||||
"Average UDP round-trip time (RTT) detected in seconds.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
TotalReceivedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_received_bytes_total"),
|
||||
"(TotalReceivedBytes)",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
TotalSentBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_sent_bytes_total"),
|
||||
"(TotalSentBytes)",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
UDPPacketsReceivedPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_udp_packets_received_total"),
|
||||
"Rate in packets per second at which packets are received over UDP.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
UDPPacketsSentPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "net_udp_packets_sent_total"),
|
||||
"Rate in packets per second at which packets are sent over UDP.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
|
||||
//gfx
|
||||
AverageEncodingTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gfx_average_encoding_time_seconds"),
|
||||
"Average frame encoding time in seconds",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
FrameQuality: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gfx_frame_quality"),
|
||||
"Quality of the output frame expressed as a percentage of the quality of the source frame.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
FramesSkippedPerSecondInsufficientResources: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gfx_frames_skipped_insufficient_resource_total"),
|
||||
"Number of frames skipped per second due to insufficient client resources.",
|
||||
[]string{"session_name", "resource"},
|
||||
nil,
|
||||
),
|
||||
GraphicsCompressionratio: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gfx_graphics_compression_ratio"),
|
||||
"Ratio of the number of bytes encoded to the number of bytes input.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
InputFramesPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gfx_input_frames_total"),
|
||||
"Number of sources frames provided as input to RemoteFX graphics per second.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
OutputFramesPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gfx_output_frames_total"),
|
||||
"Number of frames sent to the client per second.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
SourceFramesPerSecond: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "gfx_source_frames_total"),
|
||||
"Number of frames composed by the source (DWM) per second.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectRemoteFXGraphicsCounters(ctx, ch); err != nil {
|
||||
log.Error("failed collecting terminal services session count metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type perflibRemoteFxNetwork struct {
|
||||
Name string
|
||||
BaseTCPRTT float64 `perflib:"Base TCP RTT"`
|
||||
BaseUDPRTT float64 `perflib:"Base UDP RTT"`
|
||||
CurrentTCPBandwidth float64 `perflib:"Current TCP Bandwidth"`
|
||||
CurrentTCPRTT float64 `perflib:"Current TCP RTT"`
|
||||
CurrentUDPBandwidth float64 `perflib:"Current UDP Bandwidth"`
|
||||
CurrentUDPRTT float64 `perflib:"Current UDP RTT"`
|
||||
TotalReceivedBytes float64 `perflib:"Total Received Bytes"`
|
||||
TotalSentBytes float64 `perflib:"Total Sent Bytes"`
|
||||
UDPPacketsReceivedPersec float64 `perflib:"UDP Packets Received/sec"`
|
||||
UDPPacketsSentPersec float64 `perflib:"UDP Packets Sent/sec"`
|
||||
}
|
||||
|
||||
func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
dst := make([]perflibRemoteFxNetwork, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["RemoteFX Network"], &dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, d := range dst {
|
||||
// only connect metrics for remote named sessions
|
||||
n := strings.ToLower(d.Name)
|
||||
if n == "" || n == "services" || n == "console" {
|
||||
continue
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BaseTCPRTT,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.BaseTCPRTT),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.BaseUDPRTT,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.BaseUDPRTT),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentTCPBandwidth,
|
||||
prometheus.GaugeValue,
|
||||
(d.CurrentTCPBandwidth*1000)/8,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentTCPRTT,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.CurrentTCPRTT),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentUDPBandwidth,
|
||||
prometheus.GaugeValue,
|
||||
(d.CurrentUDPBandwidth*1000)/8,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CurrentUDPRTT,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.CurrentUDPRTT),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalReceivedBytes,
|
||||
prometheus.CounterValue,
|
||||
d.TotalReceivedBytes,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TotalSentBytes,
|
||||
prometheus.CounterValue,
|
||||
d.TotalSentBytes,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.UDPPacketsReceivedPersec,
|
||||
prometheus.CounterValue,
|
||||
d.UDPPacketsReceivedPersec,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.UDPPacketsSentPersec,
|
||||
prometheus.CounterValue,
|
||||
d.UDPPacketsSentPersec,
|
||||
d.Name,
|
||||
)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type perflibRemoteFxGraphics struct {
|
||||
Name string
|
||||
AverageEncodingTime float64 `perflib:"Average Encoding Time"`
|
||||
FrameQuality float64 `perflib:"Frame Quality"`
|
||||
FramesSkippedPerSecondInsufficientClientResources float64 `perflib:"Frames Skipped/Second - Insufficient Server Resources"`
|
||||
FramesSkippedPerSecondInsufficientNetworkResources float64 `perflib:"Frames Skipped/Second - Insufficient Network Resources"`
|
||||
FramesSkippedPerSecondInsufficientServerResources float64 `perflib:"Frames Skipped/Second - Insufficient Client Resources"`
|
||||
GraphicsCompressionratio float64 `perflib:"Graphics Compression ratio"`
|
||||
InputFramesPerSecond float64 `perflib:"Input Frames/Second"`
|
||||
OutputFramesPerSecond float64 `perflib:"Output Frames/Second"`
|
||||
SourceFramesPerSecond float64 `perflib:"Source Frames/Second"`
|
||||
}
|
||||
|
||||
func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
dst := make([]perflibRemoteFxGraphics, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["RemoteFX Graphics"], &dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, d := range dst {
|
||||
// only connect metrics for remote named sessions
|
||||
n := strings.ToLower(d.Name)
|
||||
if n == "" || n == "services" || n == "console" {
|
||||
continue
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.AverageEncodingTime,
|
||||
prometheus.GaugeValue,
|
||||
milliSecToSec(d.AverageEncodingTime),
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FrameQuality,
|
||||
prometheus.GaugeValue,
|
||||
d.FrameQuality,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FramesSkippedPerSecondInsufficientResources,
|
||||
prometheus.CounterValue,
|
||||
d.FramesSkippedPerSecondInsufficientClientResources,
|
||||
d.Name,
|
||||
"client",
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FramesSkippedPerSecondInsufficientResources,
|
||||
prometheus.CounterValue,
|
||||
d.FramesSkippedPerSecondInsufficientNetworkResources,
|
||||
d.Name,
|
||||
"network",
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.FramesSkippedPerSecondInsufficientResources,
|
||||
prometheus.CounterValue,
|
||||
d.FramesSkippedPerSecondInsufficientServerResources,
|
||||
d.Name,
|
||||
"server",
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.GraphicsCompressionratio,
|
||||
prometheus.GaugeValue,
|
||||
d.GraphicsCompressionratio,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.InputFramesPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.InputFramesPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.OutputFramesPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.OutputFramesPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SourceFramesPerSecond,
|
||||
prometheus.CounterValue,
|
||||
d.SourceFramesPerSecond,
|
||||
d.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func milliSecToSec(t float64) float64 {
|
||||
return t / 1000
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkRemoteFXCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "remote_fx", NewRemoteFx)
|
||||
}
|
||||
@@ -1,305 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("service", NewserviceCollector)
|
||||
}
|
||||
|
||||
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()
|
||||
useAPI = kingpin.Flag(
|
||||
"collector.service.use-api",
|
||||
"Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.",
|
||||
).Default("false").Bool()
|
||||
)
|
||||
|
||||
// A serviceCollector is a Prometheus collector for WMI Win32_Service metrics
|
||||
type serviceCollector struct {
|
||||
Information *prometheus.Desc
|
||||
State *prometheus.Desc
|
||||
StartMode *prometheus.Desc
|
||||
Status *prometheus.Desc
|
||||
|
||||
queryWhereClause string
|
||||
}
|
||||
|
||||
// NewserviceCollector ...
|
||||
func NewserviceCollector() (Collector, error) {
|
||||
const subsystem = "service"
|
||||
|
||||
if *serviceWhereClause == "" {
|
||||
log.Warn("No where-clause specified for service collector. This will generate a very large number of metrics!")
|
||||
}
|
||||
if *useAPI {
|
||||
log.Warn("API collection is enabled.")
|
||||
}
|
||||
|
||||
return &serviceCollector{
|
||||
Information: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "info"),
|
||||
"A metric with a constant '1' value labeled with service information",
|
||||
[]string{"name", "display_name", "process_id", "run_as"},
|
||||
nil,
|
||||
),
|
||||
State: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "state"),
|
||||
"The state of the service (State)",
|
||||
[]string{"name", "state"},
|
||||
nil,
|
||||
),
|
||||
StartMode: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "start_mode"),
|
||||
"The start mode of the service (StartMode)",
|
||||
[]string{"name", "start_mode"},
|
||||
nil,
|
||||
),
|
||||
Status: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "status"),
|
||||
"The status of the service (Status)",
|
||||
[]string{"name", "status"},
|
||||
nil,
|
||||
),
|
||||
queryWhereClause: *serviceWhereClause,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 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 *useAPI {
|
||||
if err := c.collectAPI(ch); err != nil {
|
||||
log.Error("failed collecting API service metrics:", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := c.collectWMI(ch); err != nil {
|
||||
log.Error("failed collecting WMI service metrics:", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_Service docs:
|
||||
// - https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx
|
||||
type Win32_Service struct {
|
||||
DisplayName string
|
||||
Name string
|
||||
ProcessId uint32
|
||||
State string
|
||||
Status string
|
||||
StartMode string
|
||||
StartName *string
|
||||
}
|
||||
|
||||
var (
|
||||
allStates = []string{
|
||||
"stopped",
|
||||
"start pending",
|
||||
"stop pending",
|
||||
"running",
|
||||
"continue pending",
|
||||
"pause pending",
|
||||
"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",
|
||||
"auto",
|
||||
"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",
|
||||
"degraded",
|
||||
"unknown",
|
||||
"pred fail",
|
||||
"starting",
|
||||
"stopping",
|
||||
"service",
|
||||
"stressed",
|
||||
"nonrecover",
|
||||
"no contact",
|
||||
"lost comm",
|
||||
}
|
||||
)
|
||||
|
||||
func (c *serviceCollector) collectWMI(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_Service
|
||||
q := queryAllWhere(&dst, c.queryWhereClause)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, service := range dst {
|
||||
pid := fmt.Sprintf("%d", uint64(service.ProcessId))
|
||||
|
||||
runAs := ""
|
||||
if service.StartName != nil {
|
||||
runAs = *service.StartName
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Information,
|
||||
prometheus.GaugeValue,
|
||||
1.0,
|
||||
strings.ToLower(service.Name),
|
||||
service.DisplayName,
|
||||
pid,
|
||||
runAs,
|
||||
)
|
||||
|
||||
for _, state := range allStates {
|
||||
isCurrentState := 0.0
|
||||
if state == strings.ToLower(service.State) {
|
||||
isCurrentState = 1.0
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.State,
|
||||
prometheus.GaugeValue,
|
||||
isCurrentState,
|
||||
strings.ToLower(service.Name),
|
||||
state,
|
||||
)
|
||||
}
|
||||
|
||||
for _, startMode := range allStartModes {
|
||||
isCurrentStartMode := 0.0
|
||||
if startMode == strings.ToLower(service.StartMode) {
|
||||
isCurrentStartMode = 1.0
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StartMode,
|
||||
prometheus.GaugeValue,
|
||||
isCurrentStartMode,
|
||||
strings.ToLower(service.Name),
|
||||
startMode,
|
||||
)
|
||||
}
|
||||
|
||||
for _, status := range allStatuses {
|
||||
isCurrentStatus := 0.0
|
||||
if status == strings.ToLower(service.Status) {
|
||||
isCurrentStatus = 1.0
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Status,
|
||||
prometheus.GaugeValue,
|
||||
isCurrentStatus,
|
||||
strings.ToLower(service.Name),
|
||||
status,
|
||||
)
|
||||
}
|
||||
}
|
||||
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 {
|
||||
// Retrieve handle for each service
|
||||
serviceHandle, err := svcmgrConnection.OpenService(service)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
defer serviceHandle.Close()
|
||||
|
||||
// Get Service Configuration
|
||||
serviceConfig, err := serviceHandle.Config()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get Service Current Status
|
||||
serviceStatus, err := serviceHandle.Query()
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkServiceCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "service", NewserviceCollector)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkSmtpCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "smtp", NewSMTPCollector)
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("system", NewSystemCollector, "System")
|
||||
}
|
||||
|
||||
// A SystemCollector is a Prometheus collector for WMI metrics
|
||||
type SystemCollector struct {
|
||||
ContextSwitchesTotal *prometheus.Desc
|
||||
ExceptionDispatchesTotal *prometheus.Desc
|
||||
ProcessorQueueLength *prometheus.Desc
|
||||
SystemCallsTotal *prometheus.Desc
|
||||
SystemUpTime *prometheus.Desc
|
||||
Threads *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewSystemCollector ...
|
||||
func NewSystemCollector() (Collector, error) {
|
||||
const subsystem = "system"
|
||||
|
||||
return &SystemCollector{
|
||||
ContextSwitchesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"),
|
||||
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ExceptionDispatchesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "exception_dispatches_total"),
|
||||
"Total number of exceptions dispatched (WMI source: PerfOS_System.ExceptionDispatchesPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ProcessorQueueLength: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_queue_length"),
|
||||
"Length of processor queue (WMI source: PerfOS_System.ProcessorQueueLength)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemCallsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_calls_total"),
|
||||
"Total number of system calls (WMI source: PerfOS_System.SystemCallsPersec)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
SystemUpTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "system_up_time"),
|
||||
"System boot time (WMI source: PerfOS_System.SystemUpTime)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
Threads: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "threads"),
|
||||
"Current number of threads (WMI source: PerfOS_System.Threads)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// 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)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_PerfOS_System docs:
|
||||
// - https://web.archive.org/web/20050830140516/http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_perfrawdata_perfos_system.asp
|
||||
type system struct {
|
||||
ContextSwitchesPersec float64 `perflib:"Context Switches/sec"`
|
||||
ExceptionDispatchesPersec float64 `perflib:"Exception Dispatches/sec"`
|
||||
ProcessorQueueLength float64 `perflib:"Processor Queue Length"`
|
||||
SystemCallsPersec float64 `perflib:"System Calls/sec"`
|
||||
SystemUpTime float64 `perflib:"System Up Time"`
|
||||
Threads float64 `perflib:"Threads"`
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ContextSwitchesTotal,
|
||||
prometheus.CounterValue,
|
||||
dst[0].ContextSwitchesPersec,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ExceptionDispatchesTotal,
|
||||
prometheus.CounterValue,
|
||||
dst[0].ExceptionDispatchesPersec,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ProcessorQueueLength,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].ProcessorQueueLength,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SystemCallsTotal,
|
||||
prometheus.CounterValue,
|
||||
dst[0].SystemCallsPersec,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SystemUpTime,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].SystemUpTime,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Threads,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].Threads,
|
||||
)
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkSystemCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "system", NewSystemCollector)
|
||||
}
|
||||
192
collector/tcp.go
192
collector/tcp.go
@@ -1,192 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"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 {
|
||||
ConnectionFailures *prometheus.Desc
|
||||
ConnectionsActive *prometheus.Desc
|
||||
ConnectionsEstablished *prometheus.Desc
|
||||
ConnectionsPassive *prometheus.Desc
|
||||
ConnectionsReset *prometheus.Desc
|
||||
SegmentsTotal *prometheus.Desc
|
||||
SegmentsReceivedTotal *prometheus.Desc
|
||||
SegmentsRetransmittedTotal *prometheus.Desc
|
||||
SegmentsSentTotal *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewTCPCollector ...
|
||||
func NewTCPCollector() (Collector, error) {
|
||||
const subsystem = "tcp"
|
||||
|
||||
return &TCPCollector{
|
||||
ConnectionFailures: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connection_failures"),
|
||||
"(TCP.ConnectionFailures)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
ConnectionsActive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_active"),
|
||||
"(TCP.ConnectionsActive)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
ConnectionsEstablished: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_established"),
|
||||
"(TCP.ConnectionsEstablished)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
ConnectionsPassive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_passive"),
|
||||
"(TCP.ConnectionsPassive)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
ConnectionsReset: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connections_reset"),
|
||||
"(TCP.ConnectionsReset)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
SegmentsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "segments_total"),
|
||||
"(TCP.SegmentsTotal)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
SegmentsReceivedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "segments_received_total"),
|
||||
"(TCP.SegmentsReceivedTotal)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
SegmentsRetransmittedTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "segments_retransmitted_total"),
|
||||
"(TCP.SegmentsRetransmittedTotal)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
SegmentsSentTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "segments_sent_total"),
|
||||
"(TCP.SegmentsSentTotal)",
|
||||
[]string{"af"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting tcp metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_Tcpip_TCPv4 docs
|
||||
// - https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx
|
||||
// The TCPv6 performance object uses the same fields.
|
||||
type tcp struct {
|
||||
ConnectionFailures float64 `perflib:"Connection Failures"`
|
||||
ConnectionsActive float64 `perflib:"Connections Active"`
|
||||
ConnectionsEstablished float64 `perflib:"Connections Established"`
|
||||
ConnectionsPassive float64 `perflib:"Connections Passive"`
|
||||
ConnectionsReset float64 `perflib:"Connections Reset"`
|
||||
SegmentsPersec float64 `perflib:"Segments/sec"`
|
||||
SegmentsReceivedPersec float64 `perflib:"Segments Received/sec"`
|
||||
SegmentsRetransmittedPersec float64 `perflib:"Segments Retransmitted/sec"`
|
||||
SegmentsSentPersec float64 `perflib:"Segments Sent/sec"`
|
||||
}
|
||||
|
||||
func writeTCPCounters(metrics tcp, labels []string, c *TCPCollector, ch chan<- prometheus.Metric) {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionFailures,
|
||||
prometheus.CounterValue,
|
||||
metrics.ConnectionFailures,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionsActive,
|
||||
prometheus.CounterValue,
|
||||
metrics.ConnectionsActive,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionsEstablished,
|
||||
prometheus.GaugeValue,
|
||||
metrics.ConnectionsEstablished,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionsPassive,
|
||||
prometheus.CounterValue,
|
||||
metrics.ConnectionsPassive,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionsReset,
|
||||
prometheus.CounterValue,
|
||||
metrics.ConnectionsReset,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SegmentsTotal,
|
||||
prometheus.CounterValue,
|
||||
metrics.SegmentsPersec,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SegmentsReceivedTotal,
|
||||
prometheus.CounterValue,
|
||||
metrics.SegmentsReceivedPersec,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SegmentsRetransmittedTotal,
|
||||
prometheus.CounterValue,
|
||||
metrics.SegmentsRetransmittedPersec,
|
||||
labels...,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.SegmentsSentTotal,
|
||||
prometheus.CounterValue,
|
||||
metrics.SegmentsSentPersec,
|
||||
labels...,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []tcp
|
||||
|
||||
// TCPv4 counters
|
||||
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) != 0 {
|
||||
writeTCPCounters(dst[0], []string{"ipv4"}, c, ch)
|
||||
}
|
||||
|
||||
// TCPv6 counters
|
||||
if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) != 0 {
|
||||
writeTCPCounters(dst[0], []string{"ipv6"}, c, ch)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkTCPCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "tcp", NewTCPCollector)
|
||||
}
|
||||
@@ -1,404 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const ConnectionBrokerFeatureID uint32 = 133
|
||||
|
||||
func init() {
|
||||
registerCollector("terminal_services", NewTerminalServicesCollector, "Terminal Services", "Terminal Services Session", "Remote Desktop Connection Broker Counterset")
|
||||
}
|
||||
|
||||
var (
|
||||
connectionBrokerEnabled = isConnectionBrokerServer()
|
||||
)
|
||||
|
||||
type Win32_ServerFeature struct {
|
||||
ID uint32
|
||||
}
|
||||
|
||||
func isConnectionBrokerServer() bool {
|
||||
var dst []Win32_ServerFeature
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return false
|
||||
}
|
||||
for _, d := range dst {
|
||||
if d.ID == ConnectionBrokerFeatureID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
log.Debug("host is not a connection broker skipping Connection Broker performance metrics.")
|
||||
return false
|
||||
}
|
||||
|
||||
// A TerminalServicesCollector is a Prometheus collector for WMI
|
||||
// Win32_PerfRawData_LocalSessionManager_TerminalServices & Win32_PerfRawData_TermService_TerminalServicesSession metrics
|
||||
// https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85)
|
||||
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/
|
||||
type TerminalServicesCollector struct {
|
||||
LocalSessionCount *prometheus.Desc
|
||||
ConnectionBrokerPerformance *prometheus.Desc
|
||||
HandleCount *prometheus.Desc
|
||||
PageFaultsPersec *prometheus.Desc
|
||||
PageFileBytes *prometheus.Desc
|
||||
PageFileBytesPeak *prometheus.Desc
|
||||
PercentPrivilegedTime *prometheus.Desc
|
||||
PercentProcessorTime *prometheus.Desc
|
||||
PercentUserTime *prometheus.Desc
|
||||
PoolNonpagedBytes *prometheus.Desc
|
||||
PoolPagedBytes *prometheus.Desc
|
||||
PrivateBytes *prometheus.Desc
|
||||
ThreadCount *prometheus.Desc
|
||||
VirtualBytes *prometheus.Desc
|
||||
VirtualBytesPeak *prometheus.Desc
|
||||
WorkingSet *prometheus.Desc
|
||||
WorkingSetPeak *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewTerminalServicesCollector ...
|
||||
func NewTerminalServicesCollector() (Collector, error) {
|
||||
const subsystem = "terminal_services"
|
||||
return &TerminalServicesCollector{
|
||||
LocalSessionCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "local_session_count"),
|
||||
"Number of Terminal Services sessions",
|
||||
[]string{"session"},
|
||||
nil,
|
||||
),
|
||||
ConnectionBrokerPerformance: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "connection_broker_performance_total"),
|
||||
"The total number of connections handled by the Connection Brokers since the service started.",
|
||||
[]string{"connection"},
|
||||
nil,
|
||||
),
|
||||
HandleCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "handle_count"),
|
||||
"Total number of handles currently opened by this process. This number is the sum of the handles currently opened by each thread in this process.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PageFaultsPersec: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "page_fault_total"),
|
||||
"Rate at which page faults occur in 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. The page may not be retrieved from disk if it is on the standby list and therefore already in main memory. The page also may not be retrieved if it is in use by another process which shares the page.",
|
||||
[]string{"session_name"},
|
||||
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.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PageFileBytesPeak: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes_peak"),
|
||||
"Maximum 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.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PercentPrivilegedTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "privileged_time_seconds_total"),
|
||||
"Total elapsed time that the threads of the process have spent executing code in privileged mode.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PercentProcessorTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "processor_time_seconds_total"),
|
||||
"Total elapsed time that all of the threads of this process used the processor to execute instructions.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PercentUserTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "user_time_seconds_total"),
|
||||
"Total elapsed time that this process's threads have spent executing code in user mode. Applications, environment subsystems, and integral subsystems execute in user mode.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PoolNonpagedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_non_paged_bytes"),
|
||||
"Number of bytes in the non-paged pool, 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. This property displays the last observed value only; it is not an average.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PoolPagedBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "pool_paged_bytes"),
|
||||
"Number of bytes in the paged pool, 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. This property displays the last observed value only; it is not an average.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
PrivateBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "private_bytes"),
|
||||
"Current number of bytes this process has allocated that cannot be shared with other processes.",
|
||||
[]string{"session_name"},
|
||||
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.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
VirtualBytes: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"),
|
||||
"Current size, in bytes, of the virtual address space 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.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
VirtualBytesPeak: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes_peak"),
|
||||
"Maximum number of bytes of virtual address space the process has used at any one time. 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 might limit its ability to load libraries.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
WorkingSet: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes"),
|
||||
"Current number of bytes in the working set of this process. 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.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
WorkingSetPeak: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes_peak"),
|
||||
"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.",
|
||||
[]string{"session_name"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *TerminalServicesCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collectTSSessionCount(ctx, ch); err != nil {
|
||||
log.Error("failed collecting terminal services session count metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectTSSessionCounters(ctx, ch); err != nil {
|
||||
log.Error("failed collecting terminal services session count metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// only collect CollectionBrokerPerformance if host is a Connection Broker
|
||||
if connectionBrokerEnabled {
|
||||
if desc, err := c.collectCollectionBrokerPerformanceCounter(ctx, ch); err != nil {
|
||||
log.Error("failed collecting Connection Broker performance metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type perflibTerminalServices struct {
|
||||
ActiveSessions float64 `perflib:"Active Sessions"`
|
||||
InactiveSessions float64 `perflib:"Inactive Sessions"`
|
||||
TotalSessions float64 `perflib:"Total Sessions"`
|
||||
}
|
||||
|
||||
func (c *TerminalServicesCollector) collectTSSessionCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
dst := make([]perflibTerminalServices, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Terminal Services"], &dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.LocalSessionCount,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].ActiveSessions,
|
||||
"active",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.LocalSessionCount,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].InactiveSessions,
|
||||
"inactive",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.LocalSessionCount,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].TotalSessions,
|
||||
"total",
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type perflibTerminalServicesSession struct {
|
||||
Name string
|
||||
HandleCount float64 `perflib:"Handle Count"`
|
||||
PageFaultsPersec float64 `perflib:"Page Faults/sec"`
|
||||
PageFileBytes float64 `perflib:"Page File Bytes"`
|
||||
PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"`
|
||||
PercentPrivilegedTime float64 `perflib:"% Privileged Time"`
|
||||
PercentProcessorTime float64 `perflib:"% Processor Time"`
|
||||
PercentUserTime float64 `perflib:"% User Time"`
|
||||
PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
|
||||
PoolPagedBytes float64 `perflib:"Pool Paged Bytes"`
|
||||
PrivateBytes float64 `perflib:"Private Bytes"`
|
||||
ThreadCount float64 `perflib:"Thread Count"`
|
||||
VirtualBytes float64 `perflib:"Virtual Bytes"`
|
||||
VirtualBytesPeak float64 `perflib:"Virtual Bytes Peak"`
|
||||
WorkingSet float64 `perflib:"Working Set"`
|
||||
WorkingSetPeak float64 `perflib:"Working Set Peak"`
|
||||
}
|
||||
|
||||
func (c *TerminalServicesCollector) collectTSSessionCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
dst := make([]perflibTerminalServicesSession, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Terminal Services Session"], &dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, d := range dst {
|
||||
// only connect metrics for remote named sessions
|
||||
n := strings.ToLower(d.Name)
|
||||
if n == "" || n == "services" || n == "console" {
|
||||
continue
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HandleCount,
|
||||
prometheus.GaugeValue,
|
||||
d.HandleCount,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFaultsPersec,
|
||||
prometheus.CounterValue,
|
||||
d.PageFaultsPersec,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFileBytes,
|
||||
prometheus.GaugeValue,
|
||||
d.PageFileBytes,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFileBytesPeak,
|
||||
prometheus.GaugeValue,
|
||||
d.PageFileBytesPeak,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PercentPrivilegedTime,
|
||||
prometheus.CounterValue,
|
||||
d.PercentPrivilegedTime,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PercentProcessorTime,
|
||||
prometheus.CounterValue,
|
||||
d.PercentProcessorTime,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PercentUserTime,
|
||||
prometheus.CounterValue,
|
||||
d.PercentUserTime,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolNonpagedBytes,
|
||||
prometheus.GaugeValue,
|
||||
d.PoolNonpagedBytes,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolPagedBytes,
|
||||
prometheus.GaugeValue,
|
||||
d.PoolPagedBytes,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PrivateBytes,
|
||||
prometheus.GaugeValue,
|
||||
d.PrivateBytes,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ThreadCount,
|
||||
prometheus.GaugeValue,
|
||||
d.ThreadCount,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualBytes,
|
||||
prometheus.GaugeValue,
|
||||
d.VirtualBytes,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualBytesPeak,
|
||||
prometheus.GaugeValue,
|
||||
d.VirtualBytesPeak,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WorkingSet,
|
||||
prometheus.GaugeValue,
|
||||
d.WorkingSet,
|
||||
d.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WorkingSetPeak,
|
||||
prometheus.GaugeValue,
|
||||
d.WorkingSetPeak,
|
||||
d.Name,
|
||||
)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type perflibRemoteDesktopConnectionBrokerCounterset struct {
|
||||
SuccessfulConnections float64 `perflib:"Successful Connections"`
|
||||
PendingConnections float64 `perflib:"Pending Connections"`
|
||||
FailedConnections float64 `perflib:"Failed Connections"`
|
||||
}
|
||||
|
||||
func (c *TerminalServicesCollector) collectCollectionBrokerPerformanceCounter(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
|
||||
dst := make([]perflibRemoteDesktopConnectionBrokerCounterset, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Remote Desktop Connection Broker Counterset"], &dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionBrokerPerformance,
|
||||
prometheus.CounterValue,
|
||||
dst[0].SuccessfulConnections,
|
||||
"Successful",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionBrokerPerformance,
|
||||
prometheus.CounterValue,
|
||||
dst[0].PendingConnections,
|
||||
"Pending",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ConnectionBrokerPerformance,
|
||||
prometheus.CounterValue,
|
||||
dst[0].FailedConnections,
|
||||
"Failed",
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkTerminalServicesCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "terminal_services", NewTerminalServicesCollector)
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("thermalzone", NewThermalZoneCollector)
|
||||
}
|
||||
|
||||
// A thermalZoneCollector is a Prometheus collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics
|
||||
type thermalZoneCollector struct {
|
||||
PercentPassiveLimit *prometheus.Desc
|
||||
Temperature *prometheus.Desc
|
||||
ThrottleReasons *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewThermalZoneCollector ...
|
||||
func NewThermalZoneCollector() (Collector, error) {
|
||||
const subsystem = "thermalzone"
|
||||
return &thermalZoneCollector{
|
||||
Temperature: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "temperature_celsius"),
|
||||
"(Temperature)",
|
||||
[]string{
|
||||
"name",
|
||||
},
|
||||
nil,
|
||||
),
|
||||
PercentPassiveLimit: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "percent_passive_limit"),
|
||||
"(PercentPassiveLimit)",
|
||||
[]string{
|
||||
"name",
|
||||
},
|
||||
nil,
|
||||
),
|
||||
ThrottleReasons: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "throttle_reasons"),
|
||||
"(ThrottleReasons)",
|
||||
[]string{
|
||||
"name",
|
||||
},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *thermalZoneCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting thermalzone metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_Counters_ThermalZoneInformation docs:
|
||||
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_thermalzoneinformation/
|
||||
type Win32_PerfRawData_Counters_ThermalZoneInformation struct {
|
||||
Name string
|
||||
|
||||
HighPrecisionTemperature uint32
|
||||
PercentPassiveLimit uint32
|
||||
ThrottleReasons uint32
|
||||
}
|
||||
|
||||
func (c *thermalZoneCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_Counters_ThermalZoneInformation
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ThermalZone collector has been known to 'successfully' return an empty result.
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("Empty results set for collector")
|
||||
}
|
||||
|
||||
for _, info := range dst {
|
||||
//Divide by 10 and subtract 273.15 to convert decikelvin to celsius
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Temperature,
|
||||
prometheus.GaugeValue,
|
||||
(float64(info.HighPrecisionTemperature)/10.0)-273.15,
|
||||
info.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PercentPassiveLimit,
|
||||
prometheus.GaugeValue,
|
||||
float64(info.PercentPassiveLimit),
|
||||
info.Name,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ThrottleReasons,
|
||||
prometheus.GaugeValue,
|
||||
float64(info.ThrottleReasons),
|
||||
info.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkThermalZoneCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "thermalzone", NewThermalZoneCollector)
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("time", newTimeCollector, "Windows Time Service")
|
||||
}
|
||||
|
||||
// TimeCollector is a Prometheus collector for Perflib counter metrics
|
||||
type TimeCollector struct {
|
||||
ClockFrequencyAdjustmentPPBTotal *prometheus.Desc
|
||||
ComputedTimeOffset *prometheus.Desc
|
||||
NTPClientTimeSourceCount *prometheus.Desc
|
||||
NTPRoundtripDelay *prometheus.Desc
|
||||
NTPServerIncomingRequestsTotal *prometheus.Desc
|
||||
NTPServerOutgoingResponsesTotal *prometheus.Desc
|
||||
}
|
||||
|
||||
func newTimeCollector() (Collector, error) {
|
||||
if getWindowsVersion() <= 6.1 {
|
||||
return nil, errors.New("Windows version older than Server 2016 detected. The time collector will not run and should be disabled via CLI flags or configuration file")
|
||||
|
||||
}
|
||||
const subsystem = "time"
|
||||
|
||||
return &TimeCollector{
|
||||
ClockFrequencyAdjustmentPPBTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "clock_frequency_adjustment_ppb_total"),
|
||||
"Total adjustment made to the local system clock frequency by W32Time in Parts Per Billion (PPB) units.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ComputedTimeOffset: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "computed_time_offset_seconds"),
|
||||
"Absolute time offset between the system clock and the chosen time source, in seconds",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
NTPClientTimeSourceCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "ntp_client_time_source_count"),
|
||||
"Active number of NTP Time sources being used by the client",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
NTPRoundtripDelay: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "ntp_round_trip_delay_seconds"),
|
||||
"Roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
NTPServerOutgoingResponsesTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "ntp_server_outgoing_responses_total"),
|
||||
"Total number of requests responded to by NTP server",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
NTPServerIncomingRequestsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "ntp_server_incoming_requests_total"),
|
||||
"Total number of requests received by NTP server",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *TimeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ctx, ch); err != nil {
|
||||
log.Error("failed collecting time metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Perflib "Windows Time Service"
|
||||
type windowsTime struct {
|
||||
ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"`
|
||||
ComputedTimeOffset float64 `perflib:"Computed Time Offset"`
|
||||
NTPClientTimeSourceCount float64 `perflib:"NTP Client Time Source Count"`
|
||||
NTPRoundtripDelay float64 `perflib:"NTP Roundtrip Delay"`
|
||||
NTPServerIncomingRequestsTotal float64 `perflib:"NTP Server Incoming Requests"`
|
||||
NTPServerOutgoingResponsesTotal float64 `perflib:"NTP Server Outgoing Responses"`
|
||||
}
|
||||
|
||||
func (c *TimeCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []windowsTime // Single-instance class, array is required but will have single entry.
|
||||
if err := unmarshalObject(ctx.perfObjects["Windows Time Service"], &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ClockFrequencyAdjustmentPPBTotal,
|
||||
prometheus.CounterValue,
|
||||
dst[0].ClockFrequencyAdjustmentPPBTotal,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ComputedTimeOffset,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].ComputedTimeOffset/1000000, // microseconds -> seconds
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NTPClientTimeSourceCount,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].NTPClientTimeSourceCount,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NTPRoundtripDelay,
|
||||
prometheus.GaugeValue,
|
||||
dst[0].NTPRoundtripDelay/1000000, // microseconds -> seconds
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NTPServerIncomingRequestsTotal,
|
||||
prometheus.CounterValue,
|
||||
dst[0].NTPServerIncomingRequestsTotal,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.NTPServerOutgoingResponsesTotal,
|
||||
prometheus.CounterValue,
|
||||
dst[0].NTPServerOutgoingResponsesTotal,
|
||||
)
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkTimeCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "time", newTimeCollector)
|
||||
}
|
||||
@@ -1,345 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("vmware", NewVmwareCollector)
|
||||
}
|
||||
|
||||
// A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics
|
||||
type VmwareCollector struct {
|
||||
MemActive *prometheus.Desc
|
||||
MemBallooned *prometheus.Desc
|
||||
MemLimit *prometheus.Desc
|
||||
MemMapped *prometheus.Desc
|
||||
MemOverhead *prometheus.Desc
|
||||
MemReservation *prometheus.Desc
|
||||
MemShared *prometheus.Desc
|
||||
MemSharedSaved *prometheus.Desc
|
||||
MemShares *prometheus.Desc
|
||||
MemSwapped *prometheus.Desc
|
||||
MemTargetSize *prometheus.Desc
|
||||
MemUsed *prometheus.Desc
|
||||
|
||||
CpuLimitMHz *prometheus.Desc
|
||||
CpuReservationMHz *prometheus.Desc
|
||||
CpuShares *prometheus.Desc
|
||||
CpuStolenTotal *prometheus.Desc
|
||||
CpuTimeTotal *prometheus.Desc
|
||||
EffectiveVMSpeedMHz *prometheus.Desc
|
||||
HostProcessorSpeedMHz *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewVmwareCollector constructs a new VmwareCollector
|
||||
func NewVmwareCollector() (Collector, error) {
|
||||
const subsystem = "vmware"
|
||||
return &VmwareCollector{
|
||||
MemActive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_active_bytes"),
|
||||
"(MemActiveMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemBallooned: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_ballooned_bytes"),
|
||||
"(MemBalloonedMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemLimit: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_limit_bytes"),
|
||||
"(MemLimitMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemMapped: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_mapped_bytes"),
|
||||
"(MemMappedMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemOverhead: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_overhead_bytes"),
|
||||
"(MemOverheadMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemReservation: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_reservation_bytes"),
|
||||
"(MemReservationMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemShared: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_shared_bytes"),
|
||||
"(MemSharedMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemSharedSaved: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_shared_saved_bytes"),
|
||||
"(MemSharedSavedMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemShares: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_shares"),
|
||||
"(MemShares)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemSwapped: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_swapped_bytes"),
|
||||
"(MemSwappedMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemTargetSize: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_target_size_bytes"),
|
||||
"(MemTargetSizeMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
MemUsed: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "mem_used_bytes"),
|
||||
"(MemUsedMB)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
|
||||
CpuLimitMHz: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_limit_mhz"),
|
||||
"(CpuLimitMHz)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CpuReservationMHz: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_reservation_mhz"),
|
||||
"(CpuReservationMHz)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CpuShares: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_shares"),
|
||||
"(CpuShares)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CpuStolenTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_stolen_seconds_total"),
|
||||
"(CpuStolenMs)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
CpuTimeTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "cpu_time_seconds_total"),
|
||||
"(CpuTimePercents)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
EffectiveVMSpeedMHz: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "effective_vm_speed_mhz"),
|
||||
"(EffectiveVMSpeedMHz)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
HostProcessorSpeedMHz: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "host_processor_speed_mhz"),
|
||||
"(HostProcessorSpeedMHz)",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *VmwareCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collectMem(ch); err != nil {
|
||||
log.Error("failed collecting vmware memory metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
if desc, err := c.collectCpu(ch); err != nil {
|
||||
log.Error("failed collecting vmware cpu metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_vmGuestLib_VMem struct {
|
||||
MemActiveMB uint64
|
||||
MemBalloonedMB uint64
|
||||
MemLimitMB uint64
|
||||
MemMappedMB uint64
|
||||
MemOverheadMB uint64
|
||||
MemReservationMB uint64
|
||||
MemSharedMB uint64
|
||||
MemSharedSavedMB uint64
|
||||
MemShares uint64
|
||||
MemSwappedMB uint64
|
||||
MemTargetSizeMB uint64
|
||||
MemUsedMB uint64
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_vmGuestLib_VCPU struct {
|
||||
CpuLimitMHz uint64
|
||||
CpuReservationMHz uint64
|
||||
CpuShares uint64
|
||||
CpuStolenMs uint64
|
||||
CpuTimePercents uint64
|
||||
EffectiveVMSpeedMHz uint64
|
||||
HostProcessorSpeedMHz uint64
|
||||
}
|
||||
|
||||
func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_vmGuestLib_VMem
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemActive,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemActiveMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemBallooned,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemBalloonedMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemLimit,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemLimitMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemMapped,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemMappedMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemOverhead,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemOverheadMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemReservation,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemReservationMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemShared,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemSharedMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemSharedSaved,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemSharedSavedMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemShares,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].MemShares),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemSwapped,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemSwappedMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemTargetSize,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemTargetSizeMB),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.MemUsed,
|
||||
prometheus.GaugeValue,
|
||||
mbToBytes(dst[0].MemUsedMB),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func mbToBytes(mb uint64) float64 {
|
||||
return float64(mb * 1024 * 1024)
|
||||
}
|
||||
|
||||
func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_vmGuestLib_VCPU
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CpuLimitMHz,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].CpuLimitMHz),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CpuReservationMHz,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].CpuReservationMHz),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CpuShares,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].CpuShares),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CpuStolenTotal,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].CpuStolenMs)*ticksToSecondsScaleFactor,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CpuTimeTotal,
|
||||
prometheus.CounterValue,
|
||||
float64(dst[0].CpuTimePercents)*ticksToSecondsScaleFactor,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.EffectiveVMSpeedMHz,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].EffectiveVMSpeedMHz),
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HostProcessorSpeedMHz,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].HostProcessorSpeedMHz),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkVmwareCollector(b *testing.B) {
|
||||
benchmarkCollector(b, "vmware", NewVmwareCollector)
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/log"
|
||||
)
|
||||
|
||||
func className(src interface{}) string {
|
||||
s := reflect.Indirect(reflect.ValueOf(src))
|
||||
t := s.Type()
|
||||
if s.Kind() == reflect.Slice {
|
||||
t = t.Elem()
|
||||
}
|
||||
return t.Name()
|
||||
}
|
||||
|
||||
func queryAll(src interface{}) string {
|
||||
var b bytes.Buffer
|
||||
b.WriteString("SELECT * FROM ")
|
||||
b.WriteString(className(src))
|
||||
|
||||
log.Debugf("Generated WMI query %s", b.String())
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func queryAllForClass(src interface{}, class string) string {
|
||||
var b bytes.Buffer
|
||||
b.WriteString("SELECT * FROM ")
|
||||
b.WriteString(class)
|
||||
|
||||
log.Debugf("Generated WMI query %s", b.String())
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func queryAllWhere(src interface{}, where string) string {
|
||||
var b bytes.Buffer
|
||||
b.WriteString("SELECT * FROM ")
|
||||
b.WriteString(className(src))
|
||||
|
||||
if where != "" {
|
||||
b.WriteString(" WHERE ")
|
||||
b.WriteString(where)
|
||||
}
|
||||
|
||||
log.Debugf("Generated WMI query %s", b.String())
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func queryAllForClassWhere(src interface{}, class string, where string) string {
|
||||
var b bytes.Buffer
|
||||
b.WriteString("SELECT * FROM ")
|
||||
b.WriteString(class)
|
||||
|
||||
if where != "" {
|
||||
b.WriteString(" WHERE ")
|
||||
b.WriteString(where)
|
||||
}
|
||||
|
||||
log.Debugf("Generated WMI query %s", b.String())
|
||||
return b.String()
|
||||
}
|
||||
@@ -3,19 +3,32 @@ This directory contains documentation of the collectors in the windows_exporter,
|
||||
|
||||
# Collectors
|
||||
- [`ad`](collector.ad.md)
|
||||
- [`adcs`](collector.adcs.md)
|
||||
- [`adfs`](collector.adfs.md)
|
||||
- [`cache`](collector.cache.md)
|
||||
- [`container`](collector.container.md)
|
||||
- [`cpu`](collector.cpu.md)
|
||||
- [`cpu_info`](collector.cpu_info.md)
|
||||
- [`cs`](collector.cs.md)
|
||||
- [`dfsr`](collector.dfsr.md)
|
||||
- [`dhcp`](collector.dhcp.md)
|
||||
- [`diskdrive`](collector.diskdrive.md)
|
||||
- [`dns`](collector.dns.md)
|
||||
- [`exchange`](collector.exchange.md)
|
||||
- [`fsrmquota`](collector.fsrmquota.md)
|
||||
- [`hyperv`](collector.hyperv.md)
|
||||
- [`iis`](collector.iis.md)
|
||||
- [`logical_disk`](collector.logical_disk.md)
|
||||
- [`logon`](collector.logon.md)
|
||||
- [`memory`](collector.memory.md)
|
||||
- [`mscluster_cluster`](collector.mscluster_cluster.md)
|
||||
- [`mscluster_network`](collector.mscluster_network.md)
|
||||
- [`mscluster_node`](collector.mscluster_node.md)
|
||||
- [`mscluster_resource`](collector.mscluster_resource.md)
|
||||
- [`mscluster_resourcegroup`](collector.mscluster_resourcegroup.md)
|
||||
- [`msmq`](collector.msmq.md)
|
||||
- [`mssql`](collector.mssql.md)
|
||||
- [`net`](collector.net.md)
|
||||
- [`netframework_clrexceptions`](collector.netframework_clrexceptions.md)
|
||||
- [`netframework_clrinterop`](collector.netframework_clrinterop.md)
|
||||
- [`netframework_clrjit`](collector.netframework_clrjit.md)
|
||||
@@ -24,15 +37,21 @@ This directory contains documentation of the collectors in the windows_exporter,
|
||||
- [`netframework_clrmemory`](collector.netframework_clrmemory.md)
|
||||
- [`netframework_clrremoting`](collector.netframework_clrremoting.md)
|
||||
- [`netframework_clrsecurity`](collector.netframework_clrsecurity.md)
|
||||
- [`net`](collector.net.md)
|
||||
- [`nps`](collector.nps.md)
|
||||
- [`os`](collector.os.md)
|
||||
- [`physical_disk`](collector.physical_disk.md)
|
||||
- [`process`](collector.process.md)
|
||||
- [`remote_fx`](collector.remote_fx.md)
|
||||
- [`scheduled_task`](collector.scheduled_task.md)
|
||||
- [`service`](collector.service.md)
|
||||
- [`smb`](collector.smb.md)
|
||||
- [`smtp`](collector.smtp.md)
|
||||
- [`system`](collector.system.md)
|
||||
- [`tcp`](collector.tcp.md)
|
||||
- [`teradici_pcoip`](collector.teradici_pcoip.md)
|
||||
- [`terminal_services`](collector.terminal_services.md)
|
||||
- [`textfile`](collector.textfile.md)
|
||||
- [`thermalzone`](collector.thermalzone.md)
|
||||
- [`time`](collector.time.md)
|
||||
- [`vmware`](collector.vmware.md)
|
||||
- [`vmware_blast`](collector.vmware_blast.md)
|
||||
|
||||
@@ -59,6 +59,7 @@ Name | Description | Type | Labels
|
||||
`windows_ad_ldap_searches_total` | _Not yet documented_ | counter | None
|
||||
`windows_ad_ldap_udp_operations_total` | _Not yet documented_ | counter | None
|
||||
`windows_ad_ldap_writes_total` | _Not yet documented_ | counter | None
|
||||
`windows_ad_ldap_client_sessions` | This is the number of sessions opened by LDAP clients at the time the data is taken. This is helpful in determining LDAP client activity and if the DC is able to handle the load. Of course, spikes during normal periods of authentication — such as first thing in the morning — are not necessarily a problem, but long sustained periods of high values indicate an overworked DC | gauge | None
|
||||
`windows_ad_link_values_cleaned_total` | _Not yet documented_ | counter | None
|
||||
`windows_ad_phantom_objects_cleaned_total` | _Not yet documented_ | counter | None
|
||||
`windows_ad_phantom_objects_visited_total` | _Not yet documented_ | counter | None
|
||||
|
||||
55
docs/collector.adcs.md
Normal file
55
docs/collector.adcs.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# adcs collector
|
||||
|
||||
The adcs collector exposes metrics about Active Directory Certificate Services, Note that this collector has only been tested against Windows Server 2019.
|
||||
Other Windows Server versions may work but are not tested.
|
||||
|
||||
|||
|
||||
-|-
|
||||
Metric name prefix | `adcs`
|
||||
Data source | Perflib
|
||||
Counters | `Certification Authority`
|
||||
Enabled by default? | No
|
||||
|
||||
## Flags
|
||||
|
||||
None
|
||||
|
||||
## Metrics
|
||||
|
||||
Name | Description | Type | Labels
|
||||
-----|-------------|------|-------
|
||||
|requests_total|Total certificate requests processed|counter|`cert_template`|
|
||||
|request_processing_time_seconds|Last time elapsed for certificate requests|gauge|`cert_template`|
|
||||
|retrievals_total|Last time elapsed for certificate requests|counter|`cert_template`|
|
||||
|retrievals_processing_time_seconds|Last time elapsed for certificate retrieval request|gauge|`cert_template`|
|
||||
|failed_requests_total|Total failed certificate requests processed|counter|`cert_template`|
|
||||
|issued_requests_total|Total issued certificate requests processed|counter|`cert_template`|
|
||||
|pending_requests_total|Total pending certificate requests processed|counter|`cert_template`|
|
||||
|request_cryptographic_signing_time_seconds|Last time elapsed for signing operation request|gauge|`cert_template`|
|
||||
|request_policy_module_processing_time_seconds|Last time elapsed for policy module processing request|gauge|`cert_template`|
|
||||
|challenge_responses_total|Total certificate challenge responses processed|counter|`cert_template`|
|
||||
|challenge_response_processing_time_seconds|Last time elapsed for challenge response|gauge|`cert_template`|
|
||||
|signed_certificate_timestamp_lists_total|Total Signed Certificate Timestamp Lists processed|counter|`cert_template`|
|
||||
|signed_certificate_timestamp_list_processing_time_seconds|Last time elapsed for Signed Certificate Timestamp List|gauge|`cert_template`|
|
||||
|
||||
### Example metric
|
||||
```
|
||||
windows_adcs_issued_requests_total{cert_template="Administrator"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="DirectoryEmailReplication"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="DomainController"} 1
|
||||
windows_adcs_issued_requests_total{cert_template="DomainControllerAuthentication"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="EFS"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="EFSRecovery"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="KerberosAuthentication"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="Machine"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="SubCA"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="User"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="WebServer"} 0
|
||||
windows_adcs_issued_requests_total{cert_template="_Total"} 1
|
||||
```
|
||||
|
||||
## Useful queries
|
||||
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
|
||||
|
||||
## Alerting examples
|
||||
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
|
||||
@@ -1,6 +1,6 @@
|
||||
# adfs collector
|
||||
|
||||
The adfs collector exposes metrics about Active Directory Federation Services. Note that this collector has only been tested against ADFS 4.0 (2016).
|
||||
The ADFS collector exposes metrics about Active Directory Federation Services. Note that this collector has only been tested against ADFS 4.0/ [Farm Behavior (FLB) 3](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/upgrading-to-ad-fs-in-windows-server#ad-fs-farm-behavior-levels-fbl) (Server 2016).
|
||||
Other ADFS versions may work but are not tested.
|
||||
|
||||
|||
|
||||
@@ -28,6 +28,39 @@ Name | Description | Type | Labels
|
||||
`windows_adfs_password_change_succeeded_total` | Total number of succeeded password changes. The Password Change Portal must be enabled in the AD FS Management tool in order to allow user password changes | counter | None
|
||||
`windows_adfs_token_requests_total` | Total number of requested access tokens | counter | None
|
||||
`windows_adfs_windows_integrated_authentications_total` | Total number of Windows integrated authentications using Kerberos or NTLM | counter | None
|
||||
`windows_adfs_passive_requests_total` | Total number of passive (browser-based) requests | counter | None
|
||||
`windows_adfs_oauth_authorization_requests_total` | Total number of incoming requests to the OAuth Authorization endpoint | counter | None
|
||||
`windows_adfs_oauth_client_authentication_success_total` | Total number of successful OAuth client Authentications | counter | None
|
||||
`windows_adfs_oauth_client_authentication_failure_total` | Total number of failed OAuth client Authentications | counter | None
|
||||
`windows_adfs_oauth_client_credentials_failure_total` | Total number of failed OAuth Client Credentials Requests | counter | None
|
||||
`windows_adfs_oauth_client_credentials_success_total` | Total number of successful RP tokens issued for OAuth Client Credentials Requests | counter | None
|
||||
`windows_adfs_oauth_client_privkey_jwt_authentication_failure_total` | Total number of failed OAuth Client Private Key Jwt Authentications | counter | None
|
||||
`windows_adfs_oauth_client_privkey_jwt_authentications_success_total` | Total number of successful OAuth Client Private Key Jwt Authentications | counter | None
|
||||
`windows_adfs_oauth_client_secret_basic_authentications_failure_total` | Total number of failed OAuth Client Secret Basic Authentications | counter | None
|
||||
`windows_adfs_oauth_client_secret_basic_authentications_success_total` | Total number of successful OAuth Client Secret Basic Authentications | counter | None
|
||||
`windows_adfs_oauth_client_secret_post_authentications_failure_total` | Total number of failed OAuth Client Secret Post Authentications | counter | None
|
||||
`windows_adfs_oauth_client_secret_post_authentications_success_total` | Total number of successful OAuth Client Secret Post Authentications | counter | None
|
||||
`windows_adfs_oauth_client_windows_authentications_failure_total` | Total number of failed OAuth Client Windows Integrated Authentications | counter | None
|
||||
`windows_adfs_oauth_client_windows_authentications_success_total` | Total number of successful OAuth Client Windows Integrated Authentications | counter | None
|
||||
`windows_adfs_oauth_logon_certificate_requests_failure_total` | Total number of failed OAuth Logon Certificate Requests | counter | None
|
||||
`windows_adfs_oauth_logon_certificate_token_requests_success_total` | Total number of successful RP tokens issued for OAuth Logon Certificate Requests | counter | None
|
||||
`windows_adfs_oauth_password_grant_requests_failure_total` | Total number of failed OAuth Password Grant Requests | counter | None
|
||||
`windows_adfs_oauth_password_grant_requests_success_total` | Total number of successful OAuth Password Grant Requests | counter | None
|
||||
`windows_adfs_oauth_token_requests_success_total` | Total number of successful RP tokens issued over OAuth protocol | counter | None
|
||||
`windows_adfs_samlp_token_requests_success_total` | Total number of successful RP tokens issued over SAML-P protocol | counter | None
|
||||
`windows_adfs_sso_authentications_failure_total` | Total number of failed SSO authentications | counter | None
|
||||
`windows_adfs_sso_authentications_success_total` | Total number of successful SSO authentications | counter | None
|
||||
`windows_adfs_wsfed_token_requests_success_total` | Total number of successful RP tokens issued over WS-Fed protocol | counter | None
|
||||
`windows_adfs_wstrust_token_requests_success_total` | Total number of successful RP tokens issued over WS-Trust protocol | counter | None
|
||||
`windows_adfs_userpassword_authentications_failure_total` | Total number of failed AD U/P authentications | counter | None
|
||||
`windows_adfs_userpassword_authentications_success_total` | Total number of successful AD U/P authentications | counter | None
|
||||
`windows_adfs_external_authentications_failure_total` | Total number of failed authentications from external MFA providers | counter | None
|
||||
`windows_adfs_external_authentications_success_total` | Total number of successful authentications from external MFA providers | counter | None
|
||||
`windows_adfs_db_artifact_failure_total` | Total number of failures connecting to the artifact database | counter | None
|
||||
`windows_adfs_db_artifact_query_time_seconds_total` | Accumulator of time taken for an artifact database query | counter | None
|
||||
`windows_adfs_db_config_failure_total` | Total number of failures connecting to the configuration database | counter | None
|
||||
`windows_adfs_db_config_query_time_seconds_total` | Accumulator of time taken for a configuration database query | counter | None
|
||||
`windows_adfs_federation_metadata_requests_total` | Total number of Federation Metadata requests | counter | None
|
||||
|
||||
### Example metric
|
||||
Show rate of device authentications in AD FS:
|
||||
@@ -37,6 +70,11 @@ rate(windows_adfs_device_authentications)[2m]
|
||||
|
||||
## Useful queries
|
||||
|
||||
|Query|Description|
|
||||
|---|----|
|
||||
|`rate(windows_adfs_oauth_password_grant_requests_failure_total[5m])`| Rate of OAuth requests failing due to bad client/resource values|
|
||||
|`rate(windows_adfs_userpassword_authentications_failures_total[5m])`| Rate of `/adfs/oauth2/token/` requests failing due to bad username/password values (possible credential spraying)|
|
||||
|
||||
## Alerting examples
|
||||
**prometheus.rules**
|
||||
```yaml
|
||||
|
||||
@@ -30,6 +30,10 @@ Name | Description | Type | Labels
|
||||
`windows_container_network_transmit_bytes_total` | Bytes Sent on Interface | counter | `container_id`, `interface`
|
||||
`windows_container_network_transmit_packets_total` | Packets Sent on Interface | counter | `container_id`, `interface`
|
||||
`windows_container_network_transmit_packets_dropped_total` | Dropped Outgoing Packets on Interface | counter | `container_id`, `interface`
|
||||
`windows_container_storage_read_count_normalized_total` | Read Count Normalized | counter | `container_id`
|
||||
`windows_container_storage_read_size_bytes_total` | Read Size Bytes | counter | `container_id`
|
||||
`windows_container_storage_write_count_normalized_total` | Write Count Normalized | counter | `container_id`
|
||||
`windows_container_storage_write_size_bytes_total` | Write Size Bytes | counter | `container_id`
|
||||
|
||||
### Example metric
|
||||
_windows_container_network_receive_bytes_total{container_id="docker://1bd30e8b8ac28cbd76a9b697b4d7bb9d760267b0733d1bc55c60024e98d1e43e",interface="822179E7-002C-4280-ABBA-28BCFE401826"} 9.3305343e+07_
|
||||
@@ -37,7 +41,11 @@ _windows_container_network_receive_bytes_total{container_id="docker://1bd30e8b8a
|
||||
This metric means that total _9.3305343e+07_ bytes received on interface _822179E7-002C-4280-ABBA-28BCFE401826_ for container _docker://1bd30e8b8ac28cbd76a9b697b4d7bb9d760267b0733d1bc55c60024e98d1e43e_
|
||||
|
||||
## Useful queries
|
||||
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
|
||||
|
||||
Attach labels namespace/pod/container fow windows container metrics.
|
||||
```
|
||||
# kube_pod_container_info(a metric of kube-state-metrics) has labels namespace/pod/container/container_id for a container, while windows container metrics only have container_id.
|
||||
# Attaching labels namespace/pod/container for windows container metrics, is useful to query for windows pods.
|
||||
windows_container_network_receive_bytes_total * on(container_id) group_left(namespace, pod, container) kube_pod_container_info{container_id!=""}
|
||||
```
|
||||
## Alerting examples
|
||||
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
|
||||
|
||||
@@ -19,7 +19,7 @@ These metrics are available on all versions of Windows:
|
||||
Name | Description | Type | Labels
|
||||
-----|-------------|------|-------
|
||||
`windows_cpu_cstate_seconds_total` | Time spent in low-power idle states | counter | `core`, `state`
|
||||
`windows_cpu_time_total` | Time that processor spent in different modes (idle, user, system, ...) | counter | `core`, `mode`
|
||||
`windows_cpu_time_total` | Time that processor spent in different modes (dpc, idle, interrupt, privileged, user) | counter | `core`, `mode`
|
||||
`windows_cpu_interrupts_total` | Total number of received and serviced hardware interrupts | counter | `core`
|
||||
`windows_cpu_dpcs_total` | Total number of received and serviced deferred procedure calls (DPCs) | counter | `core`
|
||||
|
||||
@@ -31,7 +31,11 @@ Name | Description | Type | Labels
|
||||
`windows_cpu_idle_break_events_total` | Total number of time processor was woken from idle | counter | `core`
|
||||
`windows_cpu_parking_status` | Parking Status represents whether a processor is parked or not | gauge | `core`
|
||||
`windows_cpu_core_frequency_mhz` | Core frequency in megahertz | gauge | `core`
|
||||
`windows_cpu_processor_performance` | 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% | gauge | `core`
|
||||
`windows_cpu_processor_performance_total` | Processor Performance is the number of CPU cycles executing instructions by each core; it is believed to be similar to the value that the APERF MSR would show, were it exposed | counter | `core`
|
||||
`windows_cpu_processor_mperf_total` | Processor MPerf Total is proportioanl to the number of TSC ticks each core has accumulated while executing instructions. Due to the manner in which it is presented, it should be scaled by 1e2 to properly line up with Processor Performance Total. As above, it is believed to be closely related to the MPERF MSR. | counter | `core`
|
||||
`windows_cpu_processor_rtc_total` | RTC total is assumed to represent the 64Hz tick rate in Windows. It is not by itself useful, but can be used with `windows_cpu_processor_utility_total` to more accurately measure CPU utilisation than with `windows_cpu_time_total` | counter | `core`
|
||||
`windows_cpu_processor_utility_total` | Processor Utility Total is a newer, more accurate measure of CPU utilization, in particular handling modern CPUs with variant CPU frequencies. The rate of this counter divided by the rate of `windows_cpu_processor_rtc_total` should provide an accurate view of CPU utilisation on modern systems, as observed in Task Manager. | counter | `core`
|
||||
`windows_cpu_processor_privileged_utility_total` | Processor Privileged Utility Total, when used in a similar fashion to `windows_cpu_processor_utility_total` will show the portion of CPU utilization which is happening in privileged mode. | counter | `core`
|
||||
|
||||
### Example metric
|
||||
Show frequency of host CPU cores
|
||||
@@ -44,6 +48,19 @@ Show cpu usage by mode.
|
||||
```
|
||||
sum by (mode) (irate(windows_cpu_time_total{instance="localhost"}[5m]))
|
||||
```
|
||||
Show per-cpu utilisation using the processor utility metrics
|
||||
```
|
||||
rate(windows_cpu_processor_utility_total{instance="localhost"}[5m]) / rate(windows_cpu_processor_rtc_total{instance="localhost"}[5m])
|
||||
```
|
||||
Show actual average CPU frequency in Hz
|
||||
```
|
||||
avg by(instance) (
|
||||
1e4 * windows_cpu_core_frequency_mhz{}
|
||||
* rate(windows_cpu_processor_performance_total{}[5m])
|
||||
/ rate(windows_cpu_processor_mperf_total{}[5m])
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
## Alerting examples
|
||||
**prometheus.rules**
|
||||
@@ -57,4 +74,18 @@ sum by (mode) (irate(windows_cpu_time_total{instance="localhost"}[5m]))
|
||||
annotations:
|
||||
summary: "CPU Usage (instance {{ $labels.instance }})"
|
||||
description: "CPU Usage is more than 80%\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
|
||||
# Alert on hosts which are not boosting their CPU frequencies
|
||||
- alert: NoCpuTurbo
|
||||
expr: |
|
||||
avg by(instance) (
|
||||
1e4 * windows_cpu_core_frequency_mhz{}
|
||||
* rate(windows_cpu_processor_performance_total{}[5m])
|
||||
/ rate(windows_cpu_processor_mperf_total{}[5m])
|
||||
)
|
||||
/
|
||||
(1e6 * avg by (instance) (windows_cpu_core_frequency_mhz))
|
||||
< 1.1
|
||||
for: 1h
|
||||
annotations:
|
||||
summary: "CPU Frequency on {{ $labels.instance }} is less than 110% of base frequency, suggesting it is not able to boost.
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ None
|
||||
|
||||
Name | Description | Type | Labels
|
||||
-----|-------------|------|-------
|
||||
`windows_cpu_info` | Labeled CPU information | gauge | `architecture`, `device_id`, `description`, `family`, `l2_cache_size` `l3_cache_size`, `name`
|
||||
`windows_cpu_info` | Labelled CPU information | gauge | `architecture`, `device_id`, `description`, `family`, `l2_cache_size` `l3_cache_size`, `name`
|
||||
|
||||
### Example metric
|
||||
```
|
||||
|
||||
@@ -18,7 +18,7 @@ Name | Description | Type | Labels
|
||||
-----|-------------|------|-------
|
||||
`windows_cs_logical_processors` | Number of installed logical processors | gauge | None
|
||||
`windows_cs_physical_memory_bytes` | Total installed physical memory | gauge | None
|
||||
`windows_cs_hostname` | Labeled system hostname information | gauge | `hostname`, `domain`, `fqdn`
|
||||
`windows_cs_hostname` | Labelled system hostname information | gauge | `hostname`, `domain`, `fqdn`
|
||||
|
||||
### Example metric
|
||||
_This collector does not yet have explained examples, we would appreciate your help adding them!_
|
||||
|
||||
40
docs/collector.diskdrive.md
Normal file
40
docs/collector.diskdrive.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# diskdrive collector
|
||||
|
||||
The diskdrive collector exposes metrics about physical disks
|
||||
|
||||
| | |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Metric name prefix | `diskdrive` |
|
||||
| Classes | [`Win32_DiskDrive`](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive) |
|
||||
| Enabled by default? | No |
|
||||
|
||||
## Flags
|
||||
|
||||
None
|
||||
|
||||
## Metrics
|
||||
|
||||
| Name | Description | Type | Labels |
|
||||
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ |
|
||||
| `diskdrive_info` | General identifiable information about the disk drive | gauge | name,caption,device_id,model |
|
||||
| `diskdrive_availability` | The disk drive's current availability | gauge | name,availability |
|
||||
| `diskdrive_partitions` | Number of partitions on the drive | gauge | name |
|
||||
| `diskdrive_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. | gauge | name |
|
||||
| `diskdrive_status` | Operational status of the drive | gauge | name,status |
|
||||
|
||||
## Alerting examples
|
||||
**prometheus.rules**
|
||||
```yaml
|
||||
groups:
|
||||
- name: Windows Disk Alerts
|
||||
rules:
|
||||
|
||||
- alert: Drive_Status
|
||||
expr: windows_disk_drive_status{status="OK"} != 1
|
||||
for: 10m
|
||||
labels:
|
||||
severity: high
|
||||
annotations:
|
||||
summary: "Instance: {{ $labels.instance }} has drive status: {{ $labels.status }} on disk {{ $labels.name }}"
|
||||
description: "Drive Status Unhealthy"
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user