Compare commits

...

143 Commits

Author SHA1 Message Date
Ben Reedy
05091643c6 Merge pull request #1256 from breed808/fix_msi_flag
fix: Set correct eventlog flag for MSI installer
2023-07-22 08:42:41 +10:00
Ben Reedy
76e73487e4 fix: Set correct eventlog flag for MSI installer
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-07-22 08:38:09 +10:00
Ben Reedy
9a2ec21278 Merge pull request #1255 from jkroepke/fix-eventlog
Fix panic with log.file=eventlog
2023-07-22 08:31:11 +10:00
Jan-Otto Kröpke
44b435e7d4 Fix panic with log.file=eventlog
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-21 20:18:15 +02:00
Ben Reedy
f068cf4523 Merge pull request #1218 from tzifudzi/bugfix/missing-container-metrics
Resolve issue preventing networking container stats from being sent to collector
2023-07-21 18:02:08 +10:00
Tatenda Zifudzi
9adefdceeb fix: Resolve missing container network metrics by querying from HNS
This fix ensures that network stats for containerd on Windows are successfully collected. Before this change, other container stats such as CPU and memory are successfully collected, but network stats are failing for containerd.

The root cause is that the code for collecting network stats was originally written to work with docker which relies on v1 schema. After dockershim removal as Kubernetes's container runtime, containerd adoption has increased and this error is more frequently encountered when using containerd as  the runtime. containerd uses v2 schema whereby the network stats need to be queried from the HNS component.

Signed-off-by: Tatenda Zifudzi <tzifudzi@amazon.com>
2023-07-20 11:22:29 -07:00
Ben Reedy
be9d2872a5 Merge pull request #1241 from jkroepke/perflib
Integrate perflib
2023-07-19 19:32:44 +10:00
Ben Reedy
89cb5439b8 Merge pull request #1243 from DiniFarb/master
Load config file from URL
2023-07-17 20:26:34 +10:00
DiniFarb
b08ce0697c Update readme (flag part)
Signed-off-by: DiniFarb <andreas.vogt89@bluewin.ch>
2023-07-17 20:10:15 +10:00
DiniFarb
279a8fce89 Update readme: config file part
Signed-off-by: DiniFarb <andreas.vogt89@bluewin.ch>
2023-07-17 20:10:07 +10:00
DiniFarb
11ec45e710 feat: Skip TLS verify in loading config from url
Signed-off-by: DiniFarb <andreas.vogt89@bluewin.ch>
2023-07-17 20:09:58 +10:00
DiniFarb
6797126e78 update readme
Signed-off-by: DiniFarb <andreas.vogt89@bluewin.ch>
2023-07-17 20:09:49 +10:00
DiniFarb
19794ad2e0 feat: load config file from url (#1207)
Signed-off-by: DiniFarb <andreas.vogt89@bluewin.ch>
2023-07-17 20:09:39 +10:00
Jan-Otto Kröpke
9e59bf920f Post rebase issues
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 10:05:51 +02:00
Jan-Otto Kröpke
11218a95d0 Implement Lazy Loading of NameTable
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 10:01:46 +02:00
Jan-Otto Kröpke
9b5bc37a42 Re-add NameIndex
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 10:00:46 +02:00
Jan-Otto Kröpke
9ef897e07b Add LICENSE
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 10:00:46 +02:00
Jan-Otto Kröpke
3a61935273 Cleanup binaryReaderFrom
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 10:00:46 +02:00
Jan-Otto Kröpke
8b9c9a5bd2 Remove HelpNameTable
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 10:00:46 +02:00
Jan-Otto Kröpke
976e055252 move directory
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 10:00:43 +02:00
Jan-Otto Kröpke
9e368d49e7 add error handling
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 09:59:46 +02:00
Jan-Otto Kröpke
ad1ab35399 remove SortObjects
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 09:59:46 +02:00
Jan-Otto Kröpke
81745eeedf fix docs
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 09:59:46 +02:00
Jan-Otto Kröpke
fff737998d move global Name Tables
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 09:59:46 +02:00
Jan-Otto Kröpke
4ea61a2641 Remove unused nameTableLookuper
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 09:59:46 +02:00
Jan-Otto Kröpke
750225775b Integrate perflib
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-15 09:59:43 +02:00
Ben Reedy
80cf16efe8 Merge pull request #1245 from bragi92/master
fix: Update init container in windows exporter so that it works on both WS2019 and WS2022
2023-07-15 10:58:31 +10:00
Kaveesh Dubey
f96c6654be fix: Update init container in windows exporter so that it works on both WS2019 and WS2022
Signed-off-by: Kaveesh Dubey <kadubey@microsoft.com>
2023-07-14 17:17:53 -07:00
Ben Reedy
10e42d3583 Merge pull request #1188 from rebortg/master
NPS(feature): add nps collector
2023-07-11 06:28:40 +10:00
Ben Reedy
95f250ed39 feat: Update NPS collector for go-kit logging
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-07-11 06:23:10 +10:00
rebortg
7115c9dc22 add nps collector in init.go
Signed-off-by: rebortg <github@ghlr.de>
2023-07-11 06:04:19 +10:00
rebortg
478eaa91d9 delete init() and rename newNPSCollector function
Signed-off-by: rebortg <github@ghlr.de>
2023-07-11 06:04:15 +10:00
rebortg
217b670272 NPS(feature): add nps collector
Signed-off-by: rebortg <github@ghlr.de>
2023-07-11 06:04:12 +10:00
Ben Reedy
d5e8a0ed7e Merge pull request #1184 from peekjef72/update-terminal_services
fix Terminal Service duplicate session names under load.
2023-07-10 12:06:07 +10:00
Peekjef72
8b74c77663 remove known session name
Signed-off-by: Peekjef72 <67902897+peekjef72@users.noreply.github.com>
2023-07-10 12:00:40 +10:00
Ben Reedy
4077290659 Merge pull request #1192 from jkroepke/custom-logger
switch to go-kit logger
2023-07-10 11:57:32 +10:00
Jan-Otto Kröpke
014153a503 Use 0200 for write permissions
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-10 01:31:26 +02:00
Jan-Otto Kröpke
cfb0111d8c revert fix on newTimeCollector
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-10 00:44:30 +02:00
Jan-Otto Kröpke
5d96a42382 fix typo
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-10 00:44:23 +02:00
Jan-Otto Kröpke
6890f391d4 fix lint
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-09 22:42:00 +02:00
Jan-Otto Kröpke
4350587141 go mod tidy
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-09 22:37:58 +02:00
Jan-Otto Kröpke
8509bc69a6 switch to go-kit logger
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-09 22:37:27 +02:00
Ben Reedy
e0e31254e2 Merge pull request #1239 from breed808/pwsh_7.3
feat(doc): Document Powershell v7.3 argument parsing
2023-07-09 13:43:28 +10:00
Ben Reedy
c633aadc71 feat(doc): Document Powershell v7.3 argument parsing
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-07-09 13:42:24 +10:00
Ben Reedy
809424f851 Merge pull request #1238 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.10.0
chore(deps): bump golang.org/x/sys from 0.8.0 to 0.10.0
2023-07-09 08:13:32 +10:00
dependabot[bot]
88d518378c chore(deps): bump golang.org/x/sys from 0.8.0 to 0.10.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.8.0 to 0.10.0.
- [Commits](https://github.com/golang/sys/compare/v0.8.0...v0.10.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-08 21:57:53 +00:00
Ben Reedy
8cfd6bbcf1 Merge pull request #1230 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_golang-1.16.0
chore(deps): bump github.com/prometheus/client_golang from 1.15.1 to 1.16.0
2023-07-09 07:56:54 +10:00
dependabot[bot]
4ba2fe7f22 chore(deps): bump github.com/prometheus/client_golang
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.15.1 to 1.16.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.15.1...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-08 21:51:13 +00:00
Ben Reedy
a49a0fc612 Merge pull request #1225 from prometheus-community/dependabot/go_modules/github.com/leoluk/perflib_exporter-0.2.1
chore(deps): bump github.com/leoluk/perflib_exporter from 0.2.0 to 0.2.1
2023-07-09 07:50:25 +10:00
dependabot[bot]
23722ae792 chore(deps): bump github.com/leoluk/perflib_exporter from 0.2.0 to 0.2.1
Bumps [github.com/leoluk/perflib_exporter](https://github.com/leoluk/perflib_exporter) from 0.2.0 to 0.2.1.
- [Release notes](https://github.com/leoluk/perflib_exporter/releases)
- [Commits](https://github.com/leoluk/perflib_exporter/compare/v0.2.0...v0.2.1)

---
updated-dependencies:
- dependency-name: github.com/leoluk/perflib_exporter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-08 21:43:59 +00:00
Ben Reedy
731b996767 Merge pull request #1224 from prometheus-community/dependabot/go_modules/github.com/yusufpapurcu/wmi-1.2.3
chore(deps): bump github.com/yusufpapurcu/wmi from 1.2.2 to 1.2.3
2023-07-09 07:41:45 +10:00
dependabot[bot]
2fe869f1db chore(deps): bump github.com/yusufpapurcu/wmi from 1.2.2 to 1.2.3
Bumps [github.com/yusufpapurcu/wmi](https://github.com/yusufpapurcu/wmi) from 1.2.2 to 1.2.3.
- [Release notes](https://github.com/yusufpapurcu/wmi/releases)
- [Commits](https://github.com/yusufpapurcu/wmi/compare/v1.2.2...v1.2.3)

---
updated-dependencies:
- dependency-name: github.com/yusufpapurcu/wmi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 11:57:50 +00:00
Ben Reedy
6ba0297aa9 Merge pull request #1219 from prometheus-community/dependabot/go_modules/github.com/sirupsen/logrus-1.9.3
chore(deps): bump github.com/sirupsen/logrus from 1.9.0 to 1.9.3
2023-06-12 08:04:43 +10:00
dependabot[bot]
dc3e172056 chore(deps): bump github.com/sirupsen/logrus from 1.9.0 to 1.9.3
Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.9.0 to 1.9.3.
- [Release notes](https://github.com/sirupsen/logrus/releases)
- [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sirupsen/logrus/compare/v1.9.0...v1.9.3)

---
updated-dependencies:
- dependency-name: github.com/sirupsen/logrus
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-11 21:46:01 +00:00
Ben Reedy
4327eb386a Merge pull request #1212 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.44.0
chore(deps): bump github.com/prometheus/common from 0.42.0 to 0.44.0
2023-06-12 07:45:12 +10:00
dependabot[bot]
79f4cf5dec chore(deps): bump github.com/prometheus/common from 0.42.0 to 0.44.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.42.0 to 0.44.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.42.0...v0.44.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/common
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-11 21:39:44 +00:00
Ben Reedy
5aae5054e6 Merge pull request #1204 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_golang-1.15.1
chore(deps): bump github.com/prometheus/client_golang from 1.15.0 to 1.15.1
2023-06-12 07:38:55 +10:00
dependabot[bot]
e81231d403 chore(deps): bump github.com/prometheus/client_golang
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.15.0 to 1.15.1.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.15.0...v1.15.1)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-11 21:22:52 +00:00
Ben Reedy
0e0d0f8fd8 Merge pull request #1202 from prometheus-community/dependabot/go_modules/github.com/prometheus/exporter-toolkit-0.10.0
chore(deps): bump github.com/prometheus/exporter-toolkit from 0.9.1 to 0.10.0
2023-06-12 07:21:32 +10:00
dependabot[bot]
c1e829dbd5 chore(deps): bump github.com/prometheus/exporter-toolkit
Bumps [github.com/prometheus/exporter-toolkit](https://github.com/prometheus/exporter-toolkit) from 0.9.1 to 0.10.0.
- [Release notes](https://github.com/prometheus/exporter-toolkit/releases)
- [Changelog](https://github.com/prometheus/exporter-toolkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prometheus/exporter-toolkit/compare/v0.9.1...v0.10.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/exporter-toolkit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-11 21:15:04 +00:00
Ben Reedy
434788a90a Merge pull request #1205 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.8.0
chore(deps): bump golang.org/x/sys from 0.7.0 to 0.8.0
2023-06-12 07:13:17 +10:00
Ben Reedy
6c06beca1d Merge pull request #1206 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_model-0.4.0
chore(deps): bump github.com/prometheus/client_model from 0.3.0 to 0.4.0
2023-05-23 17:43:28 +10:00
dependabot[bot]
486b4319c7 chore(deps): bump github.com/prometheus/client_model from 0.3.0 to 0.4.0
Bumps [github.com/prometheus/client_model](https://github.com/prometheus/client_model) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/prometheus/client_model/releases)
- [Commits](https://github.com/prometheus/client_model/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_model
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 12:07:52 +00:00
dependabot[bot]
88847204ff chore(deps): bump golang.org/x/sys from 0.7.0 to 0.8.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.7.0 to 0.8.0.
- [Commits](https://github.com/golang/sys/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 12:07:45 +00:00
Ben Reedy
79781c6d75 Merge pull request #1201 from ilyam8/fix_hyperv_vswitch_missing_sent_packets
fix: add missing vswitch packets_sent_total
2023-05-07 20:46:22 +10:00
Ben Reedy
4cd095798d Merge pull request #1133 from breed808/iis_duplicates
fix: Ignore duplicate IIS entries from Perflib
2023-05-07 20:17:25 +10:00
Ben Reedy
1d3af58305 fix: Ignore duplicate IIS entries from Perflib
Perflib often exposes duplicate IIS entries, suffixed with '#' and a
number (I.E. iis_site_name#1).
These duplicate entries were causing the exporter to fail scraping due
to duplicate metrics.

Based on user feedback, the entry with the highest suffix
value is kept, with other duplicate entries discarded.

E.G. Given the following list of site names, "Site_B" would be
discarded, and "Site_B#2" would be kept and presented as "Site_B" in the
collector metrics.
[ "Site_A", "Site_B", "Site_C", "Site_B#2" ]

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-05-07 20:12:32 +10:00
Ben Reedy
b431ff6ac3 Merge pull request #1195 from jkroepke/custom-collector
Move prometheus collector from main to collectors
2023-05-07 13:04:58 +10:00
ilyam8
579369dbf5 fix: add missing vswitch packets_sent_total
Signed-off-by: ilyam8 <ilya@netdata.cloud>
2023-05-04 19:25:17 +03:00
Ben Reedy
f19fa777c3 Merge pull request #1189 from vrapolinario/viniap-msft-ws2022
Add yaml for WS2022 nodes
2023-04-30 08:13:27 +10:00
vrapolinario
0db55044e8 Add yaml for WS2022 nodes
Signed-off-by: vrapolinario <viniap@microsoft.com>
2023-04-26 14:49:27 -07:00
Jan-Otto Kröpke
352492ea97 Move collector from main to separate package
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-04-23 15:25:41 +02:00
Ben Reedy
76c435d12c Merge pull request #1170 from breed808/include_exclude
feat!: Deprecate whitelist/blacklist flags
2023-04-19 09:15:30 +10:00
Ben Reedy
fab77d9d31 feat!: Deprecate whitelist/blacklist flags
Flags have been deprecated in favour of include/exclude terminology.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-04-19 06:11:23 +10:00
Ben Reedy
3627520559 Merge pull request #1186 from jkroepke/custom-kingpin
Remove fluent-style kingpin
2023-04-18 08:27:00 +10:00
Ben Reedy
b033ff71ff Merge pull request #1187 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_golang-1.15.0
chore(deps): bump github.com/prometheus/client_golang from 1.14.0 to 1.15.0
2023-04-18 07:14:44 +10:00
dependabot[bot]
8d781cf540 chore(deps): bump github.com/prometheus/client_golang
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 11:58:31 +00:00
Jan-Otto Kröpke
da6898afc4 Remove fluent-style kingpin
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-04-17 13:22:36 +02:00
Ben Reedy
a105e088b3 Merge pull request #1181 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.7.0
chore(deps): bump golang.org/x/sys from 0.6.0 to 0.7.0
2023-04-15 05:31:59 +10:00
Ben Reedy
30955eae17 Merge pull request #1183 from Elpatii/master
Fix telemetry.addr deprecated since v0.21.0
2023-04-15 05:31:13 +10:00
Elpatii
d7b08d7ce0 Fix telemetry.addr deprecated since v0.21.0
Signed-off-by: Elpatii <4057711+Elpatii@users.noreply.github.com>
2023-04-12 14:52:55 +02:00
dependabot[bot]
05abe04d90 chore(deps): bump golang.org/x/sys from 0.6.0 to 0.7.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/sys/releases)
- [Commits](https://github.com/golang/sys/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 11:57:37 +00:00
Ben Reedy
bacd040b17 Merge pull request #1174 from breed808/adfs_jwt
fix!: Fix jtw -> jwt ADFS spelling error
2023-04-04 06:15:29 +10:00
Ben Reedy
1df91ba769 fix!: Fix jtw -> jwt ADFS spelling error
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-04-04 05:49:39 +10:00
Ben Reedy
4e02053f13 Merge pull request #1171 from breed808/diskdrive_name
fix!: Set correct diskdrive collector/metric name
2023-04-04 05:48:05 +10:00
Ben Reedy
535f041423 fix!: Set correct diskdrive collector/metric name
Previous name did not match documentation and WMI class.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-04-03 06:17:15 +10:00
Ben Reedy
49afc93d93 Merge pull request #1112 from breed808/remove_init
Remove init functions from collectors
2023-04-01 18:17:27 +10:00
Ben Reedy
04257a1b25 chore: Ensure collector build funcs are private
Collector builder functions are only used internally in the `collector`
package, and shouldn't needlessly be exposed as part of the package API
to downstream clients.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-04-01 17:54:41 +10:00
Ben Reedy
9214a87d0d feat: Remove init functions from collectors
Behaviour of init functions has been centralised in `collector/init.go`,
and can be called during exporter startup. This allows the exporter to
control the timing of collector initialisation, rather than relying on
the import & `init()` method.

This should reduce unexpected behaviour arising from the use of
`init()`, such as #551.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-04-01 17:54:40 +10:00
Ben Reedy
8132083892 Merge pull request #1167 from breed808/ci_deps
chore(ci): Update release workflow actions
2023-03-27 07:04:30 +10:00
Ben Reedy
890fac507e chore(ci): Update release workflow actions
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-03-27 07:03:01 +10:00
Ben Reedy
b29434c7c0 Merge pull request #1166 from breed808/net_output_queue_length
feat: Add output_queue_length metric to net collector
2023-03-26 06:55:02 +10:00
Ben Reedy
7e293a4230 feat: Add output_queue_length metric to net collector
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-03-26 06:48:39 +10:00
Ben Reedy
e21407c112 Merge pull request #1165 from prometheus-community/superq/landing_page
Use new landing page generator
2023-03-26 06:00:29 +10:00
SuperQ
bee042d9fa Use new landing page generator
Use the new exporter-toolkit landing page generator feature.
* Update Go to 1.20.
* Update promu to 0.14.0.

Signed-off-by: SuperQ <superq@gmail.com>
2023-03-25 10:41:48 +01:00
Ben Reedy
6efeace169 Merge pull request #1161 from breed808/default_metrics
feat: Allow default metrics to be disabled
2023-03-25 09:05:52 +10:00
Ben Reedy
a5b3926063 feat: Remove default metrics from e2e test
Metrics are provided by client library, and not the exporter, so
comparing them for differences does not provide much value.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-03-25 09:00:05 +10:00
Ben Reedy
6306973948 feat: Allow default metrics to be disabled
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-03-25 08:59:54 +10:00
Ben Reedy
84b6f15505 Merge pull request #1162 from Mak0tin/update-doc-mssql-iis
Update docs for mssql and iis
2023-03-24 15:49:34 +10:00
Manuel Hernandez
0a75d72610 Update collector.mssql.md
Update metric types from counter to gauge to match code

Signed-off-by: Manuel Hernandez <106690360+Mak0tin@users.noreply.github.com>
2023-03-21 15:49:32 +01:00
Manuel Hernandez
549c4d1098 Update collector.iis.md
Update metric types from counter to gauge to match code

Signed-off-by: Manuel Hernandez <106690360+Mak0tin@users.noreply.github.com>
2023-03-21 12:28:30 +01:00
Ben Reedy
ea2b446130 Merge pull request #1158 from mansikulkarni96/fix1157
fix: Build error with GOFLAGS=-mod=vendor
2023-03-21 07:14:12 +10:00
mansikulkarni96
6129a528c6 fix: Build error with GOFLAGS=-mod=vendor
This commit updates go version in go.mod to go1.17
to resolve build error when vendor flag is used.
Package x/sys/windows requires go1.17 or above
causing make build to fail.

Fixes: #1157
Signed-off-by: mansikulkarni96 <mankulka@redhat.com>
2023-03-20 16:29:10 -04:00
Ben Reedy
13c5bc5c95 Merge pull request #1160 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.9.8
chore(deps): bump github.com/Microsoft/hcsshim from 0.9.7 to 0.9.8
2023-03-21 05:35:54 +10:00
dependabot[bot]
78b11f9dc0 chore(deps): bump github.com/Microsoft/hcsshim from 0.9.7 to 0.9.8
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.9.7 to 0.9.8.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.9.7...v0.9.8)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 11:58:22 +00:00
Ben Reedy
0dc4acac00 Merge pull request #1144 from fuxingZhang/patch-1
docs: fix documentation error
2023-03-19 08:03:10 +10:00
zfx
931c3f78d9 docs: fix documentation errors
Fix the documentation and code inconsistencies caused by the following commit
> e9c594473c

Signed-off-by: zfx <fuxing.zhang@qq.com>
2023-03-13 15:46:36 +08:00
Ben Reedy
6a26df8069 Merge pull request #1148 from ankom2007/patch-1
Update collector.iis.md
2023-03-13 09:47:41 +10:00
Ben Reedy
a4404fa77a Merge pull request #1150 from prometheus-community/dependabot/go_modules/github.com/prometheus/exporter-toolkit-0.9.1
chore(deps): bump github.com/prometheus/exporter-toolkit from 0.8.2 to 0.9.1
2023-03-13 09:44:23 +10:00
dependabot[bot]
e19f80e5c7 chore(deps): bump github.com/prometheus/exporter-toolkit
Bumps [github.com/prometheus/exporter-toolkit](https://github.com/prometheus/exporter-toolkit) from 0.8.2 to 0.9.1.
- [Release notes](https://github.com/prometheus/exporter-toolkit/releases)
- [Changelog](https://github.com/prometheus/exporter-toolkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prometheus/exporter-toolkit/compare/v0.8.2...v0.9.1)

---
updated-dependencies:
- dependency-name: github.com/prometheus/exporter-toolkit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-13 09:36:27 +10:00
Ben Reedy
416ccf1228 chore(deps): bump github.com/alecthomas/kingpin
Bumps [github.com/alecthomas/kingpin](https://github.com/alecthomas/kingpin) from
v2.2.6 to v2.3.2.

This also changes the upstream package name from
gopkg.in/alecthomas/kingpin.v2 to github.com/alecthomas/kingpin/v2 which
is required by the upstream exporter-toolkit package.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-03-13 09:36:23 +10:00
Ben Reedy
edbccbdad4 Merge pull request #1151 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.42.0
chore(deps): bump github.com/prometheus/common from 0.39.0 to 0.42.0
2023-03-12 18:34:16 +10:00
dependabot[bot]
aa66719b30 chore(deps): bump github.com/prometheus/common from 0.39.0 to 0.42.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.39.0 to 0.42.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.39.0...v0.42.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/common
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-12 08:11:20 +00:00
Ben Reedy
b1b8c34361 Merge pull request #1146 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.6.0
chore(deps): bump golang.org/x/sys from 0.4.0 to 0.6.0
2023-03-12 18:10:12 +10:00
dependabot[bot]
9c08c916e0 chore(deps): bump golang.org/x/sys from 0.4.0 to 0.6.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.4.0 to 0.6.0.
- [Release notes](https://github.com/golang/sys/releases)
- [Commits](https://github.com/golang/sys/compare/v0.4.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-12 07:41:49 +00:00
Ben Reedy
b6c91bfe8c Merge pull request #1152 from breed808/wmi_upstream_change
chore(deps): Update wmi to v1.2.2
2023-03-12 17:41:01 +10:00
Ben Reedy
7886cf9e37 chore(deps): Update wmi to v1.2.2
This includes a move from github.com/StackExchange/wmi to
github.com/yusufpapurcu/wmi, as the StackExchange repository has been
archived.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-03-12 17:34:34 +10:00
Ben Reedy
8d4c38b48e chore(ci): Update golangci-lint to v1.51.2
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-03-12 17:34:33 +10:00
Ben Reedy
0a26661b7d Merge pull request #1142 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.9.7
chore(deps): bump github.com/Microsoft/hcsshim from 0.9.6 to 0.9.7
2023-03-12 09:31:16 +10:00
Ankur Agarwal
864687daed Update collector.iis.md
Added the description of the metrics for "no documented yet"

Signed-off-by: Ankur Agarwal <75574195+ankom2007@users.noreply.github.com>
2023-03-08 18:16:41 +11:00
dependabot[bot]
c8c3cefecc chore(deps): bump github.com/Microsoft/hcsshim from 0.9.6 to 0.9.7
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.9.6 to 0.9.7.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.9.6...v0.9.7)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 11:59:24 +00:00
Ben Reedy
12e5422845 Merge pull request #1137 from DennisGaida/patch-1
Added quote information for absolute paths
2023-02-25 09:57:37 +10:00
Ben Reedy
a7960872bb Merge pull request #1136 from bck01215/patch-2
Remove Bad Comment
2023-02-18 11:17:07 +10:00
Dennis Gaida
94aff9fe73 Added quote information for absolute paths
This had me running in circles because `ioutil.ReadFile` did not read the local file for me when running as a service (i.e. `config.yml` in the same folder as the `windows_exporter.exe`). I had to use absolute paths and additionally quote them.

Signed-off-by: Dennis Gaida <2392217+DennisGaida@users.noreply.github.com>
2023-02-15 16:40:22 +01:00
Brandon Kauffman
9044097f2c Remove Bad Comment
Signed-off-by: Brandon Kauffman <bck01215@gmail.com>
2023-02-14 08:56:11 -05:00
Ben Reedy
a52ce30089 Merge pull request #1127 from tpowelldev/master
Add VDI Metrics collections
2023-02-12 09:44:35 +10:00
Tom Powell
846263afee Returning test functions to public
Signed-off-by: Tom Powell <t.powell@mwam.com>
2023-02-08 10:12:15 +00:00
Tom Powell
ba3cffdc79 Applying PR comments
Signed-off-by: Tom Powell <t.powell@mwam.com>
2023-02-08 09:30:36 +00:00
Tom Powell
dde839b66d Adding Teradici PCoIP session metrics collection
Signed-off-by: Tom Powell <t.powell@mwam.com>

Added collector for VMware Blast session metrics

Signed-off-by: Tom Powell <t.powell@mwam.com>

Updating collection logic to handle missing WMI classes

Signed-off-by: Tom Powell <t.powell@mwam.com>

Updating packet loss metric to gauge

Signed-off-by: Tom Powell <t.powell@mwam.com>
2023-01-25 12:04:55 +00:00
Ben Reedy
ca15e2c70d Merge pull request #1121 from breed808/diskdrive_docs
Add labels to diskdrive docs
2023-01-15 09:53:27 +10:00
Ben Reedy
0ea3bfa5c9 chore(docs): Add labels to diskdrive docs
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-01-15 09:51:45 +10:00
Ben Reedy
5331909446 Merge pull request #1095 from 6fears7/master
Add Win32_DiskDrive Collector
2023-01-15 09:27:49 +10:00
Ben Reedy
e8eb77363e Merge pull request #1119 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.4.0
chore(deps): bump golang.org/x/sys from 0.3.0 to 0.4.0
2023-01-14 08:47:08 +10:00
pgibbs1
da2707c594 Removed placeholder text
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
pgibbs1
b0844b9118 Fixed linting md
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
pgibbs1
27977e3730 Added collector docs, entry to readme
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
sixfears7
f2f9f624b5 Updated naming convention, fixed metric type
Signed-off-by: sixfears7 <57415489+6fears7@users.noreply.github.com>
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
sixfears7
586152a4ad Updated code to add label to size and partition
Signed-off-by: sixfears7 <57415489+6fears7@users.noreply.github.com>
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
pgibbs1
9a2ef3fca8 Fixed blackslashes, replaced model with name
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
pgibbs1
6912c5b1e7 Removed commented benchmark
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
pgibbs1
f24fc07ac4 Fixed moved files
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
sixfears7
653182a90c Added diskdrive collector
To retrieve data from Win32_DiskDrive Object

Signed-off-by: sixfears7 <57415489+6fears7@users.noreply.github.com>
Signed-off-by: pgibbs1 <pgibbs1@liberty.edu>
2023-01-12 17:08:59 -05:00
dependabot[bot]
2958e0801d chore(deps): bump golang.org/x/sys from 0.3.0 to 0.4.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/golang/sys/releases)
- [Commits](https://github.com/golang/sys/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 11:04:33 +00:00
141 changed files with 6562 additions and 2246 deletions

View File

@@ -23,8 +23,8 @@ on:
- master
env:
PROMU_VER: '0.13.0'
PROMTOOL_VER: '2.32.1'
PROMU_VER: '0.14.0'
PROMTOOL_VER: '2.43.0'
jobs:
test:
@@ -33,7 +33,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.17.5'
go-version: '^1.20.2'
- name: Test
run: make test
@@ -57,7 +57,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.17.5'
go-version: '^1.20.2'
- name: Install promtool
run: |
@@ -89,12 +89,12 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.17.5'
go-version: '^1.20.2'
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.45.2
version: v1.51.2
args: "--timeout=5m"
# golangci-lint action doesn't always provide helpful output, so re-run without the action for

View File

@@ -12,7 +12,7 @@ permissions:
packages: write
env:
PROMU_VER: '0.13.0'
PROMU_VER: '0.14.0'
jobs:
build:
@@ -25,7 +25,7 @@ jobs:
- uses: actions/setup-go@v3
with:
go-version: '^1.17.5'
go-version: '^1.20.2'
- name: Install Build deps
run: |
@@ -59,7 +59,7 @@ jobs:
}
- name: Upload Artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: windows_exporter_binaries
path: output\windows_exporter-*.exe
@@ -82,7 +82,7 @@ jobs:
- name: Login to GitHub container registry
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}

View File

@@ -10,7 +10,7 @@ on:
- master
env:
PROMU_VER: 'v0.13.0'
PROMU_VER: 'v0.14.0'
jobs:
codespell:

View File

@@ -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

View File

@@ -51,10 +51,12 @@ Name | Description | Enabled by default
[smtp](docs/collector.smtp.md) | IIS SMTP Server |
[system](docs/collector.system.md) | System calls | &#10003;
[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 | &#10003;
[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.
@@ -80,13 +82,15 @@ windows_exporter accepts flags to configure certain behaviours. The ones configu
Flag | Description | Default value
---------|-------------|--------------------
`--telemetry.addr` | host:port for exporter. | `:9182`
`--web.listen-address` | host:port for exporter. | `:9182`
`--telemetry.path` | URL path for surfacing collected metrics. | `/metrics`
`--telemetry.max-requests` | Maximum number of concurrent requests. 0 to disable. | `5`
`--collectors.enabled` | Comma-separated list of collectors to use. Use `[defaults]` as a placeholder 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).
@@ -102,7 +106,7 @@ Name | Description
`LISTEN_PORT` | The port to bind to. Defaults to 9182.
`METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics`
`TEXTFILE_DIR` | As the `--collector.textfile.directory` flag, provide a directory to read text files with metrics from
`REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (whitelist). Defaults to an empty string (any remote address).
`REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (allow list). Defaults to an empty string (any remote address).
`EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string.
Parameters are sent to the installer via `msiexec`. Example invocations:
@@ -121,6 +125,13 @@ On some older versions of Windows you may need to surround parameter values with
msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,thermalzone" TEXTFILE_DIR="C:\custom_metrics\"
```
Powershell versions 7.3 and above require [PSNativeCommandArgumentPassing](https://learn.microsoft.com/en-us/powershell/scripting/learn/experimental-features?view=powershell-7.3) to be set to `Legacy` when using `--% EXTRA_FLAGS`:
```powershell
$PSNativeCommandArgumentPassing = 'Legacy'
msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,service --% EXTRA_FLAGS="--collector.service.services-where ""Name LIKE 'sql%'"""
```
## Kubernetes Implementation
@@ -148,7 +159,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.
@@ -162,7 +173,11 @@ This enables the additional process and container collectors on top of the defau
### 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:

View File

@@ -6,17 +6,16 @@ package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("ad", NewADCollector)
}
// A ADCollector is a Prometheus collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics
type ADCollector struct {
logger log.Logger
AddressBookOperationsTotal *prometheus.Desc
AddressBookClientSessions *prometheus.Desc
ApproximateHighestDistinguishedNameTag *prometheus.Desc
@@ -80,10 +79,12 @@ type ADCollector struct {
TombstonedObjectsVisitedTotal *prometheus.Desc
}
// NewADCollector ...
func NewADCollector() (Collector, error) {
// newADCollector ...
func newADCollector(logger log.Logger) (Collector, error) {
const subsystem = "ad"
return &ADCollector{
logger: log.With(logger, "collector", subsystem),
AddressBookOperationsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "address_book_operations_total"),
"",
@@ -457,7 +458,7 @@ func NewADCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *ADCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting ad metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting ad metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -617,7 +618,7 @@ type Win32_PerfRawData_DirectoryServices_DirectoryServices struct {
func (c *ADCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_DirectoryServices_DirectoryServices
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkADCollector(b *testing.B) {
benchmarkCollector(b, "ad", NewADCollector)
benchmarkCollector(b, "ad", newADCollector)
}

View File

@@ -5,16 +5,16 @@ package collector
import (
"errors"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"strings"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("adcs", adcsCollectorMethod, "Certification Authority")
}
type adcsCollector struct {
logger log.Logger
RequestsPerSecond *prometheus.Desc
RequestProcessingTime *prometheus.Desc
RetrievalsPerSecond *prometheus.Desc
@@ -31,9 +31,11 @@ type adcsCollector struct {
}
// ADCSCollectorMethod ...
func adcsCollectorMethod() (Collector, error) {
func adcsCollectorMethod(logger log.Logger) (Collector, error) {
const subsystem = "adcs"
return &adcsCollector{
logger: log.With(logger, "collector", subsystem),
RequestsPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "requests_total"),
"Total certificate requests processed",
@@ -117,7 +119,7 @@ func adcsCollectorMethod() (Collector, error) {
func (c *adcsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collectADCSCounters(ctx, ch); err != nil {
log.Error("Failed collecting ADCS Metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting ADCS metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -145,7 +147,7 @@ func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- promet
if _, ok := ctx.perfObjects["Certification Authority"]; !ok {
return nil, errors.New("Perflib did not contain an entry for Certification Authority")
}
err := unmarshalObject(ctx.perfObjects["Certification Authority"], &dst)
err := unmarshalObject(ctx.perfObjects["Certification Authority"], &dst, c.logger)
if err != nil {
return nil, err
}

View File

@@ -4,15 +4,15 @@
package collector
import (
"github.com/prometheus/client_golang/prometheus"
"math"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("adfs", newADFSCollector, "AD FS")
}
type adfsCollector struct {
logger log.Logger
adLoginConnectionFailures *prometheus.Desc
certificateAuthentications *prometheus.Desc
deviceAuthentications *prometheus.Desc
@@ -59,10 +59,12 @@ type adfsCollector struct {
}
// newADFSCollector constructs a new adfsCollector
func newADFSCollector() (Collector, error) {
func newADFSCollector(logger log.Logger) (Collector, error) {
const subsystem = "adfs"
return &adfsCollector{
logger: log.With(logger, "collector", subsystem),
adLoginConnectionFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ad_login_connection_failures_total"),
"Total number of connection failures to an Active Directory domain controller",
@@ -160,7 +162,7 @@ func newADFSCollector() (Collector, error) {
nil,
),
oAuthClientPrivateKeyJwtAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jtw_authentication_failure_total"),
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jwt_authentication_failure_total"),
"Total number of failed OAuth Client Private Key Jwt Authentications",
nil,
nil,
@@ -372,7 +374,7 @@ type perflibADFS struct {
func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var adfsData []perflibADFS
err := unmarshalObject(ctx.perfObjects["AD FS"], &adfsData)
err := unmarshalObject(ctx.perfObjects["AD FS"], &adfsData, c.logger)
if err != nil {
return err
}

View File

@@ -4,16 +4,15 @@
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("cache", newCacheCollector, "Cache")
}
// A CacheCollector is a Prometheus collector for Perflib Cache metrics
type CacheCollector struct {
logger log.Logger
AsyncCopyReadsTotal *prometheus.Desc
AsyncDataMapsTotal *prometheus.Desc
AsyncFastReadsTotal *prometheus.Desc
@@ -46,9 +45,11 @@ type CacheCollector struct {
}
// NewCacheCollector ...
func newCacheCollector() (Collector, error) {
func newCacheCollector(logger log.Logger) (Collector, error) {
const subsystem = "cache"
return &CacheCollector{
logger: log.With(logger, "collector", subsystem),
AsyncCopyReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "async_copy_reads_total"),
"(AsyncCopyReadsTotal)",
@@ -229,7 +230,7 @@ func newCacheCollector() (Collector, error) {
// Collect implements the Collector interface
func (c *CacheCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting cache metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting cache metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -271,7 +272,7 @@ type perflibCache struct {
func (c *CacheCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []perflibCache // Single-instance class, array is required but will have single entry.
if err := unmarshalObject(ctx.perfObjects["Cache"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["Cache"], &dst, c.logger); err != nil {
return nil, err
}

View File

@@ -6,8 +6,11 @@ import (
"strconv"
"strings"
"github.com/leoluk/perflib_exporter/perflib"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus-community/windows_exporter/perflib"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows/registry"
)
@@ -24,33 +27,35 @@ const (
// getWindowsVersion reads the version number of the OS from the Registry
// See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version
func getWindowsVersion() float64 {
func getWindowsVersion(logger log.Logger) float64 {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
if err != nil {
log.Warn("Couldn't open registry", err)
_ = level.Warn(logger).Log("msg", "Couldn't open registry", "err", err)
return 0
}
defer func() {
err = k.Close()
if err != nil {
log.Warnf("Failed to close registry key: %v", err)
_ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err)
}
}()
currentv, _, err := k.GetStringValue("CurrentVersion")
if err != nil {
log.Warn("Couldn't open registry to determine current Windows version:", err)
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine current Windows version", "err", err)
return 0
}
currentv_flt, err := strconv.ParseFloat(currentv, 64)
log.Debugf("Detected Windows version %f\n", currentv_flt)
_ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected Windows version %f\n", currentv_flt))
return currentv_flt
}
type collectorBuilder func() (Collector, error)
type collectorBuilder func(log.Logger) (Collector, error)
type flagsBuilder func(*kingpin.Application)
type perfCounterNamesBuilder func(log.Logger) []string
var (
builders = make(map[string]collectorBuilder)
@@ -77,12 +82,12 @@ func Available() []string {
}
return cs
}
func Build(collector string) (Collector, error) {
func Build(collector string, logger log.Logger) (Collector, error) {
builder, exists := builders[collector]
if !exists {
return nil, fmt.Errorf("Unknown collector %q", collector)
}
return builder()
return builder(logger)
}
func getPerfQuery(collectors []string) string {
parts := make([]string, 0, len(collectors))

View File

@@ -4,6 +4,7 @@ import (
"reflect"
"testing"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
)
@@ -35,14 +36,14 @@ func TestExpandChildCollectors(t *testing.T) {
}
}
func benchmarkCollector(b *testing.B, name string, collectFunc func() (Collector, error)) {
func benchmarkCollector(b *testing.B, name string, collectFunc func(logger log.Logger) (Collector, error)) {
// Create perflib scrape context. Some perflib collectors required a correct context,
// or will fail during benchmark.
scrapeContext, err := PrepareScrapeContext([]string{name})
if err != nil {
b.Error(err)
}
c, err := collectFunc()
c, err := collectFunc(log.NewNopLogger())
if err != nil {
b.Error(err)
}

View File

@@ -4,17 +4,19 @@
package collector
import (
"fmt"
"strings"
"github.com/Microsoft/hcsshim"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("container", NewContainerMetricsCollector)
}
// A ContainerMetricsCollector is a Prometheus collector for containers metrics
type ContainerMetricsCollector struct {
logger log.Logger
// Presence
ContainerAvailable *prometheus.Desc
@@ -45,10 +47,12 @@ type ContainerMetricsCollector struct {
WriteSizeBytes *prometheus.Desc
}
// NewContainerMetricsCollector constructs a new ContainerMetricsCollector
func NewContainerMetricsCollector() (Collector, error) {
// newContainerMetricsCollector constructs a new ContainerMetricsCollector
func newContainerMetricsCollector(logger log.Logger) (Collector, error) {
const subsystem = "container"
return &ContainerMetricsCollector{
logger: log.With(logger, "collector", subsystem),
ContainerAvailable: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "available"),
"Available",
@@ -164,17 +168,17 @@ func NewContainerMetricsCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *ContainerMetricsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting ContainerMetricsCollector metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting ContainerMetricsCollector metrics", "desc", desc, "err", err)
return err
}
return nil
}
// containerClose closes the container resource
func containerClose(c hcsshim.Container) {
err := c.Close()
func (c *ContainerMetricsCollector) containerClose(container hcsshim.Container) {
err := container.Close()
if err != nil {
log.Error(err)
_ = level.Error(c.logger).Log("err", err)
}
}
@@ -183,7 +187,7 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
// Types Container is passed to get the containers compute systems only
containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}})
if err != nil {
log.Error("Err in Getting containers:", err)
_ = level.Error(c.logger).Log("msg", "Err in Getting containers", "err", err)
return nil, err
}
@@ -198,22 +202,26 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
return nil, nil
}
containerPrefixes := make(map[string]string)
for _, containerDetails := range containers {
container, err := hcsshim.OpenContainer(containerDetails.ID)
if container != nil {
defer containerClose(container)
defer c.containerClose(container)
}
if err != nil {
log.Error("err in opening container: ", containerDetails.ID, err)
_ = level.Error(c.logger).Log("msg", "err in opening container", "containerId", containerDetails.ID, "err", err)
continue
}
cstats, err := container.Statistics()
if err != nil {
log.Error("err in fetching container Statistics: ", containerDetails.ID, err)
_ = level.Error(c.logger).Log("msg", "err in fetching container Statistics", "containerId", containerDetails.ID, "err", err)
continue
}
containerIdWithPrefix := getContainerIdWithPrefix(containerDetails)
containerPrefixes[containerDetails.ID] = containerIdWithPrefix
ch <- prometheus.MustNewConstMetric(
c.ContainerAvailable,
@@ -257,54 +265,6 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
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
}
ch <- prometheus.MustNewConstMetric(
c.ReadCountNormalized,
prometheus.CounterValue,
@@ -331,6 +291,73 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
)
}
hnsEndpoints, err := hcsshim.HNSListEndpointRequest()
if err != nil {
_ = level.Warn(c.logger).Log("msg", "Failed to collect network stats for containers")
return nil, nil
}
if len(hnsEndpoints) == 0 {
_ = level.Info(c.logger).Log("msg", fmt.Sprintf("No network stats for containers to collect"))
return nil, nil
}
for _, endpoint := range hnsEndpoints {
endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id)
if err != nil {
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for interface %s", endpoint.Id), "err", err)
continue
}
for _, containerId := range endpoint.SharedContainers {
containerIdWithPrefix, ok := containerPrefixes[containerId]
endpointId := strings.ToUpper(endpoint.Id)
if !ok {
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for container %s", containerId))
continue
}
ch <- prometheus.MustNewConstMetric(
c.BytesReceived,
prometheus.CounterValue,
float64(endpointStats.BytesReceived),
containerIdWithPrefix, endpointId,
)
ch <- prometheus.MustNewConstMetric(
c.BytesSent,
prometheus.CounterValue,
float64(endpointStats.BytesSent),
containerIdWithPrefix, endpointId,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsReceived,
prometheus.CounterValue,
float64(endpointStats.PacketsReceived),
containerIdWithPrefix, endpointId,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsSent,
prometheus.CounterValue,
float64(endpointStats.PacketsSent),
containerIdWithPrefix, endpointId,
)
ch <- prometheus.MustNewConstMetric(
c.DroppedPacketsIncoming,
prometheus.CounterValue,
float64(endpointStats.DroppedPacketsIncoming),
containerIdWithPrefix, endpointId,
)
ch <- prometheus.MustNewConstMetric(
c.DroppedPacketsOutgoing,
prometheus.CounterValue,
float64(endpointStats.DroppedPacketsOutgoing),
containerIdWithPrefix, endpointId,
)
}
}
return nil, nil
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkContainerCollector(b *testing.B) {
benchmarkCollector(b, "container", NewContainerMetricsCollector)
benchmarkCollector(b, "container", newContainerMetricsCollector)
}

View File

@@ -6,27 +6,21 @@ package collector
import (
"strings"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
var deps string
// See below for 6.05 magic value
if getWindowsVersion() > 6.05 {
deps = "Processor Information"
} else {
deps = "Processor"
}
registerCollector("cpu", newCPUCollector, deps)
}
type cpuCollectorBasic struct {
logger log.Logger
CStateSecondsTotal *prometheus.Desc
TimeTotal *prometheus.Desc
InterruptsTotal *prometheus.Desc
DPCsTotal *prometheus.Desc
}
type cpuCollectorFull struct {
logger log.Logger
CStateSecondsTotal *prometheus.Desc
TimeTotal *prometheus.Desc
InterruptsTotal *prometheus.Desc
@@ -44,10 +38,11 @@ type cpuCollectorFull struct {
}
// newCPUCollector constructs a new cpuCollector, appropriate for the running OS
func newCPUCollector() (Collector, error) {
func newCPUCollector(logger log.Logger) (Collector, error) {
const subsystem = "cpu"
logger = log.With(logger, "collector", subsystem)
version := getWindowsVersion()
version := getWindowsVersion(logger)
// For Windows 2008 (version 6.0) or earlier we only have the "Processor"
// class. As of Windows 2008 R2 (version 6.1) the more detailed
// "Processor Information" set is available (although some of the counters
@@ -56,6 +51,7 @@ func newCPUCollector() (Collector, error) {
// Value 6.05 was selected to split between Windows versions.
if version < 6.05 {
return &cpuCollectorBasic{
logger: logger,
CStateSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"),
"Time spent in low-power idle state",
@@ -84,6 +80,7 @@ func newCPUCollector() (Collector, error) {
}
return &cpuCollectorFull{
logger: logger,
CStateSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"),
"Time spent in low-power idle state",
@@ -186,7 +183,7 @@ type perflibProcessor struct {
func (c *cpuCollectorBasic) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
data := make([]perflibProcessor, 0)
err := unmarshalObject(ctx.perfObjects["Processor"], &data)
err := unmarshalObject(ctx.perfObjects["Processor"], &data, c.logger)
if err != nil {
return err
}
@@ -295,7 +292,7 @@ type perflibProcessorInformation struct {
func (c *cpuCollectorFull) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
data := make([]perflibProcessorInformation, 0)
err := unmarshalObject(ctx.perfObjects["Processor Information"], &data)
err := unmarshalObject(ctx.perfObjects["Processor Information"], &data, c.logger)
if err != nil {
return err
}

View File

@@ -8,15 +8,12 @@ import (
"strconv"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("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"
@@ -24,13 +21,18 @@ const (
// A CpuInfoCollector is a Prometheus collector for a few WMI metrics in Win32_Processor
type CpuInfoCollector struct {
logger log.Logger
CpuInfo *prometheus.Desc
}
func newCpuInfoCollector() (Collector, error) {
func newCpuInfoCollector(logger log.Logger) (Collector, error) {
const subsystem = "cpu_info"
return &CpuInfoCollector{
logger: log.With(logger, "collector", subsystem),
CpuInfo: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "", "cpu_info"),
prometheus.BuildFQName(Namespace, "", subsystem),
"Labeled CPU information as provided provided by Win32_Processor",
[]string{
"architecture",
@@ -59,7 +61,7 @@ type win32_Processor struct {
// to the provided prometheus Metric channel.
func (c *CpuInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting cpu_info metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting cpu_info metrics", "desc", desc, "err", err)
return err
}
return nil

View File

@@ -4,28 +4,28 @@
package collector
import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"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 {
logger log.Logger
PhysicalMemoryBytes *prometheus.Desc
LogicalProcessors *prometheus.Desc
Hostname *prometheus.Desc
}
// NewCSCollector ...
func NewCSCollector() (Collector, error) {
// newCSCollector ...
func newCSCollector(logger log.Logger) (Collector, error) {
const subsystem = "cs"
return &CSCollector{
logger: log.With(logger, "collector", subsystem),
LogicalProcessors: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "logical_processors"),
"ComputerSystem.NumberOfLogicalProcessors",
@@ -54,7 +54,7 @@ func NewCSCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *CSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting cs metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting cs metrics", "desc", desc, "err", err)
return err
}
return nil

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkCsCollector(b *testing.B) {
benchmarkCollector(b, "cs", NewCSCollector)
benchmarkCollector(b, "cs", newCSCollector)
}

View File

@@ -4,25 +4,22 @@
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
)
var dfsrEnabledCollectors = kingpin.Flag("collectors.dfsr.sources-enabled", "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String()
const (
FlagDfsrEnabledCollectors = "collectors.dfsr.sources-enabled"
)
func init() {
// Perflib sources are dynamic, depending on the enabled child collectors
var perflibDependencies []string
for _, source := range expandEnabledChildCollectors(*dfsrEnabledCollectors) {
perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source))
}
registerCollector("dfsr", NewDFSRCollector, perflibDependencies...)
}
var dfsrEnabledCollectors *string
// DFSRCollector contains the metric and state data of the DFSR collectors.
type DFSRCollector struct {
logger log.Logger
// Connection source
ConnectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc
ConnectionBytesReceivedTotal *prometheus.Desc
@@ -92,10 +89,16 @@ func dfsrGetPerfObjectName(collector string) string {
return (prefix + suffix)
}
// NewDFSRCollector is registered
func NewDFSRCollector() (Collector, error) {
log.Info("dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
// newDFSRCollectorFlags is registered
func newDFSRCollectorFlags(app *kingpin.Application) {
dfsrEnabledCollectors = app.Flag(FlagDfsrEnabledCollectors, "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String()
}
// newDFSRCollector is registered
func newDFSRCollector(logger log.Logger) (Collector, error) {
const subsystem = "dfsr"
logger = log.With(logger, "collector", subsystem)
_ = level.Info(logger).Log("msg", "dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
enabled := expandEnabledChildCollectors(*dfsrEnabledCollectors)
perfCounters := make([]string, 0, len(enabled))
@@ -105,6 +108,8 @@ func NewDFSRCollector() (Collector, error) {
addPerfCounterDependencies(subsystem, perfCounters)
dfsrCollector := DFSRCollector{
logger: logger,
// Connection
ConnectionBandwidthSavingsUsingDFSReplicationTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_bandwidth_savings_using_dfs_replication_bytes_total"),
@@ -448,7 +453,7 @@ type PerflibDFSRConnection struct {
func (c *DFSRCollector) collectConnection(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []PerflibDFSRConnection
if err := unmarshalObject(ctx.perfObjects["DFS Replication Connections"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["DFS Replication Connections"], &dst, c.logger); err != nil {
return err
}
@@ -555,7 +560,7 @@ type PerflibDFSRFolder struct {
func (c *DFSRCollector) collectFolder(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []PerflibDFSRFolder
if err := unmarshalObject(ctx.perfObjects["DFS Replicated Folders"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["DFS Replicated Folders"], &dst, c.logger); err != nil {
return err
}
@@ -765,7 +770,7 @@ type PerflibDFSRVolume struct {
func (c *DFSRCollector) collectVolume(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []PerflibDFSRVolume
if err := unmarshalObject(ctx.perfObjects["DFS Replication Service Volumes"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["DFS Replication Service Volumes"], &dst, c.logger); err != nil {
return err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkDFSRCollector(b *testing.B) {
benchmarkCollector(b, "dfsr", NewDFSRCollector)
benchmarkCollector(b, "dfsr", newDFSRCollector)
}

View File

@@ -4,15 +4,14 @@
package collector
import (
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("dhcp", NewDhcpCollector, "DHCP Server")
}
// A DhcpCollector is a Prometheus collector perflib DHCP metrics
type DhcpCollector struct {
logger log.Logger
PacketsReceivedTotal *prometheus.Desc
DuplicatesDroppedTotal *prometheus.Desc
PacketsExpiredTotal *prometheus.Desc
@@ -40,10 +39,12 @@ type DhcpCollector struct {
FailoverBndupdDropped *prometheus.Desc
}
func NewDhcpCollector() (Collector, error) {
func newDhcpCollector(logger log.Logger) (Collector, error) {
const subsystem = "dhcp"
return &DhcpCollector{
logger: log.With(logger, "collector", subsystem),
PacketsReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"),
"Total number of packets received by the DHCP server (PacketsReceivedTotal)",
@@ -230,7 +231,7 @@ type dhcpPerf struct {
func (c *DhcpCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var perflib []dhcpPerf
if err := unmarshalObject(ctx.perfObjects["DHCP Server"], &perflib); err != nil {
if err := unmarshalObject(ctx.perfObjects["DHCP Server"], &perflib, c.logger); err != nil {
return err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkDHCPCollector(b *testing.B) {
benchmarkCollector(b, "dhcp", NewDhcpCollector)
benchmarkCollector(b, "dhcp", newDhcpCollector)
}

209
collector/diskdrive.go Normal file
View File

@@ -0,0 +1,209 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"strings"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
const (
win32DiskQuery = "SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive"
)
// A DiskDriveInfoCollector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive
type DiskDriveInfoCollector struct {
logger log.Logger
DiskInfo *prometheus.Desc
Status *prometheus.Desc
Size *prometheus.Desc
Partitions *prometheus.Desc
Availability *prometheus.Desc
}
func newDiskDriveInfoCollector(logger log.Logger) (Collector, error) {
const subsystem = "diskdrive"
return &DiskDriveInfoCollector{
logger: log.With(logger, "collector", subsystem),
DiskInfo: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "info"),
"General drive information",
[]string{
"device_id",
"model",
"caption",
"name",
},
nil,
),
Status: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "status"),
"Status of the drive",
[]string{
"name", "status"},
nil,
),
Size: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "size"),
"Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector.",
[]string{"name"},
nil,
),
Partitions: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "partitions"),
"Number of partitions",
[]string{"name"},
nil,
),
Availability: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "availability"),
"Availability Status",
[]string{
"name", "availability"},
nil,
),
}, nil
}
type Win32_DiskDrive struct {
DeviceID string
Model string
Size uint64
Name string
Caption string
Partitions uint32
Status string
Availability uint16
}
var (
allDiskStatus = []string{
"OK",
"Error",
"Degraded",
"Unknown",
"Pred fail",
"Starting",
"Stopping",
"Service",
"Stressed",
"Nonrecover",
"No Contact",
"Lost Comm",
}
availMap = map[int]string{
1: "Other",
2: "Unknown",
3: "Running / Full Power",
4: "Warning",
5: "In Test",
6: "Not Applicable",
7: "Power Off",
8: "Off line",
9: "Off Duty",
10: "Degraded",
11: "Not Installed",
12: "Install Error",
13: "Power Save - Unknown",
14: "Power Save - Low Power Mode",
15: "Power Save - Standby",
16: "Power Cycle",
17: "Power Save - Warning",
18: "Paused",
19: "Not Ready",
20: "Not Configured",
21: "Quiesced",
}
)
// Collect sends the metric values for each metric to the provided prometheus Metric channel.
func (c *DiskDriveInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
_ = level.Error(c.logger).Log("msg", "failed collecting disk_drive_info metrics", "desc", desc, "err", err)
return err
}
return nil
}
func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_DiskDrive
if err := wmi.Query(win32DiskQuery, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
for _, disk := range dst {
ch <- prometheus.MustNewConstMetric(
c.DiskInfo,
prometheus.GaugeValue,
1.0,
strings.Trim(disk.DeviceID, "\\.\\"),
strings.TrimRight(disk.Model, " "),
strings.TrimRight(disk.Caption, " "),
strings.TrimRight(disk.Name, "\\.\\"),
)
for _, status := range allDiskStatus {
isCurrentState := 0.0
if status == disk.Status {
isCurrentState = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.Status,
prometheus.GaugeValue,
isCurrentState,
strings.Trim(disk.Name, "\\.\\"),
status,
)
}
ch <- prometheus.MustNewConstMetric(
c.Size,
prometheus.GaugeValue,
float64(disk.Size),
strings.Trim(disk.Name, "\\.\\"),
)
ch <- prometheus.MustNewConstMetric(
c.Partitions,
prometheus.GaugeValue,
float64(disk.Partitions),
strings.Trim(disk.Name, "\\.\\"),
)
for availNum, val := range availMap {
isCurrentState := 0.0
if availNum == int(disk.Availability) {
isCurrentState = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.Availability,
prometheus.GaugeValue,
isCurrentState,
strings.Trim(disk.Name, "\\.\\"),
val,
)
}
}
return nil, nil
}

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkDiskDriveCollector(b *testing.B) {
benchmarkCollector(b, "disk_drive", newDiskDriveInfoCollector)
}

View File

@@ -6,17 +6,16 @@ package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("dns", NewDNSCollector)
}
// A DNSCollector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics
type DNSCollector struct {
logger log.Logger
ZoneTransferRequestsReceived *prometheus.Desc
ZoneTransferRequestsSent *prometheus.Desc
ZoneTransferResponsesReceived *prometheus.Desc
@@ -41,10 +40,12 @@ type DNSCollector struct {
UnmatchedResponsesReceived *prometheus.Desc
}
// NewDNSCollector ...
func NewDNSCollector() (Collector, error) {
// newDNSCollector ...
func newDNSCollector(logger log.Logger) (Collector, error) {
const subsystem = "dns"
return &DNSCollector{
logger: log.With(logger, "collector", subsystem),
ZoneTransferRequestsReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_received_total"),
"Number of zone transfer requests (AXFR/IXFR) received by the master DNS server",
@@ -184,7 +185,7 @@ func NewDNSCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *DNSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting dns metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting dns metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -238,7 +239,7 @@ type Win32_PerfRawData_DNS_DNS struct {
func (c *DNSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_DNS_DNS
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkDNSCollector(b *testing.B) {
benchmarkCollector(b, "dns", NewDNSCollector)
benchmarkCollector(b, "dns", newDNSCollector)
}

View File

@@ -8,26 +8,20 @@ import (
"os"
"strings"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
)
func init() {
registerCollector("exchange", newExchangeCollector,
"MSExchange ADAccess Processes",
"MSExchangeTransport Queues",
"MSExchange HttpProxy",
"MSExchange ActiveSync",
"MSExchange Availability Service",
"MSExchange OWA",
"MSExchangeAutodiscover",
"MSExchange WorkloadManagement Workloads",
"MSExchange RpcClientAccess",
)
}
const (
FlagExchangeListAllCollectors = "collectors.exchange.list"
FlagExchangeCollectorsEnabled = "collectors.exchange.enabled"
)
type exchangeCollector struct {
logger log.Logger
LDAPReadTime *prometheus.Desc
LDAPSearchTime *prometheus.Desc
LDAPWriteTime *prometheus.Desc
@@ -83,19 +77,27 @@ var (
"RpcClientAccess",
}
argExchangeListAllCollectors = kingpin.Flag(
"collectors.exchange.list",
argExchangeListAllCollectors *bool
argExchangeCollectorsEnabled *string
)
// newExchangeCollectorFlags ...
func newExchangeCollectorFlags(app *kingpin.Application) {
argExchangeListAllCollectors = app.Flag(
FlagExchangeListAllCollectors,
"List the collectors along with their perflib object name/ids",
).Bool()
argExchangeCollectorsEnabled = kingpin.Flag(
"collectors.exchange.enabled",
argExchangeCollectorsEnabled = app.Flag(
FlagExchangeCollectorsEnabled,
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default("").String()
)
}
// newExchangeCollector returns a new Collector
func newExchangeCollector() (Collector, error) {
func newExchangeCollector(logger log.Logger) (Collector, error) {
const subsystem = "exchange"
// desc creates a new prometheus description
desc := func(metricName string, description string, labels ...string) *prometheus.Desc {
@@ -108,6 +110,8 @@ func newExchangeCollector() (Collector, error) {
}
c := exchangeCollector{
logger: log.With(logger, "collector", subsystem),
RPCAveragedLatency: desc("rpc_avg_latency_sec", "The latency (sec), averaged for the past 1024 packets"),
RPCRequests: desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service"),
ActiveUserCount: desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes"),
@@ -203,7 +207,7 @@ func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Met
for _, collectorName := range c.enabledCollectors {
if err := collectorFuncs[collectorName](ctx, ch); err != nil {
log.Errorf("Error in %s: %s", collectorName, err)
_ = level.Error(c.logger).Log("msg", "Error in "+collectorName, "err", err)
return err
}
}
@@ -223,7 +227,7 @@ type perflibADAccessProcesses struct {
func (c *exchangeCollector) collectADAccessProcesses(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibADAccessProcesses
if err := unmarshalObject(ctx.perfObjects["MSExchange ADAccess Processes"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchange ADAccess Processes"], &data, c.logger); err != nil {
return err
}
@@ -281,7 +285,7 @@ type perflibAvailabilityService struct {
func (c *exchangeCollector) collectAvailabilityService(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibAvailabilityService
if err := unmarshalObject(ctx.perfObjects["MSExchange Availability Service"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchange Availability Service"], &data, c.logger); err != nil {
return err
}
@@ -309,7 +313,7 @@ type perflibHTTPProxy struct {
func (c *exchangeCollector) collectHTTPProxy(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibHTTPProxy
if err := unmarshalObject(ctx.perfObjects["MSExchange HttpProxy"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchange HttpProxy"], &data, c.logger); err != nil {
return err
}
@@ -363,7 +367,7 @@ type perflibOWA struct {
func (c *exchangeCollector) collectOWA(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibOWA
if err := unmarshalObject(ctx.perfObjects["MSExchange OWA"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchange OWA"], &data, c.logger); err != nil {
return err
}
@@ -391,7 +395,7 @@ type perflibActiveSync struct {
func (c *exchangeCollector) collectActiveSync(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibActiveSync
if err := unmarshalObject(ctx.perfObjects["MSExchange ActiveSync"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchange ActiveSync"], &data, c.logger); err != nil {
return err
}
@@ -427,7 +431,7 @@ type perflibRPCClientAccess struct {
func (c *exchangeCollector) collectRPC(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibRPCClientAccess
if err := unmarshalObject(ctx.perfObjects["MSExchange RpcClientAccess"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchange RpcClientAccess"], &data, c.logger); err != nil {
return err
}
@@ -483,7 +487,7 @@ type perflibTransportQueues struct {
func (c *exchangeCollector) collectTransportQueues(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibTransportQueues
if err := unmarshalObject(ctx.perfObjects["MSExchangeTransport Queues"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchangeTransport Queues"], &data, c.logger); err != nil {
return err
}
@@ -557,7 +561,7 @@ type perflibWorkloadManagementWorkloads struct {
func (c *exchangeCollector) collectWorkloadManagementWorkloads(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibWorkloadManagementWorkloads
if err := unmarshalObject(ctx.perfObjects["MSExchange WorkloadManagement Workloads"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchange WorkloadManagement Workloads"], &data, c.logger); err != nil {
return err
}
@@ -608,7 +612,7 @@ type perflibAutodiscover struct {
func (c *exchangeCollector) collectAutoDiscover(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var data []perflibAutodiscover
if err := unmarshalObject(ctx.perfObjects["MSExchangeAutodiscover"], &data); err != nil {
if err := unmarshalObject(ctx.perfObjects["MSExchangeAutodiscover"], &data, c.logger); err != nil {
return err
}
for _, autodisc := range data {

View File

@@ -1,16 +1,15 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("fsrmquota", newFSRMQuotaCollector)
}
type FSRMQuotaCollector struct {
logger log.Logger
QuotasCount *prometheus.Desc
Path *prometheus.Desc
PeakUsage *prometheus.Desc
@@ -24,9 +23,11 @@ type FSRMQuotaCollector struct {
Template *prometheus.Desc
}
func newFSRMQuotaCollector() (Collector, error) {
func newFSRMQuotaCollector(logger log.Logger) (Collector, error) {
const subsystem = "fsrmquota"
return &FSRMQuotaCollector{
logger: log.With(logger, "collector", subsystem),
QuotasCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "count"),
"Number of Quotas",
@@ -88,7 +89,7 @@ func newFSRMQuotaCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *FSRMQuotaCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting fsrmquota metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting fsrmquota metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -113,7 +114,7 @@ type MSFT_FSRMQuota struct {
func (c *FSRMQuotaCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []MSFT_FSRMQuota
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
var count int

View File

@@ -4,19 +4,19 @@
package collector
import (
fmt "fmt"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("hyperv", NewHyperVCollector)
}
// HyperVCollector is a Prometheus collector for hyper-v
type HyperVCollector struct {
logger log.Logger
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
HealthCritical *prometheus.Desc
HealthOk *prometheus.Desc
@@ -130,10 +130,13 @@ type HyperVCollector struct {
VMMemoryRemovedMemory *prometheus.Desc
}
// NewHyperVCollector ...
func NewHyperVCollector() (Collector, error) {
// newHyperVCollector ...
func newHyperVCollector(logger log.Logger) (Collector, error) {
const subsystem = "hyperv"
buildSubsystemName := func(component string) string { return "hyperv_" + component }
return &HyperVCollector{
logger: log.With(logger, "collector", subsystem),
HealthCritical: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("health"), "critical"),
"This counter represents the number of virtual machines with critical health",
@@ -701,62 +704,62 @@ func NewHyperVCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *HyperVCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collectVmHealth(ch); err != nil {
log.Error("failed collecting hyperV health status metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV health status metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmVid(ch); err != nil {
log.Error("failed collecting hyperV pages metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV pages metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmHv(ch); err != nil {
log.Error("failed collecting hyperV hv status metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV hv status metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmProcessor(ch); err != nil {
log.Error("failed collecting hyperV processor metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV processor metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectHostLPUsage(ch); err != nil {
log.Error("failed collecting hyperV host logical processors metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV host logical processors metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectHostCpuUsage(ch); err != nil {
log.Error("failed collecting hyperV host CPU metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV host CPU metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmCpuUsage(ch); err != nil {
log.Error("failed collecting hyperV VM CPU metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV VM CPU metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmSwitch(ch); err != nil {
log.Error("failed collecting hyperV switch metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV switch metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmEthernet(ch); err != nil {
log.Error("failed collecting hyperV ethernet metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV ethernet metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmStorage(ch); err != nil {
log.Error("failed collecting hyperV virtual storage metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV virtual storage metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmNetwork(ch); err != nil {
log.Error("failed collecting hyperV virtual network metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV virtual network metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectVmMemory(ch); err != nil {
log.Error("failed collecting hyperV virtual memory metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting hyperV virtual memory metrics", "desc", desc, "err", err)
return err
}
@@ -771,7 +774,7 @@ type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
func (c *HyperVCollector) collectVmHealth(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -804,7 +807,7 @@ type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct {
func (c *HyperVCollector) collectVmVid(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -868,7 +871,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct {
func (c *HyperVCollector) collectVmHv(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1006,7 +1009,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisor struct {
func (c *HyperVCollector) collectVmProcessor(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_HvStats_HyperVHypervisor
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1040,7 +1043,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct {
func (c *HyperVCollector) collectHostLPUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1052,7 +1055,7 @@ func (c *HyperVCollector) collectHostLPUsage(ch chan<- prometheus.Metric) (*prom
// The name format is Hv LP <core id>
parts := strings.Split(obj.Name, " ")
if len(parts) != 3 {
log.Warnf("Unexpected format of Name in collectHostLPUsage: %q", obj.Name)
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Unexpected format of Name in collectHostLPUsage: %q", obj.Name))
continue
}
coreId := parts[2]
@@ -1094,7 +1097,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct {
func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1106,7 +1109,7 @@ func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*pro
// The name format is Root VP <core id>
parts := strings.Split(obj.Name, " ")
if len(parts) != 3 {
log.Warnf("Unexpected format of Name in collectHostCpuUsage: %q", obj.Name)
_ = level.Warn(c.logger).Log("msg", "Unexpected format of Name in collectHostCpuUsage: "+obj.Name)
continue
}
coreId := parts[2]
@@ -1155,7 +1158,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct {
func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1167,12 +1170,12 @@ func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prome
// The name format is <VM Name>:Hv VP <vcore id>
parts := strings.Split(obj.Name, ":")
if len(parts) != 2 {
log.Warnf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, "<VM Name>:Hv VP <vcore id>")
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, "<VM Name>:Hv VP <vcore id>"))
continue
}
coreParts := strings.Split(parts[1], " ")
if len(coreParts) != 3 {
log.Warnf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP <vcore id>")
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP <vcore id>"))
continue
}
vmName := parts[0]
@@ -1242,7 +1245,7 @@ type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct {
func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1377,6 +1380,12 @@ func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometh
float64(obj.PacketsReceivedPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsSent,
prometheus.CounterValue,
float64(obj.PacketsSentPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.PurgedMacAddresses,
prometheus.CounterValue,
@@ -1401,7 +1410,7 @@ type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct {
func (c *HyperVCollector) collectVmEthernet(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1471,7 +1480,7 @@ type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct {
func (c *HyperVCollector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1540,7 +1549,7 @@ type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct {
func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -1613,7 +1622,7 @@ type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct {
func (c *HyperVCollector) collectVmMemory(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkHypervCollector(b *testing.B) {
benchmarkCollector(b, "hyperv", NewHyperVCollector)
benchmarkCollector(b, "hyperv", newHyperVCollector)
}

View File

@@ -4,24 +4,46 @@
package collector
import (
"errors"
"fmt"
"regexp"
"sort"
"strings"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows/registry"
"gopkg.in/alecthomas/kingpin.v2"
)
func init() {
registerCollector("iis", NewIISCollector, "Web Service", "APP_POOL_WAS", "Web Service Cache", "W3SVC_W3WP")
}
const (
FlagIISSiteOldExclude = "collector.iis.site-blacklist"
FlagIISSiteOldInclude = "collector.iis.site-whitelist"
FlagIISAppOldExclude = "collector.iis.app-blacklist"
FlagIISAppOldInclude = "collector.iis.app-whitelist"
FlagIISSiteExclude = "collector.iis.site-exclude"
FlagIISSiteInclude = "collector.iis.site-include"
FlagIISAppExclude = "collector.iis.app-exclude"
FlagIISAppInclude = "collector.iis.app-include"
)
var (
siteWhitelist = kingpin.Flag("collector.iis.site-whitelist", "Regexp of sites to whitelist. Site name must both match whitelist and not match blacklist to be included.").Default(".+").String()
siteBlacklist = kingpin.Flag("collector.iis.site-blacklist", "Regexp of sites to blacklist. Site name must both match whitelist and not match blacklist to be included.").String()
appWhitelist = kingpin.Flag("collector.iis.app-whitelist", "Regexp of apps to whitelist. App name must both match whitelist and not match blacklist to be included.").Default(".+").String()
appBlacklist = kingpin.Flag("collector.iis.app-blacklist", "Regexp of apps to blacklist. App name must both match whitelist and not match blacklist to be included.").String()
oldSiteInclude *string
oldSiteExclude *string
oldAppInclude *string
oldAppExclude *string
siteInclude *string
siteExclude *string
appInclude *string
appExclude *string
siteIncludeSet bool
siteExcludeSet bool
appIncludeSet bool
appExcludeSet bool
)
type simple_version struct {
@@ -29,31 +51,31 @@ type simple_version struct {
minor uint64
}
func getIISVersion() simple_version {
func getIISVersion(logger log.Logger) simple_version {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE)
if err != nil {
log.Warn("Couldn't open registry to determine IIS version:", err)
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simple_version{}
}
defer func() {
err = k.Close()
if err != nil {
log.Warnf("Failed to close registry key: %v", err)
_ = level.Warn(logger).Log("msg", fmt.Sprintf("Failed to close registry key"), "err", err)
}
}()
major, _, err := k.GetIntegerValue("MajorVersion")
if err != nil {
log.Warn("Couldn't open registry to determine IIS version:", err)
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simple_version{}
}
minor, _, err := k.GetIntegerValue("MinorVersion")
if err != nil {
log.Warn("Couldn't open registry to determine IIS version:", err)
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine IIS version", "err", err)
return simple_version{}
}
log.Debugf("Detected IIS %d.%d\n", major, minor)
_ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected IIS %d.%d\n", major, minor))
return simple_version{
major: major,
@@ -62,6 +84,8 @@ func getIISVersion() simple_version {
}
type IISCollector struct {
logger log.Logger
// Web Service
CurrentAnonymousUsers *prometheus.Desc
CurrentBlockedAsyncIORequests *prometheus.Desc
@@ -86,8 +110,8 @@ type IISCollector struct {
TotalNotFoundErrors *prometheus.Desc
TotalRejectedAsyncIORequests *prometheus.Desc
siteWhitelistPattern *regexp.Regexp
siteBlacklistPattern *regexp.Regexp
siteIncludePattern *regexp.Regexp
siteExcludePattern *regexp.Regexp
// APP_POOL_WAS
CurrentApplicationPoolState *prometheus.Desc
@@ -189,22 +213,97 @@ type IISCollector struct {
ServiceCache_OutputCacheFlushedItemsTotal *prometheus.Desc
ServiceCache_OutputCacheFlushesTotal *prometheus.Desc
appWhitelistPattern *regexp.Regexp
appBlacklistPattern *regexp.Regexp
appIncludePattern *regexp.Regexp
appExcludePattern *regexp.Regexp
iis_version simple_version
}
func NewIISCollector() (Collector, error) {
func newIISCollectorFlags(app *kingpin.Application) {
oldSiteInclude = app.Flag(FlagIISSiteOldInclude, "DEPRECATED: Use --collector.iis.site-include").Default(".+").Hidden().String()
oldSiteExclude = app.Flag(FlagIISSiteOldExclude, "DEPRECATED: Use --collector.iis.site-exclude").Hidden().String()
oldAppInclude = app.Flag(FlagIISAppOldInclude, "DEPRECATED: Use --collector.iis.app-include").Hidden().String()
oldAppExclude = app.Flag(FlagIISAppOldExclude, "DEPRECATED: Use --collector.iis.app-exclude").Hidden().String()
siteInclude = app.Flag(
FlagIISSiteInclude,
"Regexp of sites to include. Site name must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
siteIncludeSet = true
return nil
}).String()
siteExclude = app.Flag(
FlagIISSiteExclude,
"Regexp of sites to exclude. Site name must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
siteExcludeSet = true
return nil
}).String()
appInclude = app.Flag(
FlagIISAppInclude,
"Regexp of apps to include. App name must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
appIncludeSet = true
return nil
}).String()
appExclude = app.Flag(
FlagIISAppExclude,
"Regexp of apps to include. App name must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
siteExcludeSet = true
return nil
}).String()
}
func newIISCollector(logger log.Logger) (Collector, error) {
const subsystem = "iis"
logger = log.With(logger, "collector", subsystem)
if *oldSiteExclude != "" {
if !siteExcludeSet {
_ = level.Warn(logger).Log("msg", "--collector.iis.site-blacklist is DEPRECATED and will be removed in a future release, use --collector.iis.site-exclude")
*siteExclude = *oldSiteExclude
} else {
return nil, errors.New("--collector.iis.site-blacklist and --collector.iis.site-exclude are mutually exclusive")
}
}
if *oldSiteInclude != "" {
if !siteIncludeSet {
_ = level.Warn(logger).Log("msg", "--collector.iis.site-whitelist is DEPRECATED and will be removed in a future release, use --collector.iis.site-include")
*siteInclude = *oldSiteInclude
} else {
return nil, errors.New("--collector.iis.site-whitelist and --collector.iis.site-include are mutually exclusive")
}
}
if *oldAppExclude != "" {
if !appExcludeSet {
_ = level.Warn(logger).Log("msg", "--collector.iis.app-blacklist is DEPRECATED and will be removed in a future release, use --collector.iis.app-exclude")
*appExclude = *oldAppExclude
} else {
return nil, errors.New("--collector.iis.app-blacklist and --collector.iis.app-exclude are mutually exclusive")
}
}
if *oldAppInclude != "" {
if !appIncludeSet {
_ = level.Warn(logger).Log("msg", "--collector.iis.app-whitelist is DEPRECATED and will be removed in a future release, use --collector.iis.app-include")
*appInclude = *oldAppInclude
} else {
return nil, errors.New("--collector.iis.app-whitelist and --collector.iis.app-include are mutually exclusive")
}
}
return &IISCollector{
iis_version: getIISVersion(),
logger: logger,
iis_version: getIISVersion(logger),
siteWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *siteWhitelist)),
siteBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *siteBlacklist)),
appWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *appWhitelist)),
appBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *appBlacklist)),
siteIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *siteInclude)),
siteExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *siteExclude)),
appIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *appInclude)),
appExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *appExclude)),
// Web Service
CurrentAnonymousUsers: prometheus.NewDesc(
@@ -821,22 +920,22 @@ func NewIISCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *IISCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collectWebService(ctx, ch); err != nil {
log.Error("failed collecting iis metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting iis metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectAPP_POOL_WAS(ctx, ch); err != nil {
log.Error("failed collecting iis metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting iis metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectW3SVC_W3WP(ctx, ch); err != nil {
log.Error("failed collecting iis metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting iis metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectWebServiceCache(ctx, ch); err != nil {
log.Error("failed collecting iis metrics:", desc, err)
_ = level.Error(c.logger).Log("msg", "failed collecting iis metrics", "desc", desc, "err", err)
return err
}
@@ -886,14 +985,63 @@ type perflibWebService struct {
TotalUnlockRequests float64 `perflib:"Total Unlock Requests"`
}
// Fulfill the hasGetIISName interface
func (p perflibWebService) getIISName() string {
return p.Name
}
// Fulfill the hasGetIISName interface
func (p perflibAPP_POOL_WAS) getIISName() string {
return p.Name
}
// Fulfill the hasGetIISName interface
func (p perflibW3SVC_W3WP) getIISName() string {
return p.Name
}
// Fulfill the hasGetIISName interface
func (p perflibW3SVC_W3WP_IIS8) getIISName() string {
return p.Name
}
// Required as Golang doesn't allow access to struct fields in generic functions. That restriction may be removed in a future release.
type hasGetIISName interface {
getIISName() string
}
// Deduplicate IIS site names from various IIS perflib objects.
//
// E.G. Given the following list of site names, "Site_B" would be
// discarded, and "Site_B#2" would be kept and presented as "Site_B" in the
// collector metrics.
// [ "Site_A", "Site_B", "Site_C", "Site_B#2" ]
func dedupIISNames[V hasGetIISName](services []V) map[string]V {
// Ensure IIS entry with the highest suffix occurs last
sort.SliceStable(services, func(i, j int) bool {
return services[i].getIISName() < services[j].getIISName()
})
var webServiceDeDuplicated = make(map[string]V)
// Use map to deduplicate IIS entries
for _, entry := range services {
name := strings.Split(entry.getIISName(), "#")[0]
webServiceDeDuplicated[name] = entry
}
return webServiceDeDuplicated
}
func (c *IISCollector) collectWebService(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var WebService []perflibWebService
if err := unmarshalObject(ctx.perfObjects["Web Service"], &WebService); err != nil {
var webService []perflibWebService
if err := unmarshalObject(ctx.perfObjects["Web Service"], &webService, c.logger); err != nil {
return nil, err
}
for _, app := range WebService {
if app.Name == "_Total" || c.siteBlacklistPattern.MatchString(app.Name) || !c.siteWhitelistPattern.MatchString(app.Name) {
webServiceDeDuplicated := dedupIISNames(webService)
for name, app := range webServiceDeDuplicated {
if name == "_Total" || c.siteExcludePattern.MatchString(name) || !c.siteIncludePattern.MatchString(name) {
continue
}
@@ -901,238 +1049,238 @@ func (c *IISCollector) collectWebService(ctx *ScrapeContext, ch chan<- prometheu
c.CurrentAnonymousUsers,
prometheus.GaugeValue,
app.CurrentAnonymousUsers,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.CurrentBlockedAsyncIORequests,
prometheus.GaugeValue,
app.CurrentBlockedAsyncIORequests,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.CurrentCGIRequests,
prometheus.GaugeValue,
app.CurrentCGIRequests,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.CurrentConnections,
prometheus.GaugeValue,
app.CurrentConnections,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.CurrentISAPIExtensionRequests,
prometheus.GaugeValue,
app.CurrentISAPIExtensionRequests,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.CurrentNonAnonymousUsers,
prometheus.GaugeValue,
app.CurrentNonAnonymousUsers,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.ServiceUptime,
prometheus.GaugeValue,
app.ServiceUptime,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalBytesReceived,
prometheus.CounterValue,
app.TotalBytesReceived,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalBytesSent,
prometheus.CounterValue,
app.TotalBytesSent,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalAnonymousUsers,
prometheus.CounterValue,
app.TotalAnonymousUsers,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalBlockedAsyncIORequests,
prometheus.CounterValue,
app.TotalBlockedAsyncIORequests,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalCGIRequests,
prometheus.CounterValue,
app.TotalCGIRequests,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalConnectionAttemptsAllInstances,
prometheus.CounterValue,
app.TotalConnectionAttemptsAllInstances,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalFilesReceived,
prometheus.CounterValue,
app.TotalFilesReceived,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalFilesSent,
prometheus.CounterValue,
app.TotalFilesSent,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalISAPIExtensionRequests,
prometheus.CounterValue,
app.TotalISAPIExtensionRequests,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalLockedErrors,
prometheus.CounterValue,
app.TotalLockedErrors,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalLogonAttempts,
prometheus.CounterValue,
app.TotalLogonAttempts,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalNonAnonymousUsers,
prometheus.CounterValue,
app.TotalNonAnonymousUsers,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalNotFoundErrors,
prometheus.CounterValue,
app.TotalNotFoundErrors,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalRejectedAsyncIORequests,
prometheus.CounterValue,
app.TotalRejectedAsyncIORequests,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalOtherRequests,
app.Name,
name,
"other",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalCopyRequests,
app.Name,
name,
"COPY",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalDeleteRequests,
app.Name,
name,
"DELETE",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalGetRequests,
app.Name,
name,
"GET",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalHeadRequests,
app.Name,
name,
"HEAD",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalLockRequests,
app.Name,
name,
"LOCK",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalMkcolRequests,
app.Name,
name,
"MKCOL",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalMoveRequests,
app.Name,
name,
"MOVE",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalOptionsRequests,
app.Name,
name,
"OPTIONS",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalPostRequests,
app.Name,
name,
"POST",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalPropfindRequests,
app.Name,
name,
"PROPFIND",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalProppatchRequests,
app.Name,
name,
"PROPPATCH",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalPutRequests,
app.Name,
name,
"PUT",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalSearchRequests,
app.Name,
name,
"SEARCH",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalTraceRequests,
app.Name,
name,
"TRACE",
)
ch <- prometheus.MustNewConstMetric(
c.TotalRequests,
prometheus.CounterValue,
app.TotalUnlockRequests,
app.Name,
name,
"UNLOCK",
)
}
@@ -1172,14 +1320,16 @@ var applicationStates = map[uint32]string{
func (c *IISCollector) collectAPP_POOL_WAS(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var APP_POOL_WAS []perflibAPP_POOL_WAS
if err := unmarshalObject(ctx.perfObjects["APP_POOL_WAS"], &APP_POOL_WAS); err != nil {
if err := unmarshalObject(ctx.perfObjects["APP_POOL_WAS"], &APP_POOL_WAS, c.logger); err != nil {
return nil, err
}
for _, app := range APP_POOL_WAS {
if app.Name == "_Total" ||
c.appBlacklistPattern.MatchString(app.Name) ||
!c.appWhitelistPattern.MatchString(app.Name) {
appPoolDeDuplicated := dedupIISNames(APP_POOL_WAS)
for name, app := range appPoolDeDuplicated {
if name == "_Total" ||
c.appExcludePattern.MatchString(name) ||
!c.appIncludePattern.MatchString(name) {
continue
}
@@ -1192,7 +1342,7 @@ func (c *IISCollector) collectAPP_POOL_WAS(ctx *ScrapeContext, ch chan<- prometh
c.CurrentApplicationPoolState,
prometheus.GaugeValue,
isCurrentState,
app.Name,
name,
label,
)
}
@@ -1201,73 +1351,73 @@ func (c *IISCollector) collectAPP_POOL_WAS(ctx *ScrapeContext, ch chan<- prometh
c.CurrentApplicationPoolUptime,
prometheus.GaugeValue,
app.CurrentApplicationPoolUptime,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.CurrentWorkerProcesses,
prometheus.GaugeValue,
app.CurrentWorkerProcesses,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.MaximumWorkerProcesses,
prometheus.GaugeValue,
app.MaximumWorkerProcesses,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.RecentWorkerProcessFailures,
prometheus.GaugeValue,
app.RecentWorkerProcessFailures,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TimeSinceLastWorkerProcessFailure,
prometheus.GaugeValue,
app.TimeSinceLastWorkerProcessFailure,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalApplicationPoolRecycles,
prometheus.CounterValue,
app.TotalApplicationPoolRecycles,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalApplicationPoolUptime,
prometheus.CounterValue,
app.TotalApplicationPoolUptime,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalWorkerProcessesCreated,
prometheus.CounterValue,
app.TotalWorkerProcessesCreated,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalWorkerProcessFailures,
prometheus.CounterValue,
app.TotalWorkerProcessFailures,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalWorkerProcessPingFailures,
prometheus.CounterValue,
app.TotalWorkerProcessPingFailures,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalWorkerProcessShutdownFailures,
prometheus.CounterValue,
app.TotalWorkerProcessShutdownFailures,
app.Name,
name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalWorkerProcessStartupFailures,
prometheus.CounterValue,
app.TotalWorkerProcessStartupFailures,
app.Name,
name,
)
}
@@ -1347,17 +1497,24 @@ type perflibW3SVC_W3WP_IIS8 struct {
func (c *IISCollector) collectW3SVC_W3WP(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var W3SVC_W3WP []perflibW3SVC_W3WP
if err := unmarshalObject(ctx.perfObjects["W3SVC_W3WP"], &W3SVC_W3WP); err != nil {
if err := unmarshalObject(ctx.perfObjects["W3SVC_W3WP"], &W3SVC_W3WP, c.logger); err != nil {
return nil, err
}
for _, app := range W3SVC_W3WP {
w3svcW3WPDeduplicated := dedupIISNames(W3SVC_W3WP)
for w3Name, app := range w3svcW3WPDeduplicated {
// Extract the apppool name from the format <PID>_<NAME>
pid := workerProcessNameExtractor.ReplaceAllString(app.Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(app.Name, "$2")
pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2")
if name == "" || name == "_Total" ||
c.appBlacklistPattern.MatchString(name) ||
!c.appWhitelistPattern.MatchString(name) {
c.appExcludePattern.MatchString(name) ||
!c.appIncludePattern.MatchString(name) {
continue
}
// Duplicate instances are suffixed # with an index number. These should be ignored
if strings.Contains(app.Name, "#") {
continue
}
@@ -1599,17 +1756,19 @@ func (c *IISCollector) collectW3SVC_W3WP(ctx *ScrapeContext, ch chan<- prometheu
if c.iis_version.major >= 8 {
var W3SVC_W3WP_IIS8 []perflibW3SVC_W3WP_IIS8
if err := unmarshalObject(ctx.perfObjects["W3SVC_W3WP"], &W3SVC_W3WP_IIS8); err != nil {
if err := unmarshalObject(ctx.perfObjects["W3SVC_W3WP"], &W3SVC_W3WP_IIS8, c.logger); err != nil {
return nil, err
}
for _, app := range W3SVC_W3WP_IIS8 {
w3svcW3WPIIS8Deduplicated := dedupIISNames(W3SVC_W3WP_IIS8)
for w3Name, app := range w3svcW3WPIIS8Deduplicated {
// Extract the apppool name from the format <PID>_<NAME>
pid := workerProcessNameExtractor.ReplaceAllString(app.Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(app.Name, "$2")
pid := workerProcessNameExtractor.ReplaceAllString(w3Name, "$1")
name := workerProcessNameExtractor.ReplaceAllString(w3Name, "$2")
if name == "" || name == "_Total" ||
c.appBlacklistPattern.MatchString(name) ||
!c.appWhitelistPattern.MatchString(name) {
c.appExcludePattern.MatchString(name) ||
!c.appIncludePattern.MatchString(name) {
continue
}
@@ -1736,7 +1895,7 @@ type perflibWebServiceCache struct {
func (c *IISCollector) collectWebServiceCache(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var WebServiceCache []perflibWebServiceCache
if err := unmarshalObject(ctx.perfObjects["Web Service Cache"], &WebServiceCache); err != nil {
if err := unmarshalObject(ctx.perfObjects["Web Service Cache"], &WebServiceCache, c.logger); err != nil {
return nil, err
}

View File

@@ -1,9 +1,49 @@
package collector
import (
"reflect"
"testing"
)
func BenchmarkIISCollector(b *testing.B) {
benchmarkCollector(b, "iis", NewIISCollector)
benchmarkCollector(b, "iis", newIISCollector)
}
func TestIISDeduplication(t *testing.T) {
start := []perflibAPP_POOL_WAS{
{
Name: "foo",
Frequency_Object: 1,
},
{
Name: "foo1#999",
Frequency_Object: 2,
},
{
Name: "foo#2",
Frequency_Object: 3,
},
{
Name: "bar$2",
Frequency_Object: 4,
},
{
Name: "bar_2",
Frequency_Object: 5,
},
}
var expected = make(map[string]perflibAPP_POOL_WAS)
// Should be deduplicated from "foo#2"
expected["foo"] = perflibAPP_POOL_WAS{Name: "foo#2", Frequency_Object: 3}
// Map key should have suffix stripped, but struct name field should be unchanged
expected["foo1"] = perflibAPP_POOL_WAS{Name: "foo1#999", Frequency_Object: 2}
// Map key and Name should be identical, as there is no suffix starting with "#"
expected["bar$2"] = perflibAPP_POOL_WAS{Name: "bar$2", Frequency_Object: 4}
// Map key and Name should be identical, as there is no suffix starting with "#"
expected["bar_2"] = perflibAPP_POOL_WAS{Name: "bar_2", Frequency_Object: 5}
deduplicated := dedupIISNames(start)
if !reflect.DeepEqual(expected, deduplicated) {
t.Errorf("Flattened values do not match!\nExpected result: %+v\nActual result: %+v", expected, deduplicated)
}
}

415
collector/init.go Normal file
View File

@@ -0,0 +1,415 @@
package collector
import (
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
)
// collectorInit represents the required initialisation config for a collector.
type collectorInit struct {
// Name of collector to be initialised
name string
// Builder function for the collector
flags flagsBuilder
// Builder function for the collector
builder collectorBuilder
// Perflib counter names for the collector.
// These will be included in the Perflib scrape scope by the exporter.
perfCounterFunc perfCounterNamesBuilder
}
func getDFSRCollectorDeps(_ log.Logger) []string {
// Perflib sources are dynamic, depending on the enabled child collectors
var perflibDependencies []string
for _, source := range expandEnabledChildCollectors(*dfsrEnabledCollectors) {
perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source))
}
return perflibDependencies
}
var collectors = []collectorInit{
{
name: "ad",
flags: nil,
builder: newADCollector,
perfCounterFunc: nil,
},
{
name: "adcs",
flags: nil,
builder: adcsCollectorMethod,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"Certification Authority"}
},
},
{
name: "adfs",
flags: nil,
builder: newADFSCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"AD FS"}
},
},
{
name: "cache",
flags: nil,
builder: newCacheCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"Cache"}
},
},
{
name: "container",
flags: nil,
builder: newContainerMetricsCollector,
perfCounterFunc: nil,
},
{
name: "cpu",
flags: nil,
builder: newCPUCollector,
perfCounterFunc: func(logger log.Logger) []string {
if getWindowsVersion(logger) > 6.05 {
return []string{"Processor Information"}
}
return []string{"Processor"}
},
},
{
name: "cpu_info",
flags: nil,
builder: newCpuInfoCollector,
perfCounterFunc: nil,
},
{
name: "cs",
flags: nil,
builder: newCSCollector,
perfCounterFunc: nil,
},
{
name: "dfsr",
flags: newDFSRCollectorFlags,
builder: newDFSRCollector,
perfCounterFunc: getDFSRCollectorDeps,
},
{
name: "dhcp",
flags: nil,
builder: newDhcpCollector,
perfCounterFunc: nil,
},
{
name: "diskdrive",
flags: nil,
builder: newDiskDriveInfoCollector,
perfCounterFunc: nil,
},
{
name: "dns",
flags: nil,
builder: newDNSCollector,
perfCounterFunc: nil,
},
{
name: "exchange",
flags: newExchangeCollectorFlags,
builder: newExchangeCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{
"MSExchange ADAccess Processes",
"MSExchangeTransport Queues",
"MSExchange HttpProxy",
"MSExchange ActiveSync",
"MSExchange Availability Service",
"MSExchange OWA",
"MSExchangeAutodiscover",
"MSExchange WorkloadManagement Workloads",
"MSExchange RpcClientAccess",
}
},
},
{
name: "fsrmquota",
flags: nil,
builder: newFSRMQuotaCollector,
perfCounterFunc: nil,
},
{
name: "hyperv",
flags: nil,
builder: newHyperVCollector,
perfCounterFunc: nil,
},
{
name: "iis",
flags: newIISCollectorFlags,
builder: newIISCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{
"Web Service",
"APP_POOL_WAS",
"Web Service Cache",
"W3SVC_W3WP",
}
},
},
{
name: "logical_disk",
flags: newLogicalDiskCollectorFlags,
builder: newLogicalDiskCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"LogicalDisk"}
},
},
{
name: "logon",
flags: nil,
builder: newLogonCollector,
perfCounterFunc: nil,
},
{
name: "memory",
flags: nil,
builder: newMemoryCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"Memory"}
},
},
{
name: "mscluster_cluster",
flags: nil,
builder: newMSCluster_ClusterCollector,
perfCounterFunc: nil,
},
{
name: "mscluster_network",
flags: nil,
builder: newMSCluster_NetworkCollector,
perfCounterFunc: nil,
},
{
name: "mscluster_node",
flags: nil,
builder: newMSCluster_NodeCollector,
perfCounterFunc: nil,
},
{
name: "mscluster_resource",
flags: nil,
builder: newMSCluster_ResourceCollector,
perfCounterFunc: nil,
},
{
name: "mscluster_resourcegroup",
flags: nil,
builder: newMSCluster_ResourceGroupCollector,
perfCounterFunc: nil,
},
{
name: "msmq",
flags: newMSMQCollectorFlags,
builder: newMSMQCollector,
perfCounterFunc: nil,
},
{
name: "mssql",
flags: newMSSQLCollectorFlags,
builder: newMSSQLCollector,
perfCounterFunc: nil,
},
{
name: "net",
flags: newNetworkCollectorFlags,
builder: newNetworkCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"Network Interface"}
},
},
{
name: "netframework_clrexceptions",
flags: nil,
builder: newNETFramework_NETCLRExceptionsCollector,
perfCounterFunc: nil,
},
{
name: "netframework_clrinterop",
flags: nil,
builder: newNETFramework_NETCLRInteropCollector,
perfCounterFunc: nil,
},
{
name: "netframework_clrjit",
flags: nil,
builder: newNETFramework_NETCLRJitCollector,
perfCounterFunc: nil,
},
{
name: "netframework_clrloading",
flags: nil,
builder: newNETFramework_NETCLRLoadingCollector,
perfCounterFunc: nil,
},
{
name: "netframework_clrlocksandthreads",
flags: nil,
builder: newNETFramework_NETCLRLocksAndThreadsCollector,
perfCounterFunc: nil,
},
{
name: "netframework_clrmemory",
flags: nil,
builder: newNETFramework_NETCLRMemoryCollector,
perfCounterFunc: nil,
},
{
name: "netframework_clrremoting",
flags: nil,
builder: newNETFramework_NETCLRRemotingCollector,
perfCounterFunc: nil,
},
{
name: "netframework_clrsecurity",
flags: nil,
builder: newNETFramework_NETCLRSecurityCollector,
perfCounterFunc: nil,
},
{
name: "nps",
builder: newNPSCollector,
perfCounterFunc: nil,
},
{
name: "os",
flags: nil,
builder: newOSCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"Paging File"}
},
},
{
name: "process",
flags: newProcessCollectorFlags,
builder: newProcessCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"Process"}
},
},
{
name: "remote_fx",
flags: nil,
builder: newRemoteFx,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"RemoteFX Network"}
},
},
{
name: "scheduled_task",
flags: newScheduledTaskFlags,
builder: newScheduledTask,
perfCounterFunc: nil,
},
{
name: "service",
flags: newServiceCollectorFlags,
builder: newserviceCollector,
perfCounterFunc: nil,
},
{
name: "smtp",
flags: newSMTPCollectorFlags,
builder: newSMTPCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"SMTP Server"}
},
},
{
name: "system",
flags: nil,
builder: newSystemCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"System"}
},
},
{
name: "teradici_pcoip",
flags: nil,
builder: newTeradiciPcoipCollector,
perfCounterFunc: nil,
},
{
name: "tcp",
flags: nil,
builder: newTCPCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"TCPv4"}
},
},
{
name: "terminal_services",
flags: nil,
builder: newTerminalServicesCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{
"Terminal Services",
"Terminal Services Session",
"Remote Desktop Connection Broker Counterset",
}
},
},
{
name: "textfile",
flags: newTextFileCollectorFlags,
builder: newTextFileCollector,
perfCounterFunc: nil,
},
{
name: "thermalzone",
flags: nil,
builder: newThermalZoneCollector,
perfCounterFunc: nil,
},
{
name: "time",
flags: nil,
builder: newTimeCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"Windows Time Service"}
},
},
{
name: "vmware",
flags: nil,
builder: newVmwareCollector,
perfCounterFunc: nil,
},
{
name: "vmware_blast",
flags: nil,
builder: newVmwareBlastCollector,
perfCounterFunc: nil,
},
}
// RegisterCollectorsFlags To be called by the exporter for collector initialisation before running app.Parse
func RegisterCollectorsFlags(app *kingpin.Application) {
for _, v := range collectors {
if v.flags != nil {
v.flags(app)
}
}
}
// RegisterCollectors To be called by the exporter for collector initialisation
func RegisterCollectors(logger log.Logger) {
for _, v := range collectors {
var perfCounterNames []string
if v.perfCounterFunc != nil {
perfCounterNames = v.perfCounterFunc(logger)
}
registerCollector(v.name, v.builder, perfCounterNames...)
}
}

View File

@@ -4,31 +4,39 @@
package collector
import (
"errors"
"fmt"
"regexp"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
)
func init() {
registerCollector("logical_disk", NewLogicalDiskCollector, "LogicalDisk")
}
const (
FlagLogicalDiskVolumeOldExclude = "collector.logical_disk.volume-blacklist"
FlagLogicalDiskVolumeOldInclude = "collector.logical_disk.volume-whitelist"
FlagLogicalDiskVolumeExclude = "collector.logical_disk.volume-exclude"
FlagLogicalDiskVolumeInclude = "collector.logical_disk.volume-include"
)
var (
volumeWhitelist = kingpin.Flag(
"collector.logical_disk.volume-whitelist",
"Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.",
).Default(".+").String()
volumeBlacklist = kingpin.Flag(
"collector.logical_disk.volume-blacklist",
"Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.",
).Default("").String()
volumeOldInclude *string
volumeOldExclude *string
volumeInclude *string
volumeExclude *string
volumeIncludeSet bool
volumeExcludeSet bool
)
// A LogicalDiskCollector is a Prometheus collector for perflib logicalDisk metrics
type LogicalDiskCollector struct {
logger log.Logger
RequestsQueued *prometheus.Desc
AvgReadQueue *prometheus.Desc
AvgWriteQueue *prometheus.Desc
@@ -46,15 +54,63 @@ type LogicalDiskCollector struct {
WriteLatency *prometheus.Desc
ReadWriteLatency *prometheus.Desc
volumeWhitelistPattern *regexp.Regexp
volumeBlacklistPattern *regexp.Regexp
volumeIncludePattern *regexp.Regexp
volumeExcludePattern *regexp.Regexp
}
// NewLogicalDiskCollector ...
func NewLogicalDiskCollector() (Collector, error) {
// newLogicalDiskCollectorFlags ...
func newLogicalDiskCollectorFlags(app *kingpin.Application) {
volumeInclude = app.Flag(
FlagLogicalDiskVolumeInclude,
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
volumeIncludeSet = true
return nil
}).String()
volumeExclude = app.Flag(
FlagLogicalDiskVolumeExclude,
"Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
volumeExcludeSet = true
return nil
}).String()
volumeOldInclude = app.Flag(
FlagLogicalDiskVolumeOldInclude,
"DEPRECATED: Use --collector.logical_disk.volume-include",
).Hidden().String()
volumeOldExclude = app.Flag(
FlagLogicalDiskVolumeOldExclude,
"DEPRECATED: Use --collector.logical_disk.volume-exclude",
).Hidden().String()
}
// newLogicalDiskCollector ...
func newLogicalDiskCollector(logger log.Logger) (Collector, error) {
const subsystem = "logical_disk"
logger = log.With(logger, "collector", subsystem)
if *volumeOldExclude != "" {
if !volumeExcludeSet {
_ = level.Warn(logger).Log("msg", "--collector.logical_disk.volume-blacklist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-exclude")
*volumeExclude = *volumeOldExclude
} else {
return nil, errors.New("--collector.logical_disk.volume-blacklist and --collector.logical_disk.volume-exclude are mutually exclusive")
}
}
if *volumeOldInclude != "" {
if !volumeIncludeSet {
_ = level.Warn(logger).Log("msg", "--collector.logical_disk.volume-whitelist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-include")
*volumeInclude = *volumeOldInclude
} else {
return nil, errors.New("--collector.logical_disk.volume-whitelist and --collector.logical_disk.volume-include are mutually exclusive")
}
}
return &LogicalDiskCollector{
logger: logger,
RequestsQueued: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "requests_queued"),
"The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)",
@@ -167,8 +223,8 @@ func NewLogicalDiskCollector() (Collector, error) {
nil,
),
volumeWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeWhitelist)),
volumeBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeBlacklist)),
volumeIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeInclude)),
volumeExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeExclude)),
}, nil
}
@@ -176,7 +232,7 @@ func NewLogicalDiskCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *LogicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting logical_disk metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting logical_disk metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -207,14 +263,14 @@ type logicalDisk struct {
func (c *LogicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []logicalDisk
if err := unmarshalObject(ctx.perfObjects["LogicalDisk"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["LogicalDisk"], &dst, c.logger); err != nil {
return nil, err
}
for _, volume := range dst {
if volume.Name == "_Total" ||
c.volumeBlacklistPattern.MatchString(volume.Name) ||
!c.volumeWhitelistPattern.MatchString(volume.Name) {
c.volumeExcludePattern.MatchString(volume.Name) ||
!c.volumeIncludePattern.MatchString(volume.Name) {
continue
}

View File

@@ -6,8 +6,8 @@ import (
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
localVolumeInclude := ".+"
volumeInclude = &localVolumeInclude
benchmarkCollector(b, "logical_disk", NewLogicalDiskCollector)
benchmarkCollector(b, "logical_disk", newLogicalDiskCollector)
}

View File

@@ -6,25 +6,25 @@ package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("logon", NewLogonCollector)
}
// A LogonCollector is a Prometheus collector for WMI metrics
type LogonCollector struct {
logger log.Logger
LogonType *prometheus.Desc
}
// NewLogonCollector ...
func NewLogonCollector() (Collector, error) {
// newLogonCollector ...
func newLogonCollector(logger log.Logger) (Collector, error) {
const subsystem = "logon"
return &LogonCollector{
logger: log.With(logger, "collector", subsystem),
LogonType: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "logon_type"),
"Number of active logon sessions (LogonSession.LogonType)",
@@ -38,7 +38,7 @@ func NewLogonCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *LogonCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting user metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting user metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -52,7 +52,7 @@ type Win32_LogonSession struct {
func (c *LogonCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_LogonSession
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkLogonCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewLogonCollector)
benchmarkCollector(b, "", newLogonCollector)
}

View File

@@ -7,16 +7,15 @@
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("memory", NewMemoryCollector, "Memory")
}
// A MemoryCollector is a Prometheus collector for perflib Memory metrics
type MemoryCollector struct {
logger log.Logger
AvailableBytes *prometheus.Desc
CacheBytes *prometheus.Desc
CacheBytesPeak *prometheus.Desc
@@ -51,11 +50,13 @@ type MemoryCollector struct {
WriteCopiesTotal *prometheus.Desc
}
// NewMemoryCollector ...
func NewMemoryCollector() (Collector, error) {
// newMemoryCollector ...
func newMemoryCollector(logger log.Logger) (Collector, error) {
const subsystem = "memory"
return &MemoryCollector{
logger: log.With(logger, "collector", subsystem),
AvailableBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "available_bytes"),
"The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+
@@ -267,7 +268,7 @@ func NewMemoryCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *MemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting memory metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting memory metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -312,7 +313,7 @@ type memory struct {
func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []memory
if err := unmarshalObject(ctx.perfObjects["Memory"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["Memory"], &dst, c.logger); err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkMemoryCollector(b *testing.B) {
benchmarkCollector(b, "memory", NewMemoryCollector)
benchmarkCollector(b, "memory", newMemoryCollector)
}

View File

@@ -1,16 +1,15 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("mscluster_cluster", newMSCluster_ClusterCollector)
}
// A MSCluster_ClusterCollector is a Prometheus collector for WMI MSCluster_Cluster metrics
type MSCluster_ClusterCollector struct {
logger log.Logger
AddEvictDelay *prometheus.Desc
AdminAccessPoint *prometheus.Desc
AutoAssignNodeSite *prometheus.Desc
@@ -90,9 +89,11 @@ type MSCluster_ClusterCollector struct {
WitnessRestartInterval *prometheus.Desc
}
func newMSCluster_ClusterCollector() (Collector, error) {
func newMSCluster_ClusterCollector(logger log.Logger) (Collector, error) {
const subsystem = "mscluster_cluster"
return &MSCluster_ClusterCollector{
logger: log.With(logger, "collector", subsystem),
AddEvictDelay: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "add_evict_delay"),
"Provides access to the cluster's AddEvictDelay property, which is the number a seconds that a new node is delayed after an eviction of another node.",
@@ -560,7 +561,6 @@ func newMSCluster_ClusterCollector() (Collector, error) {
// MSCluster_Cluster docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-cluster
//
type MSCluster_Cluster struct {
Name string
@@ -647,7 +647,7 @@ type MSCluster_Cluster struct {
// to the provided prometheus Metric channel.
func (c *MSCluster_ClusterCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []MSCluster_Cluster
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
return err
}

View File

@@ -1,16 +1,15 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("mscluster_network", newMSCluster_NetworkCollector)
}
// A MSCluster_NetworkCollector is a Prometheus collector for WMI MSCluster_Network metrics
type MSCluster_NetworkCollector struct {
logger log.Logger
Characteristics *prometheus.Desc
Flags *prometheus.Desc
Metric *prometheus.Desc
@@ -18,9 +17,11 @@ type MSCluster_NetworkCollector struct {
State *prometheus.Desc
}
func newMSCluster_NetworkCollector() (Collector, error) {
func newMSCluster_NetworkCollector(logger log.Logger) (Collector, error) {
const subsystem = "mscluster_network"
return &MSCluster_NetworkCollector{
logger: log.With(logger, "collector", subsystem),
Characteristics: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "characteristics"),
"Provides the characteristics of the network.",
@@ -56,7 +57,6 @@ func newMSCluster_NetworkCollector() (Collector, error) {
// MSCluster_Network docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
//
type MSCluster_Network struct {
Name string
@@ -71,7 +71,7 @@ type MSCluster_Network struct {
// to the provided prometheus Metric channel.
func (c *MSCluster_NetworkCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []MSCluster_Network
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
return err
}

View File

@@ -1,16 +1,15 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("mscluster_node", newMSCluster_NodeCollector)
}
// A MSCluster_NodeCollector is a Prometheus collector for WMI MSCluster_Node metrics
type MSCluster_NodeCollector struct {
logger log.Logger
BuildNumber *prometheus.Desc
Characteristics *prometheus.Desc
DetectedCloudPlatform *prometheus.Desc
@@ -27,9 +26,10 @@ type MSCluster_NodeCollector struct {
StatusInformation *prometheus.Desc
}
func newMSCluster_NodeCollector() (Collector, error) {
func newMSCluster_NodeCollector(logger log.Logger) (Collector, error) {
const subsystem = "mscluster_node"
return &MSCluster_NodeCollector{
logger: log.With(logger, "collector", subsystem),
BuildNumber: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "build_number"),
"Provides access to the node's BuildNumber property.",
@@ -119,7 +119,6 @@ func newMSCluster_NodeCollector() (Collector, error) {
// MSCluster_Node docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node
//
type MSCluster_Node struct {
Name string
@@ -143,7 +142,7 @@ type MSCluster_Node struct {
// to the provided prometheus Metric channel.
func (c *MSCluster_NodeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []MSCluster_Node
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
return err
}

View File

@@ -1,16 +1,15 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("mscluster_resource", newMSCluster_ResourceCollector)
}
// A MSCluster_ResourceCollector is a Prometheus collector for WMI MSCluster_Resource metrics
type MSCluster_ResourceCollector struct {
logger log.Logger
Characteristics *prometheus.Desc
DeadlockTimeout *prometheus.Desc
EmbeddedFailureAction *prometheus.Desc
@@ -29,9 +28,10 @@ type MSCluster_ResourceCollector struct {
Subclass *prometheus.Desc
}
func newMSCluster_ResourceCollector() (Collector, error) {
func newMSCluster_ResourceCollector(logger log.Logger) (Collector, error) {
const subsystem = "mscluster_resource"
return &MSCluster_ResourceCollector{
logger: log.With(logger, "collector", subsystem),
Characteristics: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "characteristics"),
"Provides the characteristics of the object.",
@@ -133,7 +133,6 @@ func newMSCluster_ResourceCollector() (Collector, error) {
// MSCluster_Resource docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource
//
type MSCluster_Resource struct {
Name string
Type string
@@ -161,7 +160,7 @@ type MSCluster_Resource struct {
// to the provided prometheus Metric channel.
func (c *MSCluster_ResourceCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []MSCluster_Resource
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
return err
}

View File

@@ -1,16 +1,15 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("mscluster_resourcegroup", newMSCluster_ResourceGroupCollector)
}
// A MSCluster_ResourceGroupCollector is a Prometheus collector for WMI MSCluster_ResourceGroup metrics
type MSCluster_ResourceGroupCollector struct {
logger log.Logger
AutoFailbackType *prometheus.Desc
Characteristics *prometheus.Desc
ColdStartSetting *prometheus.Desc
@@ -28,9 +27,10 @@ type MSCluster_ResourceGroupCollector struct {
State *prometheus.Desc
}
func newMSCluster_ResourceGroupCollector() (Collector, error) {
func newMSCluster_ResourceGroupCollector(logger log.Logger) (Collector, error) {
const subsystem = "mscluster_resourcegroup"
return &MSCluster_ResourceGroupCollector{
logger: log.With(logger, "collector", subsystem),
AutoFailbackType: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "auto_failback_type"),
"Provides access to the group's AutoFailbackType property.",
@@ -114,7 +114,6 @@ func newMSCluster_ResourceGroupCollector() (Collector, error) {
// MSCluster_ResourceGroup docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup
//
type MSCluster_ResourceGroup struct {
Name string
@@ -137,7 +136,7 @@ type MSCluster_ResourceGroup struct {
// to the provided prometheus Metric channel.
func (c *MSCluster_ResourceGroupCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []MSCluster_ResourceGroup
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
return err
}

View File

@@ -6,22 +6,25 @@ package collector
import (
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("msmq", NewMSMQCollector)
}
const (
FlagMsmqWhereClause = "collector.msmq.msmq-where"
)
var (
msmqWhereClause = kingpin.Flag("collector.msmq.msmq-where", "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").String()
msmqWhereClause *string
)
// A Win32_PerfRawData_MSMQ_MSMQQueueCollector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics
type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct {
logger log.Logger
BytesinJournalQueue *prometheus.Desc
BytesinQueue *prometheus.Desc
MessagesinJournalQueue *prometheus.Desc
@@ -30,15 +33,23 @@ type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct {
queryWhereClause string
}
// newMSMQCollectorFlags ..
func newMSMQCollectorFlags(app *kingpin.Application) {
msmqWhereClause = app.Flag(FlagMsmqWhereClause, "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").String()
}
// NewWin32_PerfRawData_MSMQ_MSMQQueueCollector ...
func NewMSMQCollector() (Collector, error) {
func newMSMQCollector(logger log.Logger) (Collector, error) {
const subsystem = "msmq"
logger = log.With(logger, "collector", subsystem)
if *msmqWhereClause == "" {
log.Warn("No where-clause specified for msmq collector. This will generate a very large number of metrics!")
_ = level.Warn(logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!")
}
return &Win32_PerfRawData_MSMQ_MSMQQueueCollector{
logger: logger,
BytesinJournalQueue: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_in_journal_queue"),
"Size of queue journal in bytes",
@@ -71,7 +82,7 @@ func NewMSMQCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting msmq metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting msmq metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -88,7 +99,7 @@ type Win32_PerfRawData_MSMQ_MSMQQueue struct {
func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_MSMQ_MSMQQueue
q := queryAllWhere(&dst, c.queryWhereClause)
q := queryAllWhere(&dst, c.queryWhereClause, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkMsmqCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewMSMQCollector)
benchmarkCollector(b, "", newMSMQCollector)
}

View File

@@ -11,27 +11,27 @@ import (
"sync"
"time"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows/registry"
"gopkg.in/alecthomas/kingpin.v2"
)
const (
FlagMssqlEnabledCollectors = "collectors.mssql.classes-enabled"
FlagMssqlPrintCollectors = "collectors.mssql.class-print"
)
var (
mssqlEnabledCollectors = kingpin.Flag(
"collectors.mssql.classes-enabled",
"Comma-separated list of mssql WMI classes to use.").
Default(mssqlAvailableClassCollectors()).String()
mssqlEnabledCollectors *string
mssqlPrintCollectors = kingpin.Flag(
"collectors.mssql.class-print",
"If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.",
).Bool()
mssqlPrintCollectors *bool
)
type mssqlInstancesType map[string]string
func getMSSQLInstances() mssqlInstancesType {
func getMSSQLInstances(logger log.Logger) mssqlInstancesType {
sqlInstances := make(mssqlInstancesType)
// in case querying the registry fails, return the default instance
@@ -41,19 +41,19 @@ func getMSSQLInstances() mssqlInstancesType {
regkey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.QUERY_VALUE)
if err != nil {
log.Warn("Couldn't open registry to determine SQL instances:", err)
_ = level.Warn(logger).Log("msg", "Couldn't open registry to determine SQL instances", "err", err)
return sqlDefaultInstance
}
defer func() {
err = k.Close()
if err != nil {
log.Warnf("Failed to close registry key: %v", err)
_ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err)
}
}()
instanceNames, err := k.ReadValueNames(0)
if err != nil {
log.Warnf("Can't ReadSubKeyNames %#v", err)
_ = level.Warn(logger).Log("msg", "Can't ReadSubKeyNames", "err", err)
return sqlDefaultInstance
}
@@ -63,7 +63,7 @@ func getMSSQLInstances() mssqlInstancesType {
}
}
log.Debugf("Detected MSSQL Instances: %#v\n", sqlInstances)
_ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected MSSQL Instances: %#v\n", sqlInstances))
return sqlInstances
}
@@ -129,12 +129,10 @@ func mssqlGetPerfObjectName(sqlInstance string, collector string) string {
return (prefix + suffix)
}
func init() {
registerCollector("mssql", NewMSSQLCollector)
}
// A MSSQLCollector is a Prometheus collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics
type MSSQLCollector struct {
logger log.Logger
// meta
mssqlScrapeDurationDesc *prometheus.Desc
mssqlScrapeSuccessDesc *prometheus.Desc
@@ -405,13 +403,26 @@ type MSSQLCollector struct {
mssqlChildCollectorFailure int
}
// NewMSSQLCollector ...
func NewMSSQLCollector() (Collector, error) {
// newMSSQLCollectorFlags ...
func newMSSQLCollectorFlags(app *kingpin.Application) {
mssqlEnabledCollectors = app.Flag(
FlagMssqlEnabledCollectors,
"Comma-separated list of mssql WMI classes to use.").
Default(mssqlAvailableClassCollectors()).String()
mssqlPrintCollectors = app.Flag(
FlagMssqlPrintCollectors,
"If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.",
).Bool()
}
// newMSSQLCollector ...
func newMSSQLCollector(logger log.Logger) (Collector, error) {
const subsystem = "mssql"
logger = log.With(logger, "collector", subsystem)
enabled := expandEnabledChildCollectors(*mssqlEnabledCollectors)
mssqlInstances := getMSSQLInstances()
mssqlInstances := getMSSQLInstances(logger)
perfCounters := make([]string, 0, len(mssqlInstances)*len(enabled))
for instance := range mssqlInstances {
for _, c := range enabled {
@@ -421,6 +432,7 @@ func NewMSSQLCollector() (Collector, error) {
addPerfCounterDependencies(subsystem, perfCounters)
mssqlCollector := MSSQLCollector{
logger: logger,
// meta
mssqlScrapeDurationDesc: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "collector_duration_seconds"),
@@ -1921,11 +1933,11 @@ func (c *MSSQLCollector) execute(ctx *ScrapeContext, name string, fn mssqlCollec
var success float64
if err != nil {
log.Errorf("mssql class collector %s failed after %fs: %s", name, duration.Seconds(), err)
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("mssql class collector %s failed after %fs", name, duration.Seconds()), "err", err)
success = 0
c.mssqlChildCollectorFailure++
} else {
log.Debugf("mssql class collector %s succeeded after %fs.", name, duration.Seconds())
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql class collector %s succeeded after %fs.", name, duration.Seconds()))
success = 1
}
ch <- prometheus.MustNewConstMetric(
@@ -2016,9 +2028,9 @@ type mssqlAccessMethods struct {
func (c *MSSQLCollector) collectAccessMethods(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlAccessMethods
log.Debugf("mssql_accessmethods collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_accessmethods collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "accessmethods")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "accessmethods")], &dst, c.logger); err != nil {
return nil, err
}
@@ -2351,9 +2363,9 @@ type mssqlAvailabilityReplica struct {
func (c *MSSQLCollector) collectAvailabilityReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlAvailabilityReplica
log.Debugf("mssql_availreplica collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_availreplica collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "availreplica")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "availreplica")], &dst, c.logger); err != nil {
return nil, err
}
@@ -2459,9 +2471,9 @@ type mssqlBufferManager struct {
func (c *MSSQLCollector) collectBufferManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlBufferManager
log.Debugf("mssql_bufman collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_bufman collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst, c.logger); err != nil {
return nil, err
}
@@ -2663,9 +2675,9 @@ type mssqlDatabaseReplica struct {
func (c *MSSQLCollector) collectDatabaseReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlDatabaseReplica
log.Debugf("mssql_dbreplica collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_dbreplica collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "dbreplica")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "dbreplica")], &dst, c.logger); err != nil {
return nil, err
}
@@ -2902,9 +2914,9 @@ type mssqlDatabases struct {
func (c *MSSQLCollector) collectDatabases(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlDatabases
log.Debugf("mssql_databases collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_databases collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "databases")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "databases")], &dst, c.logger); err != nil {
return nil, err
}
@@ -3284,9 +3296,9 @@ type mssqlGeneralStatistics struct {
func (c *MSSQLCollector) collectGeneralStatistics(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlGeneralStatistics
log.Debugf("mssql_genstats collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_genstats collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "genstats")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "genstats")], &dst, c.logger); err != nil {
return nil, err
}
@@ -3479,9 +3491,9 @@ type mssqlLocks struct {
func (c *MSSQLCollector) collectLocks(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlLocks
log.Debugf("mssql_locks collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_locks collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "locks")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "locks")], &dst, c.logger); err != nil {
return nil, err
}
@@ -3577,9 +3589,9 @@ type mssqlMemoryManager struct {
func (c *MSSQLCollector) collectMemoryManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlMemoryManager
log.Debugf("mssql_memmgr collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_memmgr collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "memmgr")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "memmgr")], &dst, c.logger); err != nil {
return nil, err
}
@@ -3746,9 +3758,9 @@ type mssqlSQLStatistics struct {
func (c *MSSQLCollector) collectSQLStats(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlSQLStatistics
log.Debugf("mssql_sqlstats collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_sqlstats collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlstats")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlstats")], &dst, c.logger); err != nil {
return nil, err
}
@@ -3854,9 +3866,9 @@ type mssqlWaitStatistics struct {
func (c *MSSQLCollector) collectWaitStats(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlWaitStatistics
log.Debugf("mssql_waitstats collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_waitstats collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "waitstats")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "waitstats")], &dst, c.logger); err != nil {
return nil, err
}
@@ -3960,9 +3972,9 @@ type mssqlSQLErrors struct {
// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object
func (c *MSSQLCollector) collectSQLErrors(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlSQLErrors
log.Debugf("mssql_sqlerrors collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_sqlerrors collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlerrors")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlerrors")], &dst, c.logger); err != nil {
return nil, err
}
@@ -4003,9 +4015,9 @@ type mssqlTransactions struct {
// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-transactions-object
func (c *MSSQLCollector) collectTransactions(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) {
var dst []mssqlTransactions
log.Debugf("mssql_transactions collector iterating sql instance %s.", sqlInstance)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_transactions collector iterating sql instance %s.", sqlInstance))
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "transactions")], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "transactions")], &dst, c.logger); err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkMSSQLCollector(b *testing.B) {
benchmarkCollector(b, "mssql", NewMSSQLCollector)
benchmarkCollector(b, "mssql", newMSSQLCollector)
}

View File

@@ -4,35 +4,45 @@
package collector
import (
"errors"
"fmt"
"regexp"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
)
func init() {
registerCollector("net", NewNetworkCollector, "Network Interface")
}
const (
FlagNicOldExclude = "collector.net.nic-blacklist"
FlagNicOldInclude = "collector.net.nic-whitelist"
FlagNicExclude = "collector.net.nic-exclude"
FlagNicInclude = "collector.net.nic-include"
)
var (
nicWhitelist = kingpin.Flag(
"collector.net.nic-whitelist",
"Regexp of NIC:s to whitelist. NIC name must both match whitelist and not match blacklist to be included.",
).Default(".+").String()
nicBlacklist = kingpin.Flag(
"collector.net.nic-blacklist",
"Regexp of NIC:s to blacklist. NIC name must both match whitelist and not match blacklist to be included.",
).Default("").String()
nicOldInclude *string
nicOldExclude *string
nicInclude *string
nicExclude *string
nicIncludeSet bool
nicExcludeSet bool
nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
)
// A NetworkCollector is a Prometheus collector for Perflib Network Interface metrics
type NetworkCollector struct {
logger log.Logger
BytesReceivedTotal *prometheus.Desc
BytesSentTotal *prometheus.Desc
BytesTotal *prometheus.Desc
OutputQueueLength *prometheus.Desc
PacketsOutboundDiscarded *prometheus.Desc
PacketsOutboundErrors *prometheus.Desc
PacketsTotal *prometheus.Desc
@@ -43,15 +53,63 @@ type NetworkCollector struct {
PacketsSentTotal *prometheus.Desc
CurrentBandwidth *prometheus.Desc
nicWhitelistPattern *regexp.Regexp
nicBlacklistPattern *regexp.Regexp
nicIncludePattern *regexp.Regexp
nicExcludePattern *regexp.Regexp
}
// NewNetworkCollector ...
func NewNetworkCollector() (Collector, error) {
// newNetworkCollectorFlags ...
func newNetworkCollectorFlags(app *kingpin.Application) {
nicInclude = app.Flag(
FlagNicInclude,
"Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
nicIncludeSet = true
return nil
}).String()
nicExclude = app.Flag(
FlagNicExclude,
"Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
nicExcludeSet = true
return nil
}).String()
nicOldInclude = app.Flag(
FlagNicOldInclude,
"DEPRECATED: Use --collector.net.nic-include",
).Hidden().String()
nicOldExclude = app.Flag(
FlagNicOldExclude,
"DEPRECATED: Use --collector.net.nic-exclude",
).Hidden().String()
}
// newNetworkCollector ...
func newNetworkCollector(logger log.Logger) (Collector, error) {
const subsystem = "net"
logger = log.With(logger, "collector", subsystem)
if *nicOldExclude != "" {
if !nicExcludeSet {
_ = level.Warn(logger).Log("msg", "--collector.net.nic-blacklist is DEPRECATED and will be removed in a future release, use --collector.net.nic-exclude")
*nicExclude = *nicOldExclude
} else {
return nil, errors.New("--collector.net.nic-blacklist and --collector.net.nic-exclude are mutually exclusive")
}
}
if *nicOldInclude != "" {
if !nicIncludeSet {
_ = level.Warn(logger).Log("msg", "--collector.net.nic-whitelist is DEPRECATED and will be removed in a future release, use --collector.net.nic-include")
*nicInclude = *nicOldInclude
} else {
return nil, errors.New("--collector.net.nic-whitelist and --collector.net.nic-include are mutually exclusive")
}
}
return &NetworkCollector{
logger: logger,
BytesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"),
"(Network.BytesReceivedPerSec)",
@@ -70,6 +128,12 @@ func NewNetworkCollector() (Collector, error) {
[]string{"nic"},
nil,
),
OutputQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "output_queue_length_packets"),
"(Network.OutputQueueLength)",
[]string{"nic"},
nil,
),
PacketsOutboundDiscarded: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded_total"),
"(Network.PacketsOutboundDiscarded)",
@@ -125,8 +189,8 @@ func NewNetworkCollector() (Collector, error) {
nil,
),
nicWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicWhitelist)),
nicBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicBlacklist)),
nicIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicInclude)),
nicExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicExclude)),
}, nil
}
@@ -134,7 +198,7 @@ func NewNetworkCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NetworkCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting net metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting net metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -153,6 +217,7 @@ type networkInterface struct {
BytesSentPerSec float64 `perflib:"Bytes Sent/sec"`
BytesTotalPerSec float64 `perflib:"Bytes Total/sec"`
Name string
OutputQueueLength float64 `perflib:"Output Queue Length"`
PacketsOutboundDiscarded float64 `perflib:"Packets Outbound Discarded"`
PacketsOutboundErrors float64 `perflib:"Packets Outbound Errors"`
PacketsPerSec float64 `perflib:"Packets/sec"`
@@ -167,13 +232,13 @@ type networkInterface struct {
func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []networkInterface
if err := unmarshalObject(ctx.perfObjects["Network Interface"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["Network Interface"], &dst, c.logger); err != nil {
return nil, err
}
for _, nic := range dst {
if c.nicBlacklistPattern.MatchString(nic.Name) ||
!c.nicWhitelistPattern.MatchString(nic.Name) {
if c.nicExcludePattern.MatchString(nic.Name) ||
!c.nicIncludePattern.MatchString(nic.Name) {
continue
}
@@ -201,6 +266,12 @@ func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
nic.BytesTotalPerSec,
name,
)
ch <- prometheus.MustNewConstMetric(
c.OutputQueueLength,
prometheus.GaugeValue,
nic.OutputQueueLength,
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsOutboundDiscarded,
prometheus.CounterValue,

View File

@@ -20,8 +20,8 @@ func TestNetworkToInstanceName(t *testing.T) {
}
func BenchmarkNetCollector(b *testing.B) {
// Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces.
localNicWhitelist := ".+"
nicWhitelist = &localNicWhitelist
benchmarkCollector(b, "net", NewNetworkCollector)
// Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces.
localNicInclude := ".+"
nicInclude = &localNicInclude
benchmarkCollector(b, "net", newNetworkCollector)
}

View File

@@ -4,27 +4,28 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrexceptions", NewNETFramework_NETCLRExceptionsCollector)
}
// A NETFramework_NETCLRExceptionsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics
type NETFramework_NETCLRExceptionsCollector struct {
logger log.Logger
NumberofExcepsThrown *prometheus.Desc
NumberofFilters *prometheus.Desc
NumberofFinallys *prometheus.Desc
ThrowToCatchDepth *prometheus.Desc
}
// NewNETFramework_NETCLRExceptionsCollector ...
func NewNETFramework_NETCLRExceptionsCollector() (Collector, error) {
// newNETFramework_NETCLRExceptionsCollector ...
func newNETFramework_NETCLRExceptionsCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrexceptions"
return &NETFramework_NETCLRExceptionsCollector{
logger: log.With(logger, "collector", subsystem),
NumberofExcepsThrown: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "exceptions_thrown_total"),
"Displays the total number of exceptions thrown since the application started. This includes both .NET exceptions and unmanaged exceptions that are converted into .NET exceptions.",
@@ -56,7 +57,7 @@ func NewNETFramework_NETCLRExceptionsCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRExceptionsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -74,7 +75,7 @@ type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
func (c *NETFramework_NETCLRExceptionsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNetFrameworkNETCLRExceptionsCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRExceptionsCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRExceptionsCollector)
}

View File

@@ -4,26 +4,26 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrinterop", NewNETFramework_NETCLRInteropCollector)
}
// A NETFramework_NETCLRInteropCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics
type NETFramework_NETCLRInteropCollector struct {
logger log.Logger
NumberofCCWs *prometheus.Desc
Numberofmarshalling *prometheus.Desc
NumberofStubs *prometheus.Desc
}
// NewNETFramework_NETCLRInteropCollector ...
func NewNETFramework_NETCLRInteropCollector() (Collector, error) {
// newNETFramework_NETCLRInteropCollector ...
func newNETFramework_NETCLRInteropCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrinterop"
return &NETFramework_NETCLRInteropCollector{
logger: log.With(logger, "collector", subsystem),
NumberofCCWs: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "com_callable_wrappers_total"),
"Displays the current number of COM callable wrappers (CCWs). A CCW is a proxy for a managed object being referenced from an unmanaged COM client.",
@@ -49,7 +49,7 @@ func NewNETFramework_NETCLRInteropCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRInteropCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrinterop metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrinterop metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -67,7 +67,7 @@ type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
func (c *NETFramework_NETCLRInteropCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNETFrameworkNETCLRInteropCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRInteropCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRInteropCollector)
}

View File

@@ -4,27 +4,27 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrjit", NewNETFramework_NETCLRJitCollector)
}
// A NETFramework_NETCLRJitCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics
type NETFramework_NETCLRJitCollector struct {
logger log.Logger
NumberofMethodsJitted *prometheus.Desc
TimeinJit *prometheus.Desc
StandardJitFailures *prometheus.Desc
TotalNumberofILBytesJitted *prometheus.Desc
}
// NewNETFramework_NETCLRJitCollector ...
func NewNETFramework_NETCLRJitCollector() (Collector, error) {
// newNETFramework_NETCLRJitCollector ...
func newNETFramework_NETCLRJitCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrjit"
return &NETFramework_NETCLRJitCollector{
logger: log.With(logger, "collector", subsystem),
NumberofMethodsJitted: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "jit_methods_total"),
"Displays the total number of methods JIT-compiled since the application started. This counter does not include pre-JIT-compiled methods.",
@@ -56,7 +56,7 @@ func NewNETFramework_NETCLRJitCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRJitCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrjit metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrjit metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -76,7 +76,7 @@ type Win32_PerfRawData_NETFramework_NETCLRJit struct {
func (c *NETFramework_NETCLRJitCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRJit
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNETFrameworkNETCLRJitCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRJitCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRJitCollector)
}

View File

@@ -4,17 +4,16 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrloading", NewNETFramework_NETCLRLoadingCollector)
}
// A NETFramework_NETCLRLoadingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics
type NETFramework_NETCLRLoadingCollector struct {
logger log.Logger
BytesinLoaderHeap *prometheus.Desc
Currentappdomains *prometheus.Desc
CurrentAssemblies *prometheus.Desc
@@ -26,10 +25,11 @@ type NETFramework_NETCLRLoadingCollector struct {
TotalNumberofLoadFailures *prometheus.Desc
}
// NewNETFramework_NETCLRLoadingCollector ...
func NewNETFramework_NETCLRLoadingCollector() (Collector, error) {
// newNETFramework_NETCLRLoadingCollector ...
func newNETFramework_NETCLRLoadingCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrloading"
return &NETFramework_NETCLRLoadingCollector{
logger: log.With(logger, "collector", subsystem),
BytesinLoaderHeap: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "loader_heap_size_bytes"),
"Displays the current size, in bytes, of the memory committed by the class loader across all application domains. Committed memory is the physical space reserved in the disk paging file.",
@@ -91,7 +91,7 @@ func NewNETFramework_NETCLRLoadingCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRLoadingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrloading metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrloading metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -120,7 +120,7 @@ type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
func (c *NETFramework_NETCLRLoadingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNETFrameworkNETCLRLoadingCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRLoadingCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRLoadingCollector)
}

View File

@@ -4,17 +4,16 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrlocksandthreads", NewNETFramework_NETCLRLocksAndThreadsCollector)
}
// A NETFramework_NETCLRLocksAndThreadsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics
type NETFramework_NETCLRLocksAndThreadsCollector struct {
logger log.Logger
CurrentQueueLength *prometheus.Desc
NumberofcurrentlogicalThreads *prometheus.Desc
NumberofcurrentphysicalThreads *prometheus.Desc
@@ -24,10 +23,11 @@ type NETFramework_NETCLRLocksAndThreadsCollector struct {
TotalNumberofContentions *prometheus.Desc
}
// NewNETFramework_NETCLRLocksAndThreadsCollector ...
func NewNETFramework_NETCLRLocksAndThreadsCollector() (Collector, error) {
// newNETFramework_NETCLRLocksAndThreadsCollector ...
func newNETFramework_NETCLRLocksAndThreadsCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrlocksandthreads"
return &NETFramework_NETCLRLocksAndThreadsCollector{
logger: log.With(logger, "collector", subsystem),
CurrentQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "current_queue_length"),
"Displays the total number of threads that are currently waiting to acquire a managed lock in the application.",
@@ -77,7 +77,7 @@ func NewNETFramework_NETCLRLocksAndThreadsCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRLocksAndThreadsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -100,7 +100,7 @@ type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
func (c *NETFramework_NETCLRLocksAndThreadsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNETFrameworkNETCLRLocksAndThreadsCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRLocksAndThreadsCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRLocksAndThreadsCollector)
}

View File

@@ -4,17 +4,16 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrmemory", NewNETFramework_NETCLRMemoryCollector)
}
// A NETFramework_NETCLRMemoryCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics
type NETFramework_NETCLRMemoryCollector struct {
logger log.Logger
AllocatedBytes *prometheus.Desc
FinalizationSurvivors *prometheus.Desc
HeapSize *prometheus.Desc
@@ -32,10 +31,11 @@ type NETFramework_NETCLRMemoryCollector struct {
PromotedMemoryfromGen1 *prometheus.Desc
}
// NewNETFramework_NETCLRMemoryCollector ...
func NewNETFramework_NETCLRMemoryCollector() (Collector, error) {
// newNETFramework_NETCLRMemoryCollector ...
func newNETFramework_NETCLRMemoryCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrmemory"
return &NETFramework_NETCLRMemoryCollector{
logger: log.With(logger, "collector", subsystem),
AllocatedBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "allocated_bytes_total"),
"Displays the total number of bytes allocated on the garbage collection heap.",
@@ -115,7 +115,7 @@ func NewNETFramework_NETCLRMemoryCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRMemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrmemory metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrmemory metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -157,7 +157,7 @@ type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
func (c *NETFramework_NETCLRMemoryCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNETFrameworkNETCLRMemoryCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRMemoryCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRMemoryCollector)
}

View File

@@ -4,17 +4,16 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrremoting", NewNETFramework_NETCLRRemotingCollector)
}
// A NETFramework_NETCLRRemotingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics
type NETFramework_NETCLRRemotingCollector struct {
logger log.Logger
Channels *prometheus.Desc
ContextBoundClassesLoaded *prometheus.Desc
ContextBoundObjects *prometheus.Desc
@@ -23,10 +22,11 @@ type NETFramework_NETCLRRemotingCollector struct {
TotalRemoteCalls *prometheus.Desc
}
// NewNETFramework_NETCLRRemotingCollector ...
func NewNETFramework_NETCLRRemotingCollector() (Collector, error) {
// newNETFramework_NETCLRRemotingCollector ...
func newNETFramework_NETCLRRemotingCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrremoting"
return &NETFramework_NETCLRRemotingCollector{
logger: log.With(logger, "collector", subsystem),
Channels: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "channels_total"),
"Displays the total number of remoting channels registered across all application domains since application started.",
@@ -70,7 +70,7 @@ func NewNETFramework_NETCLRRemotingCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRRemotingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrremoting metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrremoting metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -90,7 +90,7 @@ type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
func (c *NETFramework_NETCLRRemotingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNETFrameworkNETCLRRemotingCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRRemotingCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRRemotingCollector)
}

View File

@@ -4,27 +4,27 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("netframework_clrsecurity", NewNETFramework_NETCLRSecurityCollector)
}
// A NETFramework_NETCLRSecurityCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics
type NETFramework_NETCLRSecurityCollector struct {
logger log.Logger
NumberLinkTimeChecks *prometheus.Desc
TimeinRTchecks *prometheus.Desc
StackWalkDepth *prometheus.Desc
TotalRuntimeChecks *prometheus.Desc
}
// NewNETFramework_NETCLRSecurityCollector ...
func NewNETFramework_NETCLRSecurityCollector() (Collector, error) {
// newNETFramework_NETCLRSecurityCollector ...
func newNETFramework_NETCLRSecurityCollector(logger log.Logger) (Collector, error) {
const subsystem = "netframework_clrsecurity"
return &NETFramework_NETCLRSecurityCollector{
logger: log.With(logger, "collector", subsystem),
NumberLinkTimeChecks: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "link_time_checks_total"),
"Displays the total number of link-time code access security checks since the application started.",
@@ -56,7 +56,7 @@ func NewNETFramework_NETCLRSecurityCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *NETFramework_NETCLRSecurityCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -75,7 +75,7 @@ type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
func (c *NETFramework_NETCLRSecurityCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -6,5 +6,5 @@ import (
func BenchmarkNETFrameworkNETCLRSecurityCollector(b *testing.B) {
// No context name required as collector source is WMI
benchmarkCollector(b, "", NewNETFramework_NETCLRSecurityCollector)
benchmarkCollector(b, "", newNETFramework_NETCLRSecurityCollector)
}

425
collector/nps.go Normal file
View File

@@ -0,0 +1,425 @@
package collector
import (
"fmt"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
// A npsCollector is a Prometheus collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics
type npsCollector struct {
logger log.Logger
AccessAccepts *prometheus.Desc
AccessChallenges *prometheus.Desc
AccessRejects *prometheus.Desc
AccessRequests *prometheus.Desc
AccessBadAuthenticators *prometheus.Desc
AccessDroppedPackets *prometheus.Desc
AccessInvalidRequests *prometheus.Desc
AccessMalformedPackets *prometheus.Desc
AccessPacketsReceived *prometheus.Desc
AccessPacketsSent *prometheus.Desc
AccessServerResetTime *prometheus.Desc
AccessServerUpTime *prometheus.Desc
AccessUnknownType *prometheus.Desc
AccountingRequests *prometheus.Desc
AccountingResponses *prometheus.Desc
AccountingBadAuthenticators *prometheus.Desc
AccountingDroppedPackets *prometheus.Desc
AccountingInvalidRequests *prometheus.Desc
AccountingMalformedPackets *prometheus.Desc
AccountingNoRecord *prometheus.Desc
AccountingPacketsReceived *prometheus.Desc
AccountingPacketsSent *prometheus.Desc
AccountingServerResetTime *prometheus.Desc
AccountingServerUpTime *prometheus.Desc
AccountingUnknownType *prometheus.Desc
}
func newNPSCollector(logger log.Logger) (Collector, error) {
const subsystem = "nps"
logger = log.With(logger, "collector", subsystem)
return &npsCollector{
logger: logger,
AccessAccepts: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_accepts"),
"(AccessAccepts)",
nil,
nil,
),
AccessChallenges: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_challenges"),
"(AccessChallenges)",
nil,
nil,
),
AccessRejects: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_rejects"),
"(AccessRejects)",
nil,
nil,
),
AccessRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_requests"),
"(AccessRequests)",
nil,
nil,
),
AccessBadAuthenticators: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_bad_authenticators"),
"(BadAuthenticators)",
nil,
nil,
),
AccessDroppedPackets: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_dropped_packets"),
"(DroppedPackets)",
nil,
nil,
),
AccessInvalidRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_invalid_requests"),
"(InvalidRequests)",
nil,
nil,
),
AccessMalformedPackets: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_malformed_packets"),
"(MalformedPackets)",
nil,
nil,
),
AccessPacketsReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_packets_received"),
"(PacketsReceived)",
nil,
nil,
),
AccessPacketsSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_packets_sent"),
"(PacketsSent)",
nil,
nil,
),
AccessServerResetTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_server_reset_time"),
"(ServerResetTime)",
nil,
nil,
),
AccessServerUpTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_server_up_time"),
"(ServerUpTime)",
nil,
nil,
),
AccessUnknownType: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "access_unknown_type"),
"(UnknownType)",
nil,
nil,
),
AccountingRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_requests"),
"(AccountingRequests)",
nil,
nil,
),
AccountingResponses: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_responses"),
"(AccountingResponses)",
nil,
nil,
),
AccountingBadAuthenticators: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_bad_authenticators"),
"(BadAuthenticators)",
nil,
nil,
),
AccountingDroppedPackets: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_dropped_packets"),
"(DroppedPackets)",
nil,
nil,
),
AccountingInvalidRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_invalid_requests"),
"(InvalidRequests)",
nil,
nil,
),
AccountingMalformedPackets: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_malformed_packets"),
"(MalformedPackets)",
nil,
nil,
),
AccountingNoRecord: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_no_record"),
"(NoRecord)",
nil,
nil,
),
AccountingPacketsReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_packets_received"),
"(PacketsReceived)",
nil,
nil,
),
AccountingPacketsSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_packets_sent"),
"(PacketsSent)",
nil,
nil,
),
AccountingServerResetTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_server_reset_time"),
"(ServerResetTime)",
nil,
nil,
),
AccountingServerUpTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_server_up_time"),
"(ServerUpTime)",
nil,
nil,
),
AccountingUnknownType: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "accounting_unknown_type"),
"(UnknownType)",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *npsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.CollectAccept(ch); err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("failed collecting NPS accept data: %s %v", desc, err))
return err
}
if desc, err := c.CollectAccounting(ch); err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("failed collecting NPS accounting data: %s %v", desc, err))
return err
}
return nil
}
// Win32_PerfRawData_IAS_NPSAuthenticationServer docs:
// at the moment there is no Microsoft documentation
type Win32_PerfRawData_IAS_NPSAuthenticationServer struct {
Name string
AccessAccepts uint32
AccessChallenges uint32
AccessRejects uint32
AccessRequests uint32
AccessBadAuthenticators uint32
AccessDroppedPackets uint32
AccessInvalidRequests uint32
AccessMalformedPackets uint32
AccessPacketsReceived uint32
AccessPacketsSent uint32
AccessServerResetTime uint32
AccessServerUpTime uint32
AccessUnknownType uint32
}
type Win32_PerfRawData_IAS_NPSAccountingServer struct {
Name string
AccountingRequests uint32
AccountingResponses uint32
AccountingBadAuthenticators uint32
AccountingDroppedPackets uint32
AccountingInvalidRequests uint32
AccountingMalformedPackets uint32
AccountingNoRecord uint32
AccountingPacketsReceived uint32
AccountingPacketsSent uint32
AccountingServerResetTime uint32
AccountingServerUpTime uint32
AccountingUnknownType uint32
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *npsCollector) CollectAccept(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.AccessAccepts,
prometheus.CounterValue,
float64(dst[0].AccessAccepts),
)
ch <- prometheus.MustNewConstMetric(
c.AccessChallenges,
prometheus.CounterValue,
float64(dst[0].AccessChallenges),
)
ch <- prometheus.MustNewConstMetric(
c.AccessRejects,
prometheus.CounterValue,
float64(dst[0].AccessRejects),
)
ch <- prometheus.MustNewConstMetric(
c.AccessRequests,
prometheus.CounterValue,
float64(dst[0].AccessRequests),
)
ch <- prometheus.MustNewConstMetric(
c.AccessBadAuthenticators,
prometheus.CounterValue,
float64(dst[0].AccessBadAuthenticators),
)
ch <- prometheus.MustNewConstMetric(
c.AccessDroppedPackets,
prometheus.CounterValue,
float64(dst[0].AccessDroppedPackets),
)
ch <- prometheus.MustNewConstMetric(
c.AccessInvalidRequests,
prometheus.CounterValue,
float64(dst[0].AccessInvalidRequests),
)
ch <- prometheus.MustNewConstMetric(
c.AccessMalformedPackets,
prometheus.CounterValue,
float64(dst[0].AccessMalformedPackets),
)
ch <- prometheus.MustNewConstMetric(
c.AccessPacketsReceived,
prometheus.CounterValue,
float64(dst[0].AccessPacketsReceived),
)
ch <- prometheus.MustNewConstMetric(
c.AccessPacketsSent,
prometheus.CounterValue,
float64(dst[0].AccessPacketsSent),
)
ch <- prometheus.MustNewConstMetric(
c.AccessServerResetTime,
prometheus.CounterValue,
float64(dst[0].AccessServerResetTime),
)
ch <- prometheus.MustNewConstMetric(
c.AccessServerUpTime,
prometheus.CounterValue,
float64(dst[0].AccessServerUpTime),
)
ch <- prometheus.MustNewConstMetric(
c.AccessUnknownType,
prometheus.CounterValue,
float64(dst[0].AccessUnknownType),
)
return nil, nil
}
func (c *npsCollector) CollectAccounting(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_IAS_NPSAccountingServer
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.AccountingRequests,
prometheus.CounterValue,
float64(dst[0].AccountingRequests),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingResponses,
prometheus.CounterValue,
float64(dst[0].AccountingResponses),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingBadAuthenticators,
prometheus.CounterValue,
float64(dst[0].AccountingBadAuthenticators),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingDroppedPackets,
prometheus.CounterValue,
float64(dst[0].AccountingDroppedPackets),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingInvalidRequests,
prometheus.CounterValue,
float64(dst[0].AccountingInvalidRequests),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingMalformedPackets,
prometheus.CounterValue,
float64(dst[0].AccountingMalformedPackets),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingNoRecord,
prometheus.CounterValue,
float64(dst[0].AccountingNoRecord),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingPacketsReceived,
prometheus.CounterValue,
float64(dst[0].AccountingPacketsReceived),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingPacketsSent,
prometheus.CounterValue,
float64(dst[0].AccountingPacketsSent),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingServerResetTime,
prometheus.CounterValue,
float64(dst[0].AccountingServerResetTime),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingServerUpTime,
prometheus.CounterValue,
float64(dst[0].AccountingServerUpTime),
)
ch <- prometheus.MustNewConstMetric(
c.AccountingUnknownType,
prometheus.CounterValue,
float64(dst[0].AccountingUnknownType),
)
return nil, nil
}

9
collector/nps_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkNPSCollector(b *testing.B) {
benchmarkCollector(b, "nps", newNPSCollector)
}

View File

@@ -9,20 +9,19 @@ import (
"strings"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/headers/netapi32"
"github.com/prometheus-community/windows_exporter/headers/psapi"
"github.com/prometheus-community/windows_exporter/headers/sysinfoapi"
"github.com/prometheus-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 {
logger log.Logger
OSInformation *prometheus.Desc
PhysicalMemoryFreeBytes *prometheus.Desc
PagingFreeBytes *prometheus.Desc
@@ -44,11 +43,13 @@ type pagingFileCounter struct {
UsagePeak float64 `perflib:"% Usage Peak"`
}
// NewOSCollector ...
func NewOSCollector() (Collector, error) {
// newOSCollector ...
func newOSCollector(logger log.Logger) (Collector, error) {
const subsystem = "os"
return &OSCollector{
logger: log.With(logger, "collector", subsystem),
OSInformation: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "info"),
"OperatingSystem.Caption, OperatingSystem.Version",
@@ -134,7 +135,7 @@ func NewOSCollector() (Collector, error) {
// 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)
_ = level.Error(c.logger).Log("failed collecting os metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -204,7 +205,7 @@ func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (
file, err := os.Stat(fileString)
// For unknown reasons, Windows doesn't always create a page file. Continue collection rather than aborting.
if err != nil {
log.Debugf("Failed to read page file (reason: %s): %s\n", err, fileString)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("Failed to read page file (reason: %s): %s\n", err, fileString))
} else {
fsipf += float64(file.Size())
}
@@ -216,7 +217,7 @@ func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (
}
var pfc = make([]pagingFileCounter, 0)
if err := unmarshalObject(ctx.perfObjects["Paging File"], &pfc); err != nil {
if err := unmarshalObject(ctx.perfObjects["Paging File"], &pfc, c.logger); err != nil {
return nil, err
}
@@ -275,7 +276,7 @@ func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (
fsipf,
)
} else {
log.Debugln("Could not find HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management key. windows_os_paging_free_bytes and windows_os_paging_limit_bytes will be omitted.")
_ = level.Debug(c.logger).Log("Could not find HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management key. windows_os_paging_free_bytes and windows_os_paging_limit_bytes will be omitted.")
}
ch <- prometheus.MustNewConstMetric(
c.VirtualMemoryFreeBytes,

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkOSCollector(b *testing.B) {
benchmarkCollector(b, "os", NewOSCollector)
benchmarkCollector(b, "os", newOSCollector)
}

View File

@@ -6,15 +6,14 @@ import (
"strconv"
"strings"
perflibCollector "github.com/leoluk/perflib_exporter/collector"
"github.com/leoluk/perflib_exporter/perflib"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus-community/windows_exporter/perflib"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
)
var nametable = perflib.QueryNameTable("Counter 009") // Reads the names in English TODO: validate that the English names are always present
func MapCounterToIndex(name string) string {
return strconv.Itoa(int(nametable.LookupIndex(name)))
return strconv.Itoa(int(perflib.CounterNameTable.LookupIndex(name)))
}
func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error) {
@@ -30,7 +29,7 @@ func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error)
return indexed, nil
}
func unmarshalObject(obj *perflib.PerfObject, vs interface{}) error {
func unmarshalObject(obj *perflib.PerfObject, vs interface{}, logger log.Logger) error {
if obj == nil {
return fmt.Errorf("counter not found")
}
@@ -81,7 +80,7 @@ func unmarshalObject(obj *perflib.PerfObject, vs interface{}) error {
ctr, found := counters[tag]
if !found {
log.Debugf("missing counter %q, have %v", tag, counterMapKeys(counters))
_ = level.Debug(logger).Log("msg", fmt.Sprintf("missing counter %q, have %v", tag, counterMapKeys(counters)))
continue
}
if !target.Field(i).CanSet() {
@@ -100,9 +99,9 @@ func unmarshalObject(obj *perflib.PerfObject, vs interface{}) error {
}
switch ctr.Def.CounterType {
case perflibCollector.PERF_ELAPSED_TIME:
case perflib.PERF_ELAPSED_TIME:
target.Field(i).SetFloat(float64(ctr.Value-windowsEpoch) / float64(obj.Frequency))
case perflibCollector.PERF_100NSEC_TIMER, perflibCollector.PERF_PRECISION_100NS_TIMER:
case perflib.PERF_100NSEC_TIMER, perflib.PERF_PRECISION_100NS_TIMER:
target.Field(i).SetFloat(float64(ctr.Value) * ticksToSecondsScaleFactor)
default:
target.Field(i).SetFloat(float64(ctr.Value))

View File

@@ -4,8 +4,9 @@ import (
"reflect"
"testing"
perflibCollector "github.com/leoluk/perflib_exporter/collector"
"github.com/leoluk/perflib_exporter/perflib"
"github.com/prometheus-community/windows_exporter/perflib"
"github.com/go-kit/log"
)
type simple struct {
@@ -37,7 +38,7 @@ func TestUnmarshalPerflib(t *testing.T) {
{
Def: &perflib.PerfCounterDef{
Name: "Something",
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
CounterType: perflib.PERF_COUNTER_COUNTER,
},
Value: 123,
},
@@ -57,14 +58,14 @@ func TestUnmarshalPerflib(t *testing.T) {
{
Def: &perflib.PerfCounterDef{
Name: "Something",
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
CounterType: perflib.PERF_COUNTER_COUNTER,
},
Value: 123,
},
{
Def: &perflib.PerfCounterDef{
Name: "Something Else",
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
CounterType: perflib.PERF_COUNTER_COUNTER,
HasSecondValue: true,
},
Value: 256,
@@ -86,7 +87,7 @@ func TestUnmarshalPerflib(t *testing.T) {
{
Def: &perflib.PerfCounterDef{
Name: "Something",
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
CounterType: perflib.PERF_COUNTER_COUNTER,
},
Value: 321,
},
@@ -97,7 +98,7 @@ func TestUnmarshalPerflib(t *testing.T) {
{
Def: &perflib.PerfCounterDef{
Name: "Something",
CounterType: perflibCollector.PERF_COUNTER_COUNTER,
CounterType: perflib.PERF_COUNTER_COUNTER,
},
Value: 231,
},
@@ -112,7 +113,7 @@ func TestUnmarshalPerflib(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
output := make([]simple, 0)
err := unmarshalObject(c.obj, &output)
err := unmarshalObject(c.obj, &output, log.NewNopLogger())
if err != nil && !c.expectError {
t.Errorf("Did not expect error, got %q", err)
}

View File

@@ -4,33 +4,41 @@
package collector
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("process", newProcessCollector, "Process")
}
const (
FlagProcessOldExclude = "collector.process.blacklist"
FlagProcessOldInclude = "collector.process.whitelist"
FlagProcessExclude = "collector.process.exclude"
FlagProcessInclude = "collector.process.include"
)
var (
processWhitelist = kingpin.Flag(
"collector.process.whitelist",
"Regexp of processes to include. Process name must both match whitelist and not match blacklist to be included.",
).Default(".*").String()
processBlacklist = kingpin.Flag(
"collector.process.blacklist",
"Regexp of processes to exclude. Process name must both match whitelist and not match blacklist to be included.",
).Default("").String()
processOldInclude *string
processOldExclude *string
processInclude *string
processExclude *string
processIncludeSet bool
processExcludeSet bool
)
type processCollector struct {
logger log.Logger
StartTime *prometheus.Desc
CPUTimeTotal *prometheus.Desc
HandleCount *prometheus.Desc
@@ -47,19 +55,66 @@ type processCollector struct {
WorkingSetPeak *prometheus.Desc
WorkingSet *prometheus.Desc
processWhitelistPattern *regexp.Regexp
processBlacklistPattern *regexp.Regexp
processIncludePattern *regexp.Regexp
processExcludePattern *regexp.Regexp
}
// newProcessCollectorFlags ...
func newProcessCollectorFlags(app *kingpin.Application) {
processInclude = app.Flag(
FlagProcessInclude,
"Regexp of processes to include. Process name must both match include and not match exclude to be included.",
).Default(".*").PreAction(func(c *kingpin.ParseContext) error {
processIncludeSet = true
return nil
}).String()
processExclude = app.Flag(
FlagProcessExclude,
"Regexp of processes to exclude. Process name must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
processExcludeSet = true
return nil
}).String()
processOldInclude = app.Flag(
FlagProcessOldInclude,
"DEPRECATED: Use --collector.process.include",
).Hidden().String()
processOldExclude = app.Flag(
FlagProcessOldExclude,
"DEPRECATED: Use --collector.process.exclude",
).Hidden().String()
}
// NewProcessCollector ...
func newProcessCollector() (Collector, error) {
func newProcessCollector(logger log.Logger) (Collector, error) {
const subsystem = "process"
logger = log.With(logger, "collector", subsystem)
if *processWhitelist == ".*" && *processBlacklist == "" {
log.Warn("No filters specified for process collector. This will generate a very large number of metrics!")
if *processOldExclude != "" {
if !processExcludeSet {
_ = level.Warn(logger).Log("msg", "--collector.process.blacklist is DEPRECATED and will be removed in a future release, use --collector.process.exclude")
*processExclude = *processOldExclude
} else {
return nil, errors.New("--collector.process.blacklist and --collector.process.exclude are mutually exclusive")
}
}
if *processOldInclude != "" {
if !processIncludeSet {
_ = level.Warn(logger).Log("msg", "--collector.process.whitelist is DEPRECATED and will be removed in a future release, use --collector.process.include")
*processInclude = *processOldInclude
} else {
return nil, errors.New("--collector.process.whitelist and --collector.process.include are mutually exclusive")
}
}
if *processInclude == ".*" && *processExclude == "" {
_ = level.Warn(logger).Log("msg", "No filters specified for process collector. This will generate a very large number of metrics!")
}
return &processCollector{
logger: logger,
StartTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "start_time"),
"Time of process start.",
@@ -150,8 +205,8 @@ func newProcessCollector() (Collector, error) {
[]string{"process", "process_id", "creating_process_id"},
nil,
),
processWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processWhitelist)),
processBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processBlacklist)),
processIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processInclude)),
processExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processExclude)),
}, nil
}
@@ -194,21 +249,21 @@ type WorkerProcess struct {
func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
data := make([]perflibProcess, 0)
err := unmarshalObject(ctx.perfObjects["Process"], &data)
err := unmarshalObject(ctx.perfObjects["Process"], &data, c.logger)
if err != nil {
return err
}
var dst_wp []WorkerProcess
q_wp := queryAll(&dst_wp)
q_wp := queryAll(&dst_wp, c.logger)
if err := wmi.QueryNamespace(q_wp, &dst_wp, "root\\WebAdministration"); err != nil {
log.Debugf("Could not query WebAdministration namespace for IIS worker processes: %v. Skipping", err)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("Could not query WebAdministration namespace for IIS worker processes: %v. Skipping", err))
}
for _, process := range data {
if process.Name == "_Total" ||
c.processBlacklistPattern.MatchString(process.Name) ||
!c.processWhitelistPattern.MatchString(process.Name) {
c.processExcludePattern.MatchString(process.Name) ||
!c.processIncludePattern.MatchString(process.Name) {
continue
}
// Duplicate processes are suffixed # and an index number. Remove those.

View File

@@ -5,9 +5,9 @@ import (
)
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
// Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all processes.
localProcessInclude := ".+"
processInclude = &localProcessInclude
// No context name required as collector source is WMI
benchmarkCollector(b, "", newProcessCollector)

193
collector/prometheus.go Normal file
View File

@@ -0,0 +1,193 @@
//go:build windows
// +build windows
package collector
import (
"fmt"
"sync"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
// Base metrics returned by Prometheus
var (
scrapeDurationDesc = prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "exporter", "collector_duration_seconds"),
"windows_exporter: Duration of a collection.",
[]string{"collector"},
nil,
)
scrapeSuccessDesc = prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "exporter", "collector_success"),
"windows_exporter: Whether the collector was successful.",
[]string{"collector"},
nil,
)
scrapeTimeoutDesc = prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "exporter", "collector_timeout"),
"windows_exporter: Whether the collector timed out.",
[]string{"collector"},
nil,
)
snapshotDuration = prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "exporter", "perflib_snapshot_duration_seconds"),
"Duration of perflib snapshot capture",
nil,
nil,
)
)
// Prometheus implements prometheus.Collector for a set of Windows collectors.
type Prometheus struct {
maxScrapeDuration time.Duration
collectors map[string]Collector
logger log.Logger
}
// NewPrometheus returns a new Prometheus where the set of collectors must
// return metrics within the given timeout.
func NewPrometheus(timeout time.Duration, cs map[string]Collector, logger log.Logger) *Prometheus {
return &Prometheus{
maxScrapeDuration: timeout,
collectors: cs,
logger: logger,
}
}
// Describe sends all the descriptors of the collectors included to
// the provided channel.
func (coll *Prometheus) Describe(ch chan<- *prometheus.Desc) {
ch <- scrapeDurationDesc
ch <- scrapeSuccessDesc
}
type collectorOutcome int
const (
pending collectorOutcome = iota
success
failed
)
// Collect sends the collected metrics from each of the collectors to
// prometheus.
func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) {
t := time.Now()
cs := make([]string, 0, len(coll.collectors))
for name := range coll.collectors {
cs = append(cs, name)
}
scrapeContext, err := PrepareScrapeContext(cs)
ch <- prometheus.MustNewConstMetric(
snapshotDuration,
prometheus.GaugeValue,
time.Since(t).Seconds(),
)
if err != nil {
ch <- prometheus.NewInvalidMetric(scrapeSuccessDesc, fmt.Errorf("failed to prepare scrape: %v", err))
return
}
wg := sync.WaitGroup{}
wg.Add(len(coll.collectors))
collectorOutcomes := make(map[string]collectorOutcome)
for name := range coll.collectors {
collectorOutcomes[name] = pending
}
metricsBuffer := make(chan prometheus.Metric)
l := sync.Mutex{}
finished := false
go func() {
for m := range metricsBuffer {
l.Lock()
if !finished {
ch <- m
}
l.Unlock()
}
}()
for name, c := range coll.collectors {
go func(name string, c Collector) {
defer wg.Done()
outcome := execute(name, c, scrapeContext, metricsBuffer, coll.logger)
l.Lock()
if !finished {
collectorOutcomes[name] = outcome
}
l.Unlock()
}(name, c)
}
allDone := make(chan struct{})
go func() {
wg.Wait()
close(allDone)
close(metricsBuffer)
}()
// Wait until either all collectors finish, or timeout expires
select {
case <-allDone:
case <-time.After(coll.maxScrapeDuration):
}
l.Lock()
finished = true
remainingCollectorNames := make([]string, 0)
for name, outcome := range collectorOutcomes {
var successValue, timeoutValue float64
if outcome == pending {
timeoutValue = 1.0
remainingCollectorNames = append(remainingCollectorNames, name)
}
if outcome == success {
successValue = 1.0
}
ch <- prometheus.MustNewConstMetric(
scrapeSuccessDesc,
prometheus.GaugeValue,
successValue,
name,
)
ch <- prometheus.MustNewConstMetric(
scrapeTimeoutDesc,
prometheus.GaugeValue,
timeoutValue,
name,
)
}
if len(remainingCollectorNames) > 0 {
_ = level.Warn(coll.logger).Log("msg", fmt.Sprintf("Collection timed out, still waiting for %v", remainingCollectorNames))
}
l.Unlock()
}
func execute(name string, c Collector, ctx *ScrapeContext, ch chan<- prometheus.Metric, logger log.Logger) collectorOutcome {
t := time.Now()
err := c.Collect(ctx, ch)
duration := time.Since(t).Seconds()
ch <- prometheus.MustNewConstMetric(
scrapeDurationDesc,
prometheus.GaugeValue,
duration,
name,
)
if err != nil {
_ = level.Error(logger).Log("msg", fmt.Sprintf("collector %s failed after %fs", name, duration), "err", err)
return failed
}
_ = level.Debug(logger).Log("msg", fmt.Sprintf("collector %s succeeded after %fs.", name, duration))
return success
}

View File

@@ -6,20 +6,19 @@ package collector
import (
"strings"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("remote_fx", NewRemoteFx, "RemoteFX Network", "RemoteFX Graphics")
}
// A RemoteFxNetworkCollector is a Prometheus collector for
// WMI Win32_PerfRawData_Counters_RemoteFXNetwork & Win32_PerfRawData_Counters_RemoteFXGraphics metrics
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxnetwork/
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxgraphics/
type RemoteFxCollector struct {
logger log.Logger
// net
BaseTCPRTT *prometheus.Desc
BaseUDPRTT *prometheus.Desc
@@ -42,10 +41,12 @@ type RemoteFxCollector struct {
SourceFramesPerSecond *prometheus.Desc
}
// NewRemoteFx ...
func NewRemoteFx() (Collector, error) {
// newRemoteFx ...
func newRemoteFx(logger log.Logger) (Collector, error) {
const subsystem = "remote_fx"
return &RemoteFxCollector{
logger: log.With(logger, "collector", subsystem),
// net
BaseTCPRTT: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "net_base_tcp_rtt_seconds"),
@@ -158,11 +159,11 @@ func NewRemoteFx() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *RemoteFxCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collectRemoteFXNetworkCount(ctx, ch); err != nil {
log.Error("failed collecting terminal services session count metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectRemoteFXGraphicsCounters(ctx, ch); err != nil {
log.Error("failed collecting terminal services session count metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -184,7 +185,7 @@ type perflibRemoteFxNetwork struct {
func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
dst := make([]perflibRemoteFxNetwork, 0)
err := unmarshalObject(ctx.perfObjects["RemoteFX Network"], &dst)
err := unmarshalObject(ctx.perfObjects["RemoteFX Network"], &dst, c.logger)
if err != nil {
return nil, err
}
@@ -274,7 +275,7 @@ type perflibRemoteFxGraphics struct {
func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
dst := make([]perflibRemoteFxGraphics, 0)
err := unmarshalObject(ctx.perfObjects["RemoteFX Graphics"], &dst)
err := unmarshalObject(ctx.perfObjects["RemoteFX Graphics"], &dst, c.logger)
if err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkRemoteFXCollector(b *testing.B) {
benchmarkCollector(b, "remote_fx", NewRemoteFx)
benchmarkCollector(b, "remote_fx", newRemoteFx)
}

View File

@@ -4,36 +4,48 @@
package collector
import (
"errors"
"fmt"
"regexp"
"runtime"
"strings"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
ole "github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
)
const (
FlagScheduledTaskOldExclude = "collector.scheduled_task.blacklist"
FlagScheduledTaskOldInclude = "collector.scheduled_task.whitelist"
FlagScheduledTaskExclude = "collector.scheduled_task.exclude"
FlagScheduledTaskInclude = "collector.scheduled_task.include"
)
var (
taskWhitelist = kingpin.Flag(
"collector.scheduled_task.whitelist",
"Regexp of tasks to whitelist. Task path must both match whitelist and not match blacklist to be included.",
).Default(".+").String()
taskBlacklist = kingpin.Flag(
"collector.scheduled_task.blacklist",
"Regexp of tasks to blacklist. Task path must both match whitelist and not match blacklist to be included.",
).String()
taskOldExclude *string
taskOldInclude *string
taskExclude *string
taskInclude *string
taskIncludeSet bool
taskExcludeSet bool
)
type ScheduledTaskCollector struct {
logger log.Logger
LastResult *prometheus.Desc
MissedRuns *prometheus.Desc
State *prometheus.Desc
taskWhitelistPattern *regexp.Regexp
taskBlacklistPattern *regexp.Regexp
taskIncludePattern *regexp.Regexp
taskExcludePattern *regexp.Regexp
}
// TaskState ...
@@ -63,13 +75,55 @@ type ScheduledTask struct {
type ScheduledTasks []ScheduledTask
func init() {
registerCollector("scheduled_task", NewScheduledTask)
// newScheduledTask ...
func newScheduledTaskFlags(app *kingpin.Application) {
taskInclude = app.Flag(
FlagScheduledTaskInclude,
"Regexp of tasks to include. Task path must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
taskIncludeSet = true
return nil
}).String()
taskExclude = app.Flag(
FlagScheduledTaskExclude,
"Regexp of tasks to exclude. Task path must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
taskExcludeSet = true
return nil
}).String()
taskOldInclude = app.Flag(
FlagScheduledTaskOldInclude,
"DEPRECATED: Use --collector.scheduled_task.include",
).Hidden().String()
taskOldExclude = app.Flag(
FlagScheduledTaskOldExclude,
"DEPRECATED: Use --collector.scheduled_task.exclude",
).Hidden().String()
}
// NewScheduledTask ...
func NewScheduledTask() (Collector, error) {
// newScheduledTask ...
func newScheduledTask(logger log.Logger) (Collector, error) {
const subsystem = "scheduled_task"
logger = log.With(logger, "collector", subsystem)
if *taskOldExclude != "" {
if !taskExcludeSet {
_ = level.Warn(logger).Log("msg", "--collector.scheduled_task.blacklist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.exclude")
*taskExclude = *taskOldExclude
} else {
return nil, errors.New("--collector.scheduled_task.blacklist and --collector.scheduled_task.exclude are mutually exclusive")
}
}
if *taskOldInclude != "" {
if !taskIncludeSet {
_ = level.Warn(logger).Log("msg", "--collector.scheduled_task.whitelist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.include")
*taskInclude = *taskOldInclude
} else {
return nil, errors.New("--collector.scheduled_task.whitelist and --collector.scheduled_task.include are mutually exclusive")
}
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -84,6 +138,7 @@ func NewScheduledTask() (Collector, error) {
defer ole.CoUninitialize()
return &ScheduledTaskCollector{
logger: logger,
LastResult: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "last_result"),
"The result that was returned the last time the registered task was run",
@@ -105,14 +160,14 @@ func NewScheduledTask() (Collector, error) {
nil,
),
taskWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskWhitelist)),
taskBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskBlacklist)),
taskIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskInclude)),
taskExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskExclude)),
}, nil
}
func (c *ScheduledTaskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting user metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting user metrics", "desc", desc, "err", err)
return err
}
@@ -128,8 +183,8 @@ func (c *ScheduledTaskCollector) collect(ch chan<- prometheus.Metric) (*promethe
}
for _, task := range scheduledTasks {
if c.taskBlacklistPattern.MatchString(task.Path) ||
!c.taskWhitelistPattern.MatchString(task.Path) {
if c.taskExcludePattern.MatchString(task.Path) ||
!c.taskIncludePattern.MatchString(task.Path) {
continue
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkScheduledTaskCollector(b *testing.B) {
benchmarkCollector(b, "scheduled_task", NewScheduledTask)
benchmarkCollector(b, "scheduled_task", newScheduledTask)
}

View File

@@ -8,31 +8,29 @@ import (
"strings"
"syscall"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc/mgr"
"gopkg.in/alecthomas/kingpin.v2"
)
func init() {
registerCollector("service", NewserviceCollector)
}
const (
FlagServiceWhereClause = "collector.service.services-where"
FlagServiceUseAPI = "collector.service.use-api"
)
var (
serviceWhereClause = kingpin.Flag(
"collector.service.services-where",
"WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.",
).Default("").String()
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()
serviceWhereClause *string
useAPI *bool
)
// A serviceCollector is a Prometheus collector for WMI Win32_Service metrics
type serviceCollector struct {
logger log.Logger
Information *prometheus.Desc
State *prometheus.Desc
StartMode *prometheus.Desc
@@ -41,18 +39,33 @@ type serviceCollector struct {
queryWhereClause string
}
// NewserviceCollector ...
func NewserviceCollector() (Collector, error) {
// newServiceCollectorFlags ...
func newServiceCollectorFlags(app *kingpin.Application) {
serviceWhereClause = app.Flag(
FlagServiceWhereClause,
"WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.",
).Default("").String()
useAPI = app.Flag(
FlagServiceUseAPI,
"Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.",
).Default("false").Bool()
}
// newserviceCollector ...
func newserviceCollector(logger log.Logger) (Collector, error) {
const subsystem = "service"
logger = log.With(logger, "collector", subsystem)
if *serviceWhereClause == "" {
log.Warn("No where-clause specified for service collector. This will generate a very large number of metrics!")
_ = level.Warn(logger).Log("msg", "No where-clause specified for service collector. This will generate a very large number of metrics!")
}
if *useAPI {
log.Warn("API collection is enabled.")
_ = level.Warn(logger).Log("msg", "API collection is enabled.")
}
return &serviceCollector{
logger: logger,
Information: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "info"),
"A metric with a constant '1' value labeled with service information",
@@ -86,12 +99,12 @@ func NewserviceCollector() (Collector, error) {
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)
_ = level.Error(c.logger).Log("msg", "failed collecting API service metrics:", "err", err)
return err
}
} else {
if err := c.collectWMI(ch); err != nil {
log.Error("failed collecting WMI service metrics:", err)
_ = level.Error(c.logger).Log("msg", "failed collecting WMI service metrics:", "err", err)
return err
}
}
@@ -162,7 +175,7 @@ var (
func (c *serviceCollector) collectWMI(ch chan<- prometheus.Metric) error {
var dst []Win32_Service
q := queryAllWhere(&dst, c.queryWhereClause)
q := queryAllWhere(&dst, c.queryWhereClause, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return err
}
@@ -246,14 +259,14 @@ func (c *serviceCollector) collectAPI(ch chan<- prometheus.Metric) error {
// Get UTF16 service name.
serviceName, err := syscall.UTF16PtrFromString(service)
if err != nil {
log.Warnf("Service %s get name error: %#v", service, err)
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Service %s get name error: %#v", service, err))
continue
}
// Open connection for service handler.
serviceHandle, err := windows.OpenService(svcmgrConnection.Handle, serviceName, windows.GENERIC_READ)
if err != nil {
log.Warnf("Open service %s error: %#v", service, err)
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Open service %s error: %#v", service, err))
continue
}
@@ -264,14 +277,14 @@ func (c *serviceCollector) collectAPI(ch chan<- prometheus.Metric) error {
// Get Service Configuration.
serviceConfig, err := serviceManager.Config()
if err != nil {
log.Warnf("Get ervice %s config error: %#v", service, err)
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get ervice %s config error: %#v", service, err))
continue
}
// Get Service Current Status.
serviceStatus, err := serviceManager.Query()
if err != nil {
log.Warnf("Get service %s status error: %#v", service, err)
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get service %s status error: %#v", service, err))
continue
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkServiceCollector(b *testing.B) {
benchmarkCollector(b, "service", NewserviceCollector)
benchmarkCollector(b, "service", newserviceCollector)
}

View File

@@ -4,23 +4,38 @@
package collector
import (
"errors"
"fmt"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
"regexp"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("smtp", NewSMTPCollector, "SMTP Server")
}
const (
FlagSmtpServerOldExclude = "collector.smtp.server-blacklist"
FlagSmtpServerOldInclude = "collector.smtp.server-whitelist"
FlagSmtpServerExclude = "collector.smtp.server-exclude"
FlagSmtpServerInclude = "collector.smtp.server-include"
)
var (
serverWhitelist = kingpin.Flag("collector.smtp.server-whitelist", "Regexp of virtual servers to whitelist. Server name must both match whitelist and not match blacklist to be included.").Default(".+").String()
serverBlacklist = kingpin.Flag("collector.smtp.server-blacklist", "Regexp of virtual servers to blacklist. Server name must both match whitelist and not match blacklist to be included.").String()
serverOldInclude *string
serverOldExclude *string
serverInclude *string
serverExclude *string
serverIncludeSet bool
serverExcludeSet bool
)
type SMTPCollector struct {
logger log.Logger
BadmailedMessagesBadPickupFileTotal *prometheus.Desc
BadmailedMessagesGeneralFailureTotal *prometheus.Desc
BadmailedMessagesHopCountExceededTotal *prometheus.Desc
@@ -64,15 +79,62 @@ type SMTPCollector struct {
RemoteRetryQueueLength *prometheus.Desc
RoutingTableLookupsTotal *prometheus.Desc
serverWhitelistPattern *regexp.Regexp
serverBlacklistPattern *regexp.Regexp
serverIncludePattern *regexp.Regexp
serverExcludePattern *regexp.Regexp
}
func NewSMTPCollector() (Collector, error) {
log.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.")
func newSMTPCollectorFlags(app *kingpin.Application) {
serverInclude = app.Flag(
FlagSmtpServerInclude,
"Regexp of virtual servers to include. Server name must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
serverIncludeSet = true
return nil
}).String()
serverExclude = app.Flag(
FlagSmtpServerExclude,
"Regexp of virtual servers to exclude. Server name must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
serverExcludeSet = true
return nil
}).String()
serverOldInclude = app.Flag(
FlagSmtpServerOldInclude,
"DEPRECATED: Use --collector.smtp.server-include",
).Hidden().String()
serverOldExclude = app.Flag(
FlagSmtpServerOldExclude,
"DEPRECATED: Use --collector.smtp.server-exclude",
).Hidden().String()
}
func newSMTPCollector(logger log.Logger) (Collector, error) {
const subsystem = "smtp"
logger = log.With(logger, "collector", subsystem)
_ = level.Info(logger).Log("msg", "smtp collector is in an experimental state! Metrics for this collector have not been tested.")
if *serverOldExclude != "" {
if !serverExcludeSet {
_ = level.Warn(logger).Log("msg", "--collector.smtp.server-blacklist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-exclude")
*serverExclude = *serverOldExclude
} else {
return nil, errors.New("--collector.smtp.server-blacklist and --collector.smtp.server-exclude are mutually exclusive")
}
}
if *serverOldInclude != "" {
if !serverIncludeSet {
_ = level.Warn(logger).Log("msg", "--collector.smtp.server-whitelist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-include")
*serverInclude = *serverOldInclude
} else {
return nil, errors.New("--collector.smtp.server-whitelist and --collector.smtp.server-include are mutually exclusive")
}
}
return &SMTPCollector{
logger: logger,
BadmailedMessagesBadPickupFileTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_bad_pickup_file_total"),
"Total number of malformed pickup messages sent to badmail",
@@ -326,8 +388,8 @@ func NewSMTPCollector() (Collector, error) {
nil,
),
serverWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverWhitelist)),
serverBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverBlacklist)),
serverIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverInclude)),
serverExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverExclude)),
}, nil
}
@@ -335,7 +397,7 @@ func NewSMTPCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *SMTPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting smtp metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting smtp metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -391,14 +453,14 @@ type PerflibSMTPServer struct {
func (c *SMTPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []PerflibSMTPServer
if err := unmarshalObject(ctx.perfObjects["SMTP Server"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["SMTP Server"], &dst, c.logger); err != nil {
return nil, err
}
for _, server := range dst {
if server.Name == "_Total" ||
c.serverBlacklistPattern.MatchString(server.Name) ||
!c.serverWhitelistPattern.MatchString(server.Name) {
c.serverExcludePattern.MatchString(server.Name) ||
!c.serverIncludePattern.MatchString(server.Name) {
continue
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkSmtpCollector(b *testing.B) {
benchmarkCollector(b, "smtp", NewSMTPCollector)
benchmarkCollector(b, "smtp", newSMTPCollector)
}

View File

@@ -4,16 +4,15 @@
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("system", NewSystemCollector, "System")
}
// A SystemCollector is a Prometheus collector for WMI metrics
type SystemCollector struct {
logger log.Logger
ContextSwitchesTotal *prometheus.Desc
ExceptionDispatchesTotal *prometheus.Desc
ProcessorQueueLength *prometheus.Desc
@@ -22,11 +21,12 @@ type SystemCollector struct {
Threads *prometheus.Desc
}
// NewSystemCollector ...
func NewSystemCollector() (Collector, error) {
// newSystemCollector ...
func newSystemCollector(logger log.Logger) (Collector, error) {
const subsystem = "system"
return &SystemCollector{
logger: log.With(logger, "collector", subsystem),
ContextSwitchesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"),
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
@@ -70,7 +70,7 @@ func NewSystemCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *SystemCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting system metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting system metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -89,7 +89,7 @@ type system struct {
func (c *SystemCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []system
if err := unmarshalObject(ctx.perfObjects["System"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["System"], &dst, c.logger); err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkSystemCollector(b *testing.B) {
benchmarkCollector(b, "system", NewSystemCollector)
benchmarkCollector(b, "system", newSystemCollector)
}

View File

@@ -4,16 +4,15 @@
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("tcp", NewTCPCollector, "TCPv4", "TCPv6")
}
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics
type TCPCollector struct {
logger log.Logger
ConnectionFailures *prometheus.Desc
ConnectionsActive *prometheus.Desc
ConnectionsEstablished *prometheus.Desc
@@ -25,11 +24,12 @@ type TCPCollector struct {
SegmentsSentTotal *prometheus.Desc
}
// NewTCPCollector ...
func NewTCPCollector() (Collector, error) {
// newTCPCollector ...
func newTCPCollector(logger log.Logger) (Collector, error) {
const subsystem = "tcp"
return &TCPCollector{
logger: log.With(logger, "collector", subsystem),
ConnectionFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_failures_total"),
"(TCP.ConnectionFailures)",
@@ -91,7 +91,7 @@ func NewTCPCollector() (Collector, error) {
// to the provided prometheus Metric channel.
func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting tcp metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting tcp metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -173,7 +173,7 @@ func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
var dst []tcp
// TCPv4 counters
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst, c.logger); err != nil {
return nil, err
}
if len(dst) != 0 {
@@ -181,7 +181,7 @@ func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
}
// TCPv6 counters
if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst, c.logger); err != nil {
return nil, err
}
if len(dst) != 0 {

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkTCPCollector(b *testing.B) {
benchmarkCollector(b, "tcp", NewTCPCollector)
benchmarkCollector(b, "tcp", newTCPCollector)
}

665
collector/teradici_pcoip.go Normal file
View File

@@ -0,0 +1,665 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
// A teradiciPcoipCollector is a Prometheus collector for WMI metrics:
// win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics
// win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics
type teradiciPcoipCollector struct {
logger log.Logger
AudioBytesReceived *prometheus.Desc
AudioBytesSent *prometheus.Desc
AudioRXBWkbitPersec *prometheus.Desc
AudioTXBWkbitPersec *prometheus.Desc
AudioTXBWLimitkbitPersec *prometheus.Desc
BytesReceived *prometheus.Desc
BytesSent *prometheus.Desc
PacketsReceived *prometheus.Desc
PacketsSent *prometheus.Desc
RXPacketsLost *prometheus.Desc
SessionDurationSeconds *prometheus.Desc
TXPacketsLost *prometheus.Desc
ImagingActiveMinimumQuality *prometheus.Desc
ImagingApex2800Offload *prometheus.Desc
ImagingBytesReceived *prometheus.Desc
ImagingBytesSent *prometheus.Desc
ImagingDecoderCapabilitykbitPersec *prometheus.Desc
ImagingEncodedFramesPersec *prometheus.Desc
ImagingMegapixelPersec *prometheus.Desc
ImagingNegativeAcknowledgements *prometheus.Desc
ImagingRXBWkbitPersec *prometheus.Desc
ImagingSVGAdevTapframesPersec *prometheus.Desc
ImagingTXBWkbitPersec *prometheus.Desc
RoundTripLatencyms *prometheus.Desc
RXBWkbitPersec *prometheus.Desc
RXBWPeakkbitPersec *prometheus.Desc
RXPacketLossPercent *prometheus.Desc
RXPacketLossPercent_Base *prometheus.Desc
TXBWActiveLimitkbitPersec *prometheus.Desc
TXBWkbitPersec *prometheus.Desc
TXBWLimitkbitPersec *prometheus.Desc
TXPacketLossPercent *prometheus.Desc
TXPacketLossPercent_Base *prometheus.Desc
USBBytesReceived *prometheus.Desc
USBBytesSent *prometheus.Desc
USBRXBWkbitPersec *prometheus.Desc
USBTXBWkbitPersec *prometheus.Desc
}
// newTeradiciPcoipCollector constructs a new teradiciPcoipCollector
func newTeradiciPcoipCollector(logger log.Logger) (Collector, error) {
const subsystem = "teradici_pcoip"
return &teradiciPcoipCollector{
logger: log.With(logger, "collector", subsystem),
AudioBytesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "audio_bytes_received_total"),
"(AudioBytesReceived)",
nil,
nil,
),
AudioBytesSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "audio_bytes_sent_total"),
"(AudioBytesSent)",
nil,
nil,
),
AudioRXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "audio_rx_bw_kbit_persec"),
"(AudioRXBWkbitPersec)",
nil,
nil,
),
AudioTXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "audio_tx_bw_kbit_persec"),
"(AudioTXBWkbitPersec)",
nil,
nil,
),
AudioTXBWLimitkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "audio_tx_bw_limit_kbit_persec"),
"(AudioTXBWLimitkbitPersec)",
nil,
nil,
),
BytesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"),
"(BytesReceived)",
nil,
nil,
),
BytesSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"),
"(BytesSent)",
nil,
nil,
),
PacketsReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"),
"(PacketsReceived)",
nil,
nil,
),
PacketsSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_sent_total"),
"(PacketsSent)",
nil,
nil,
),
RXPacketsLost: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "rx_packets_lost_total"),
"(RXPacketsLost)",
nil,
nil,
),
SessionDurationSeconds: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "session_duration_seconds_total"),
"(SessionDurationSeconds)",
nil,
nil,
),
TXPacketsLost: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "tx_packets_lost_total"),
"(TXPacketsLost)",
nil,
nil,
),
ImagingActiveMinimumQuality: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_active_min_quality"),
"(ImagingActiveMinimumQuality)",
nil,
nil,
),
ImagingApex2800Offload: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_apex2800_offload"),
"(ImagingApex2800Offload)",
nil,
nil,
),
ImagingBytesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_bytes_received_total"),
"(ImagingBytesReceived)",
nil,
nil,
),
ImagingBytesSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_bytes_sent_total"),
"(ImagingBytesSent)",
nil,
nil,
),
ImagingDecoderCapabilitykbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_decoder_capability_kbit_persec"),
"(ImagingDecoderCapabilitykbitPersec)",
nil,
nil,
),
ImagingEncodedFramesPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_encoded_frames_persec"),
"(ImagingEncodedFramesPersec)",
nil,
nil,
),
ImagingMegapixelPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_megapixel_persec"),
"(ImagingMegapixelPersec)",
nil,
nil,
),
ImagingNegativeAcknowledgements: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_negative_acks_total"),
"(ImagingNegativeAcknowledgements)",
nil,
nil,
),
ImagingRXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_rx_bw_kbit_persec"),
"(ImagingRXBWkbitPersec)",
nil,
nil,
),
ImagingSVGAdevTapframesPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_svga_devtap_frames_persec"),
"(ImagingSVGAdevTapframesPersec)",
nil,
nil,
),
ImagingTXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "imaging_tx_bw_kbit_persec"),
"(ImagingTXBWkbitPersec)",
nil,
nil,
),
RoundTripLatencyms: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "round_trip_latency_ms"),
"(RoundTripLatencyms)",
nil,
nil,
),
RXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "rx_bw_kbit_persec"),
"(RXBWkbitPersec)",
nil,
nil,
),
RXBWPeakkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "rx_bw_peak_kbit_persec"),
"(RXBWPeakkbitPersec)",
nil,
nil,
),
RXPacketLossPercent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "rx_packet_loss_percent"),
"(RXPacketLossPercent)",
nil,
nil,
),
RXPacketLossPercent_Base: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "rx_packet_loss_percent_base"),
"(RXPacketLossPercent_Base)",
nil,
nil,
),
TXBWActiveLimitkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "tx_bw_active_limit_kbit_persec"),
"(TXBWActiveLimitkbitPersec)",
nil,
nil,
),
TXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "tx_bw_kbit_persec"),
"(TXBWkbitPersec)",
nil,
nil,
),
TXBWLimitkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "tx_bw_limit_kbit_persec"),
"(TXBWLimitkbitPersec)",
nil,
nil,
),
TXPacketLossPercent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "tx_packet_loss_percent"),
"(TXPacketLossPercent)",
nil,
nil,
),
TXPacketLossPercent_Base: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "tx_packet_loss_percent_base"),
"(TXPacketLossPercent_Base)",
nil,
nil,
),
USBBytesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "usb_bytes_received_total"),
"(USBBytesReceived)",
nil,
nil,
),
USBBytesSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "usb_bytes_sent_total"),
"(USBBytesSent)",
nil,
nil,
),
USBRXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "usb_rx_bw_kbit_persec"),
"(USBRXBWkbitPersec)",
nil,
nil,
),
USBTXBWkbitPersec: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "usb_tx_bw_kbit_persec"),
"(USBTXBWkbitPersec)",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *teradiciPcoipCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collectAudio(ch); err != nil {
_ = level.Error(c.logger).Log("failed collecting teradici session audio metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectGeneral(ch); err != nil {
_ = level.Error(c.logger).Log("failed collecting teradici session general metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectImaging(ch); err != nil {
_ = level.Error(c.logger).Log("failed collecting teradici session imaging metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectNetwork(ch); err != nil {
_ = level.Error(c.logger).Log("failed collecting teradici session network metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectUsb(ch); err != nil {
_ = level.Error(c.logger).Log("failed collecting teradici session USB metrics", "desc", desc, "err", err)
return err
}
return nil
}
type win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics struct {
AudioBytesReceived uint64
AudioBytesSent uint64
AudioRXBWkbitPersec uint64
AudioTXBWkbitPersec uint64
AudioTXBWLimitkbitPersec uint64
}
type win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics struct {
BytesReceived uint64
BytesSent uint64
PacketsReceived uint64
PacketsSent uint64
RXPacketsLost uint64
SessionDurationSeconds uint64
TXPacketsLost uint64
}
type win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics struct {
ImagingActiveMinimumQuality uint32
ImagingApex2800Offload uint32
ImagingBytesReceived uint64
ImagingBytesSent uint64
ImagingDecoderCapabilitykbitPersec uint32
ImagingEncodedFramesPersec uint32
ImagingMegapixelPersec uint32
ImagingNegativeAcknowledgements uint32
ImagingRXBWkbitPersec uint64
ImagingSVGAdevTapframesPersec uint32
ImagingTXBWkbitPersec uint64
}
type win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics struct {
RoundTripLatencyms uint32
RXBWkbitPersec uint64
RXBWPeakkbitPersec uint32
RXPacketLossPercent uint32
RXPacketLossPercent_Base uint32
TXBWActiveLimitkbitPersec uint32
TXBWkbitPersec uint64
TXBWLimitkbitPersec uint32
TXPacketLossPercent uint32
TXPacketLossPercent_Base uint32
}
type win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics struct {
USBBytesReceived uint64
USBBytesSent uint64
USBRXBWkbitPersec uint64
USBTXBWkbitPersec uint64
}
func (c *teradiciPcoipCollector) collectAudio(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric(
c.AudioBytesReceived,
prometheus.CounterValue,
float64(dst[0].AudioBytesReceived),
)
ch <- prometheus.MustNewConstMetric(
c.AudioBytesSent,
prometheus.CounterValue,
float64(dst[0].AudioBytesSent),
)
ch <- prometheus.MustNewConstMetric(
c.AudioRXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].AudioRXBWkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.AudioTXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].AudioTXBWkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.AudioTXBWLimitkbitPersec,
prometheus.GaugeValue,
float64(dst[0].AudioTXBWLimitkbitPersec),
)
return nil, nil
}
func (c *teradiciPcoipCollector) collectGeneral(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric(
c.BytesReceived,
prometheus.CounterValue,
float64(dst[0].BytesReceived),
)
ch <- prometheus.MustNewConstMetric(
c.BytesSent,
prometheus.CounterValue,
float64(dst[0].BytesSent),
)
ch <- prometheus.MustNewConstMetric(
c.PacketsReceived,
prometheus.CounterValue,
float64(dst[0].PacketsReceived),
)
ch <- prometheus.MustNewConstMetric(
c.PacketsSent,
prometheus.CounterValue,
float64(dst[0].PacketsSent),
)
ch <- prometheus.MustNewConstMetric(
c.RXPacketsLost,
prometheus.CounterValue,
float64(dst[0].RXPacketsLost),
)
ch <- prometheus.MustNewConstMetric(
c.SessionDurationSeconds,
prometheus.CounterValue,
float64(dst[0].SessionDurationSeconds),
)
ch <- prometheus.MustNewConstMetric(
c.TXPacketsLost,
prometheus.CounterValue,
float64(dst[0].TXPacketsLost),
)
return nil, nil
}
func (c *teradiciPcoipCollector) collectImaging(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric(
c.ImagingActiveMinimumQuality,
prometheus.GaugeValue,
float64(dst[0].ImagingActiveMinimumQuality),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingApex2800Offload,
prometheus.GaugeValue,
float64(dst[0].ImagingApex2800Offload),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingBytesReceived,
prometheus.CounterValue,
float64(dst[0].ImagingBytesReceived),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingBytesSent,
prometheus.CounterValue,
float64(dst[0].ImagingBytesSent),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingDecoderCapabilitykbitPersec,
prometheus.GaugeValue,
float64(dst[0].ImagingDecoderCapabilitykbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingEncodedFramesPersec,
prometheus.GaugeValue,
float64(dst[0].ImagingEncodedFramesPersec),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingMegapixelPersec,
prometheus.GaugeValue,
float64(dst[0].ImagingMegapixelPersec),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingNegativeAcknowledgements,
prometheus.CounterValue,
float64(dst[0].ImagingNegativeAcknowledgements),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingRXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].ImagingRXBWkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingSVGAdevTapframesPersec,
prometheus.GaugeValue,
float64(dst[0].ImagingSVGAdevTapframesPersec),
)
ch <- prometheus.MustNewConstMetric(
c.ImagingTXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].ImagingTXBWkbitPersec),
)
return nil, nil
}
func (c *teradiciPcoipCollector) collectNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric(
c.RoundTripLatencyms,
prometheus.GaugeValue,
float64(dst[0].RoundTripLatencyms),
)
ch <- prometheus.MustNewConstMetric(
c.RXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].RXBWkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.RXBWPeakkbitPersec,
prometheus.GaugeValue,
float64(dst[0].RXBWPeakkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.RXPacketLossPercent,
prometheus.GaugeValue,
float64(dst[0].RXPacketLossPercent),
)
ch <- prometheus.MustNewConstMetric(
c.RXPacketLossPercent_Base,
prometheus.GaugeValue,
float64(dst[0].RXPacketLossPercent_Base),
)
ch <- prometheus.MustNewConstMetric(
c.TXBWActiveLimitkbitPersec,
prometheus.GaugeValue,
float64(dst[0].TXBWActiveLimitkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.TXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].TXBWkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.TXBWLimitkbitPersec,
prometheus.GaugeValue,
float64(dst[0].TXBWLimitkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.TXPacketLossPercent,
prometheus.GaugeValue,
float64(dst[0].TXPacketLossPercent),
)
ch <- prometheus.MustNewConstMetric(
c.TXPacketLossPercent_Base,
prometheus.GaugeValue,
float64(dst[0].TXPacketLossPercent_Base),
)
return nil, nil
}
func (c *teradiciPcoipCollector) collectUsb(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric(
c.USBBytesReceived,
prometheus.CounterValue,
float64(dst[0].USBBytesReceived),
)
ch <- prometheus.MustNewConstMetric(
c.USBBytesSent,
prometheus.CounterValue,
float64(dst[0].USBBytesSent),
)
ch <- prometheus.MustNewConstMetric(
c.USBRXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].USBRXBWkbitPersec),
)
ch <- prometheus.MustNewConstMetric(
c.USBTXBWkbitPersec,
prometheus.GaugeValue,
float64(dst[0].USBTXBWkbitPersec),
)
return nil, nil
}

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkTeradiciPcoipCollector(b *testing.B) {
benchmarkCollector(b, "teradici_pcoip", newTeradiciPcoipCollector)
}

View File

@@ -7,28 +7,21 @@ import (
"errors"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
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 {
func isConnectionBrokerServer(logger log.Logger) bool {
var dst []Win32_ServerFeature
q := queryAll(&dst)
q := queryAll(&dst, logger)
if err := wmi.Query(q, &dst); err != nil {
return false
}
@@ -37,7 +30,7 @@ func isConnectionBrokerServer() bool {
return true
}
}
log.Debug("host is not a connection broker skipping Connection Broker performance metrics.")
_ = level.Debug(logger).Log("msg", "host is not a connection broker skipping Connection Broker performance metrics.")
return false
}
@@ -46,6 +39,9 @@ func isConnectionBrokerServer() bool {
// 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 {
logger log.Logger
connectionBrokerEnabled bool
LocalSessionCount *prometheus.Desc
ConnectionBrokerPerformance *prometheus.Desc
HandleCount *prometheus.Desc
@@ -65,10 +61,14 @@ type TerminalServicesCollector struct {
WorkingSetPeak *prometheus.Desc
}
// NewTerminalServicesCollector ...
func NewTerminalServicesCollector() (Collector, error) {
// newTerminalServicesCollector ...
func newTerminalServicesCollector(logger log.Logger) (Collector, error) {
const subsystem = "terminal_services"
logger = log.With(logger, "collector", subsystem)
return &TerminalServicesCollector{
logger: logger,
connectionBrokerEnabled: isConnectionBrokerServer(logger),
LocalSessionCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "local_session_count"),
"Number of Terminal Services sessions",
@@ -178,18 +178,18 @@ func NewTerminalServicesCollector() (Collector, error) {
// 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)
_ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectTSSessionCounters(ctx, ch); err != nil {
log.Error("failed collecting terminal services session count metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err)
return err
}
// only collect CollectionBrokerPerformance if host is a Connection Broker
if connectionBrokerEnabled {
if c.connectionBrokerEnabled {
if desc, err := c.collectCollectionBrokerPerformanceCounter(ctx, ch); err != nil {
log.Error("failed collecting Connection Broker performance metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting Connection Broker performance metrics", "desc", desc, "err", err)
return err
}
}
@@ -204,7 +204,7 @@ type perflibTerminalServices struct {
func (c *TerminalServicesCollector) collectTSSessionCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
dst := make([]perflibTerminalServices, 0)
err := unmarshalObject(ctx.perfObjects["Terminal Services"], &dst)
err := unmarshalObject(ctx.perfObjects["Terminal Services"], &dst, c.logger)
if err != nil {
return nil, err
}
@@ -257,10 +257,11 @@ type perflibTerminalServicesSession struct {
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)
err := unmarshalObject(ctx.perfObjects["Terminal Services Session"], &dst, c.logger)
if err != nil {
return nil, err
}
names := make(map[string]bool)
for _, d := range dst {
// only connect metrics for remote named sessions
@@ -268,6 +269,12 @@ func (c *TerminalServicesCollector) collectTSSessionCounters(ctx *ScrapeContext,
if n == "" || n == "services" || n == "console" {
continue
}
// don't add name already present in labels list
if _, ok := names[n]; ok {
continue
}
names[n] = true
ch <- prometheus.MustNewConstMetric(
c.HandleCount,
prometheus.GaugeValue,
@@ -371,7 +378,7 @@ type perflibRemoteDesktopConnectionBrokerCounterset struct {
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)
err := unmarshalObject(ctx.perfObjects["Remote Desktop Connection Broker Counterset"], &dst, c.logger)
if err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkTerminalServicesCollector(b *testing.B) {
benchmarkCollector(b, "terminal_services", NewTerminalServicesCollector)
benchmarkCollector(b, "terminal_services", newTerminalServicesCollector)
}

View File

@@ -27,19 +27,21 @@ import (
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/dimchansky/utfbom"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
const (
FlagTextFileDirectory = "collector.textfile.directory"
)
var (
textFileDirectory = kingpin.Flag(
"collector.textfile.directory",
"Directory to read text files with metrics from.",
).Default(getDefaultPath()).String()
textFileDirectory *string
mtimeDesc = prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "textfile", "mtime_seconds"),
@@ -50,20 +52,28 @@ var (
)
type textFileCollector struct {
logger log.Logger
path string
// Only set for testing to get predictable output.
mtime *float64
}
func init() {
registerCollector("textfile", NewTextFileCollector)
// newTextFileCollectorFlags ...
func newTextFileCollectorFlags(app *kingpin.Application) {
textFileDirectory = app.Flag(
FlagTextFileDirectory,
"Directory to read text files with metrics from.",
).Default(getDefaultPath()).String()
}
// NewTextFileCollector returns a new Collector exposing metrics read from files
// newTextFileCollector returns a new Collector exposing metrics read from files
// in the given textfile directory.
func NewTextFileCollector() (Collector, error) {
func newTextFileCollector(logger log.Logger) (Collector, error) {
const subsystem = "textfile"
return &textFileCollector{
path: *textFileDirectory,
logger: log.With(logger, "collector", subsystem),
path: *textFileDirectory,
}, nil
}
@@ -92,7 +102,7 @@ func duplicateMetricEntry(metricFamilies []*dto.MetricFamily) bool {
return false
}
func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric) {
func (c *textFileCollector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric) {
var valType prometheus.ValueType
var val float64
@@ -108,7 +118,7 @@ func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Me
for _, metric := range metricFamily.Metric {
if metric.TimestampMs != nil {
log.Warnf("Ignoring unsupported custom timestamp on textfile collector metric %v", metric)
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Ignoring unsupported custom timestamp on textfile collector metric %v", metric))
}
labels := metric.GetLabel()
@@ -178,7 +188,7 @@ func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Me
buckets, values...,
)
default:
log.Errorf("unknown metric type for file")
_ = level.Error(c.logger).Log("msg", "unknown metric type for file")
continue
}
if metricType == dto.MetricType_GAUGE || metricType == dto.MetricType_COUNTER || metricType == dto.MetricType_UNTYPED {
@@ -246,7 +256,7 @@ func (c *textFileCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Met
// Iterate over files and accumulate their metrics.
files, err := ioutil.ReadDir(c.path)
if err != nil && c.path != "" {
log.Errorf("Error reading textfile collector directory %q: %s", c.path, err)
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error reading textfile collector directory %q", c.path), "err", err)
error = 1.0
}
@@ -260,27 +270,27 @@ fileLoop:
continue
}
path := filepath.Join(c.path, f.Name())
log.Debugf("Processing file %q", path)
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("Processing file %q", path))
file, err := os.Open(path)
if err != nil {
log.Errorf("Error opening %q: %v", path, err)
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error opening %q: %v", path, err))
error = 1.0
continue
}
var parser expfmt.TextParser
r, encoding := utfbom.Skip(carriageReturnFilteringReader{r: file})
if err = checkBOM(encoding); err != nil {
log.Errorf("Invalid file encoding detected in %s: %s - file must be UTF8", path, err.Error())
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Invalid file encoding detected in %s: %s - file must be UTF8", path, err.Error()))
error = 1.0
continue
}
parsedFamilies, err := parser.TextToMetricFamilies(r)
closeErr := file.Close()
if closeErr != nil {
log.Warnf("Error closing file: %v", err)
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Error closing file"), "err", err)
}
if err != nil {
log.Errorf("Error parsing %q: %v", path, err)
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error parsing %q: %v", path, err))
error = 1.0
continue
}
@@ -292,7 +302,7 @@ fileLoop:
families_array = append(families_array, mf)
for _, m := range mf.Metric {
if m.TimestampMs != nil {
log.Errorf("Textfile %q contains unsupported client-side timestamps, skipping entire file", path)
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Textfile %q contains unsupported client-side timestamps, skipping entire file", path))
error = 1.0
continue fileLoop
}
@@ -305,7 +315,7 @@ fileLoop:
// If duplicate metrics are detected in a *single* file, skip processing of file metrics
if duplicateMetricEntry(families_array) {
log.Errorf("Duplicate metrics detected in file %s. Skipping file processing.", f.Name())
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Duplicate metrics detected in file %s. Skipping file processing.", f.Name()))
error = 1.0
continue
}
@@ -321,11 +331,11 @@ fileLoop:
// If duplicates are detected across *multiple* files, return error.
if duplicateMetricEntry(metricFamilies) {
log.Errorf("Duplicate metrics detected across multiple files")
_ = level.Error(c.logger).Log("msg", "Duplicate metrics detected across multiple files")
error = 1.0
} else {
for _, mf := range metricFamilies {
convertMetricFamily(mf, ch)
c.convertMetricFamily(mf, ch)
}
}

View File

@@ -1,11 +1,12 @@
package collector
import (
"github.com/dimchansky/utfbom"
"io/ioutil"
"strings"
"testing"
"github.com/dimchansky/utfbom"
dto "github.com/prometheus/client_model/go"
)

View File

@@ -3,26 +3,26 @@ package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("thermalzone", NewThermalZoneCollector)
}
// A thermalZoneCollector is a Prometheus collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics
type thermalZoneCollector struct {
logger log.Logger
PercentPassiveLimit *prometheus.Desc
Temperature *prometheus.Desc
ThrottleReasons *prometheus.Desc
}
// NewThermalZoneCollector ...
func NewThermalZoneCollector() (Collector, error) {
// newThermalZoneCollector ...
func newThermalZoneCollector(logger log.Logger) (Collector, error) {
const subsystem = "thermalzone"
return &thermalZoneCollector{
logger: log.With(logger, "collector", subsystem),
Temperature: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "temperature_celsius"),
"(Temperature)",
@@ -54,7 +54,7 @@ func NewThermalZoneCollector() (Collector, error) {
// 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)
_ = level.Error(c.logger).Log("failed collecting thermalzone metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -72,7 +72,7 @@ type Win32_PerfRawData_Counters_ThermalZoneInformation struct {
func (c *thermalZoneCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_Counters_ThermalZoneInformation
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkThermalZoneCollector(b *testing.B) {
benchmarkCollector(b, "thermalzone", NewThermalZoneCollector)
benchmarkCollector(b, "thermalzone", newThermalZoneCollector)
}

View File

@@ -6,16 +6,15 @@ package collector
import (
"errors"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("time", newTimeCollector, "Windows Time Service")
}
// TimeCollector is a Prometheus collector for Perflib counter metrics
type TimeCollector struct {
logger log.Logger
ClockFrequencyAdjustmentPPBTotal *prometheus.Desc
ComputedTimeOffset *prometheus.Desc
NTPClientTimeSourceCount *prometheus.Desc
@@ -24,14 +23,16 @@ type TimeCollector struct {
NTPServerOutgoingResponsesTotal *prometheus.Desc
}
func newTimeCollector() (Collector, error) {
if getWindowsVersion() <= 6.1 {
func newTimeCollector(logger log.Logger) (Collector, error) {
if getWindowsVersion(logger) <= 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"
logger = log.With(logger, "collector", subsystem)
return &TimeCollector{
logger: logger,
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.",
@@ -75,7 +76,7 @@ func newTimeCollector() (Collector, error) {
// 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)
_ = level.Error(c.logger).Log("failed collecting time metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -93,7 +94,7 @@ type windowsTime struct {
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 {
if err := unmarshalObject(ctx.perfObjects["Windows Time Service"], &dst, c.logger); err != nil {
return nil, err
}

View File

@@ -6,17 +6,16 @@ package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
func init() {
registerCollector("vmware", NewVmwareCollector)
}
// A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics
type VmwareCollector struct {
logger log.Logger
MemActive *prometheus.Desc
MemBallooned *prometheus.Desc
MemLimit *prometheus.Desc
@@ -39,10 +38,11 @@ type VmwareCollector struct {
HostProcessorSpeedMHz *prometheus.Desc
}
// NewVmwareCollector constructs a new VmwareCollector
func NewVmwareCollector() (Collector, error) {
// newVmwareCollector constructs a new VmwareCollector
func newVmwareCollector(logger log.Logger) (Collector, error) {
const subsystem = "vmware"
return &VmwareCollector{
logger: log.With(logger, "collector", subsystem),
MemActive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_active_bytes"),
"(MemActiveMB)",
@@ -165,11 +165,11 @@ func NewVmwareCollector() (Collector, error) {
// 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)
_ = level.Error(c.logger).Log("failed collecting vmware memory metrics", "desc", desc, "err", err)
return err
}
if desc, err := c.collectCpu(ch); err != nil {
log.Error("failed collecting vmware cpu metrics:", desc, err)
_ = level.Error(c.logger).Log("failed collecting vmware cpu metrics", "desc", desc, "err", err)
return err
}
return nil
@@ -202,7 +202,7 @@ type Win32_PerfRawData_vmGuestLib_VCPU struct {
func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_vmGuestLib_VMem
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
@@ -291,7 +291,7 @@ func mbToBytes(mb uint64) float64 {
func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_vmGuestLib_VCPU
q := queryAll(&dst)
q := queryAll(&dst, c.logger)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}

1296
collector/vmware_blast.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkVmwareBlastCollector(b *testing.B) {
benchmarkCollector(b, "vmware_blast", newVmwareBlastCollector)
}

View File

@@ -5,5 +5,5 @@ import (
)
func BenchmarkVmwareCollector(b *testing.B) {
benchmarkCollector(b, "vmware", NewVmwareCollector)
benchmarkCollector(b, "vmware", newVmwareCollector)
}

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