Compare commits

...

176 Commits

Author SHA1 Message Date
Jan-Otto Kröpke
bf6688c1fb service: [0.28.x] fix panic with NewWithConfig code path (#1647)
Co-authored-by: Erik Baranowski <erik.r.baranowski@gmail.com>
2024-09-28 10:53:41 +02:00
Jan-Otto Kröpke
9febf1e97c process: fix Access is denied errors (#1599) 2024-08-31 19:37:19 +02:00
Jan-Otto Kröpke
b53d91e048 cpu_info: Extend processor information (#1597) 2024-08-31 12:22:22 +02:00
Jan-Otto Kröpke
a5d1112fcd cache: fix windows_cache_copy_read_hits_total metric (#1591) 2024-08-31 08:25:37 +02:00
Jan-Otto Kröpke
d8f0665bdc process: introduce info metric; removed creating_process_id label from all process metric (click here for more information) (#1592) 2024-08-30 20:19:41 +02:00
Jan-Otto Kröpke
4f6e6e8b77 *: avoid using default wmi client. (#1590) 2024-08-30 00:26:15 +02:00
Jan-Otto Kröpke
3ce25ff1ef mscluster: merge multiple collector into one (Click here for more information) (#1585) 2024-08-29 22:03:05 +02:00
dependabot[bot]
c99ac2c5aa chore(deps): bump github.com/prometheus/client_golang (#1588)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 21:12:58 +02:00
dependabot[bot]
c9510e8c1d chore(deps): bump github.com/Microsoft/hcsshim from 0.12.5 to 0.12.6 (#1587)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 21:12:34 +02:00
Jan-Otto Kröpke
4484e96b66 Update bug_report.yaml
Signed-off-by: Jan-Otto Kröpke <github@jkroepke.de>
2024-08-27 20:33:11 +02:00
Jan-Otto Kröpke
9705ff0a24 Update bug_report.yaml
Signed-off-by: Jan-Otto Kröpke <github@jkroepke.de>
2024-08-27 20:32:05 +02:00
Jan-Otto Kröpke
89c832feb0 chore: pass context aware logger to collectors (#1582) 2024-08-24 19:14:38 +02:00
Jan-Otto Kröpke
fbead0fb79 terminal_services: remove old metric from docs (#1583) 2024-08-24 16:57:34 +02:00
Jan-Otto Kröpke
0f4ef8e781 chore: Update TEXTFILE_DIRS description in README (#1581) 2024-08-22 08:49:10 +02:00
Jan-Otto Kröpke
56709b9638 terminal_services: Avoid duplicate metrics by add session_id (#1576) 2024-08-20 19:24:08 +02:00
dependabot[bot]
2589e56f95 chore(deps): bump github.com/prometheus/client_golang from 1.19.1 to 1.20.0 (#1574)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-19 17:23:39 +02:00
Jan-Otto Kröpke
4e460bc24c exchange: enable all collectors as default (#1572) 2024-08-17 21:00:05 +02:00
Jan-Otto Kröpke
b5ceb27836 time: fix windows_time_computed_time_offset_seconds docs (#1571)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-08-17 20:07:25 +02:00
Jan-Otto Kröpke
f6965b10f4 mssql: fix nil panic, if YAML file is used a configuration (#1570) 2024-08-14 08:28:46 +02:00
dependabot[bot]
d7f052fb27 chore(deps): bump golang.org/x/sys from 0.23.0 to 0.24.0 (#1566)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 14:24:45 +02:00
Jan-Otto Kröpke
ca4ad46e2d scheduled_task: do not report windows_scheduled_task_last_result for task that never run before (#1562) 2024-08-11 15:47:59 +02:00
Jan-Otto Kröpke
dd956c986b chore: Refactor Config Collector API (#1558) 2024-08-11 13:28:39 +02:00
Jan-Otto Kröpke
7bb16d2f5b textfile: disable collector by default (#1560) 2024-08-11 12:57:14 +02:00
Jan-Otto Kröpke
e478843faa chore: deprecate teradici_pcoip and vmware_blast collector (#1559) 2024-08-11 11:32:01 +02:00
Jan-Otto Kröpke
9b02e4a0ea chore: enable more linter (#1557) 2024-08-10 22:05:33 +02:00
Jan-Otto Kröpke
27a3553dac *: cleanup collector API 3 (#1556) 2024-08-10 20:02:07 +02:00
Jan-Otto Kröpke
b2548e02bd installer: do not enable V1 counters by default (#1555) 2024-08-10 14:39:11 +02:00
Jan-Otto Kröpke
0ada09ee3c *: Collector API cleanup 2 (#1552) 2024-08-05 23:40:32 +02:00
Jan-Otto Kröpke
3c360c05f3 Update pr-check.yaml
Signed-off-by: Jan-Otto Kröpke <github@jkroepke.de>
2024-08-05 20:01:59 +02:00
PrometheusBot
fe8e72e38f Synchronize common files from prometheus/prometheus (#1551) 2024-08-05 20:01:08 +02:00
dependabot[bot]
2d091c7187 chore(deps): bump golang.org/x/sys from 0.22.0 to 0.23.0 (#1549)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 15:57:18 +02:00
dependabot[bot]
b4999eda4b chore(deps): bump actions/checkout from 3 to 4 (#1550)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 15:57:10 +02:00
Jan-Otto Kröpke
d1e3a63f93 *: cleanup collector API 1 (#1547) 2024-08-05 15:50:41 +02:00
Jan-Otto Kröpke
dffc53eff8 terminal_services: Fix "The operation completed successfully." error (#1548) 2024-08-05 15:31:29 +02:00
Jan-Otto Kröpke
9026bc02ff Update pr-check.yaml
Signed-off-by: Jan-Otto Kröpke <github@jkroepke.de>
2024-08-05 13:28:39 +02:00
Jan-Otto Kröpke
8f2a45d832 printer: expose config struct properties (#1545) 2024-07-31 18:02:21 +02:00
Jan-Otto Kröpke
6cecc735df logical_disk: Fix failed to get disk ID for dynamic volumes (#1544) 2024-07-31 15:02:29 +02:00
Jan-Otto Kröpke
4635be8c0c fix: CPU Collector % Cx Time mismatch (#1542) 2024-07-29 20:19:03 +02:00
dependabot[bot]
4cc7d108e3 chore(deps): bump actions/stale from 8 to 9 (#1541)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 18:11:13 +02:00
Jan-Otto Kröpke
d878423cb6 chore: Add label configuration (#1540) 2024-07-29 18:04:08 +02:00
Jan-Otto Kröpke
a93bbe4ac2 ci: disable hostimage image (#1539) 2024-07-29 09:28:44 +02:00
Jan-Otto Kröpke
33efbdfbcb try fix push by bump dependencies (#1537) 2024-07-24 16:24:01 +02:00
Jan-Otto Kröpke
8db705e67a fix push (#1536) 2024-07-24 16:01:22 +02:00
Jan-Otto Kröpke
7044b556c2 Add terminal service session info (#1525) 2024-07-24 11:18:08 +02:00
Jan-Otto Kröpke
fa8d28c181 license collector (#1524) 2024-07-23 13:02:25 +02:00
Jan-Otto Kröpke
64c8423e61 printer collector: Use ENUM pattern for printer status (#1500) 2024-07-23 13:02:09 +02:00
Jan-Otto Kröpke
e2e1141973 logical disk: Fix metrics for non drive letter disks (#1498) 2024-07-23 13:01:30 +02:00
Jan-Otto Kröpke
31bb6d03ee fix default value of collectors.dfsr.sources-enabled (#1506) 2024-07-22 15:21:19 +02:00
Jan-Otto Kröpke
caee5a05fe Add hostprocess image builds (#1507) 2024-07-22 15:21:05 +02:00
FRFlo
578b16b448 fix(README.md): Corrected image links (#1533) 2024-07-22 15:20:48 +02:00
dependabot[bot]
1da96a4f3c chore(deps): bump github.com/Microsoft/hcsshim from 0.12.4 to 0.12.5 (#1535)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 14:10:57 +02:00
jacbo0112
fddb92a9d5 Update collector.diskdrive.md (#1502) 2024-07-20 20:09:36 +02:00
jacbo0112
2cda7b3f4d Update README.md (#1516) 2024-07-20 18:25:14 +02:00
dependabot[bot]
b44b0413bb chore(deps): bump golang.org/x/sys from 0.21.0 to 0.22.0 (#1531)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-08 15:10:23 +02:00
dependabot[bot]
f4e360218f chore(deps): bump github.com/prometheus/common from 0.54.0 to 0.55.0 (#1530)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 14:54:05 +02:00
Andrey Burtasov
4efb502aab Add label user to process collector (#1472)
Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de>
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-06-17 11:05:52 +02:00
Jan-Otto Kröpke
a4a5ac464a Service V2 collector (#1497) 2024-06-14 08:59:11 +02:00
Jan-Otto Kröpke
1b438cdb82 Fix timezone caching issues (#1499) 2024-06-14 08:58:58 +02:00
dependabot[bot]
f0d0545d34 chore(deps): bump github.com/prometheus/common from 0.53.0 to 0.54.0 (#1519)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 16:00:11 +02:00
dependabot[bot]
d05effdda5 chore(deps): bump github.com/Microsoft/hcsshim from 0.12.3 to 0.12.4 (#1518)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 15:33:55 +02:00
dependabot[bot]
2d29f0004b chore(deps): bump golang.org/x/sys from 0.20.0 to 0.21.0 (#1517)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 15:33:36 +02:00
jacbo0112
d94640b6f8 Update README.md (#1501) 2024-06-07 18:46:02 +02:00
PrometheusBot
26e05e9d07 Synchronize common files from prometheus/prometheus (#1513) 2024-06-06 20:15:23 +02:00
PrometheusBot
9eec34d2f1 Synchronize common files from prometheus/prometheus (#1512)
Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de>
2024-06-06 17:18:14 +02:00
Benjamin Nash
b8b164bfca Fix omission of RemoteFX Graphics metrics (#1511)
Co-authored-by: PrometheusBot <prometheus-team@googlegroups.com>
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>
Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de>
2024-06-06 16:30:24 +02:00
PrometheusBot
7775ef95e6 Synchronize common files from prometheus/prometheus (#1510) 2024-06-03 20:19:25 +02:00
Ben Reedy
eeaefba0d7 feat: allow setting of exporter process priority (#1488) 2024-05-17 22:51:33 +02:00
Jan-Otto Kröpke
b2ab542b6d Fix docker push on release (#1496) 2024-05-17 19:38:51 +02:00
Soheil Rahmat
f85866ce1e Add Printer Exporter (#1485) 2024-05-17 18:47:32 +02:00
jacbo0112
9e24ce8f74 Update collector.diskdrive.md (#1495) 2024-05-17 07:17:26 +02:00
Darin Truckenmiller
9c65b7464f Add new RemoteFX network metrics (#1489) 2024-05-15 23:13:02 +02:00
Jan-Otto Kröpke
c242fae84c Remove push to quay.io (#1490) 2024-05-15 02:38:01 +02:00
Ben Reedy
c85cfaadde Merge pull request #1487 from breed808/ci
Additional CI linters
2024-05-15 07:13:19 +10:00
Ben Reedy
d6c24d1500 feat(ci): enable useful golangci output
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 07:07:32 +10:00
Ben Reedy
8b515ba54a feat(ci): enable promlinter
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 06:19:44 +10:00
Ben Reedy
a2575b93a9 feat(ci): add unused linter
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 06:19:39 +10:00
Ben Reedy
965be334bc ci: reverse default linter logic
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 06:19:34 +10:00
Ben Reedy
1239fbf719 perf: run perfsprint fixes
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 06:19:29 +10:00
Ben Reedy
a49dee606b perf: pre-allocate slices
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 06:19:24 +10:00
Ben Reedy
c713bed4e3 chore(ci): update golangci-lint to latest version
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 06:19:19 +10:00
Ben Reedy
99b6d215a2 chore(ci): order linters alphabetically
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-05-15 06:19:14 +10:00
dependabot[bot]
6d91cdc9fc chore(deps): bump github.com/prometheus/client_golang from 1.19.0 to 1.19.1 (#1484)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-13 13:43:14 +02:00
PrometheusBot
c9ebc3e153 Synchronize common files from prometheus/prometheus (#1483) 2024-05-12 21:02:50 +02:00
Jan-Otto Kröpke
c99cf180d0 fix: makefile variable override (#1482) 2024-05-12 12:25:06 +02:00
Jan-Otto Kröpke
6e14d4e53f fix: release build again again (#1481) 2024-05-12 10:58:09 +02:00
PrometheusBot
48e7c34539 Synchronize common files from prometheus/prometheus (#1453)
Co-authored-by: Ben Kochie <superq@gmail.com>
2024-05-12 10:57:45 +02:00
Jan-Otto Kröpke
6497a1a5cc fix: release build again (#1480) 2024-05-12 10:04:33 +02:00
Jan-Otto Kröpke
4e1987686b fix: release build again (#1479) 2024-05-12 01:46:05 +02:00
Jan-Otto Kröpke
dc4bc8e163 fix: release build (#1478) 2024-05-12 01:27:54 +02:00
Jan-Otto Kröpke
b8747045ce Enable process V1 performance counters by default (#1477) 2024-05-12 00:24:52 +02:00
Jan-Otto Kröpke
00781dbbee scheduled_task: Move OLE connection to collect function (#1451) 2024-05-12 00:22:33 +02:00
Jan-Otto Kröpke
195cfa8d5c Add: push docker images to dockerhub and quay.io (#1469) 2024-05-11 23:06:22 +02:00
rob-scheepens
be25d79b71 Implementing smbclient collector (#1408)
Co-authored-by: Bob Allegretti <ballegre@gmail.com>
Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de>
Co-authored-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-05-11 18:06:03 +02:00
Ben Reedy
9bf84fb10c Remove unused *prometheus.Desc return value from collectors collect() function (#1475) 2024-05-11 12:05:45 +02:00
Jan-Otto Kröpke
b977c8484b Remove landing page (#1471) 2024-05-11 09:41:59 +02:00
Jan-Otto Kröpke
13ebec0195 fix: release builds (#1474) 2024-05-09 15:32:26 +02:00
Jan-Otto Kröpke
cc89ae33a4 fix: release builds (#1468) 2024-05-07 13:23:43 +02:00
dependabot[bot]
215032a111 chore(deps): bump golang.org/x/sys from 0.19.0 to 0.20.0 (#1464)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:02:38 +02:00
Jan-Otto Kröpke
a2fe96fbc8 perflib: enrich error message (#1460) 2024-05-03 07:51:38 +02:00
Jan-Otto Kröpke
7d8cf59dac iis: Add IIS info metric (#1450) 2024-05-03 07:51:29 +02:00
Jan-Otto Kröpke
de8a1ebbfe Do not add "--web.listen-address" to service if default values are provided (#1452) 2024-05-03 07:30:48 +02:00
Jan-Otto Kröpke
5ff820cfd0 Ability to disable debug endpoints (#1448) 2024-05-03 07:30:40 +02:00
Jan-Otto Kröpke
8f6a1e3f07 Implement a Windows application manifest (#1445) 2024-05-03 07:30:31 +02:00
dependabot[bot]
f6b91e5cb0 chore(deps): bump github.com/prometheus/common from 0.52.3 to 0.53.0 (#1455)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-25 08:58:06 +02:00
Andrey Burtasov
f21c119c74 Add label volume_name to logical_disk collector (#1442) 2024-04-25 08:57:38 +02:00
Jan-Otto Kröpke
e7464d9fcf Merge pull request #1456 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.12.3 2024-04-23 09:46:52 +02:00
dependabot[bot]
87d1a59a57 chore(deps): bump github.com/Microsoft/hcsshim from 0.12.2 to 0.12.3
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.2 to 0.12.3.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.2...v0.12.3)

---
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>
2024-04-22 11:56:02 +00:00
Jan-Otto Kröpke
b1c272a996 Merge pull request #1395 from webalexeu/feat/add_owner_node 2024-04-21 08:51:15 +02:00
Jan-Otto Kröpke
fdf6f33941 Merge branch 'master' into feat/add_owner_node 2024-04-21 08:47:43 +02:00
Jan-Otto Kröpke
72e7096110 Merge pull request #1447 from jkroepke/setup-no-firewall 2024-04-21 08:47:15 +02:00
Jan-Otto Kröpke
658fbd92ab Merge pull request #1446 from jkroepke/fix-windows2012 2024-04-21 08:46:44 +02:00
Jan-Otto Kröpke
d503ae05d4 Restore Windows 2012 support.
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-04-20 23:31:20 +02:00
Jan-Otto Kröpke
c8b06e86b0 installer: Disable Windows Firewall Exception by default. Can be re-enabled with ADD_FIREWALL_EXCEPTION=yes
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2024-04-20 23:30:48 +02:00
Jan-Otto Kröpke
21a64b1a62 Merge pull request #1392 from breed808/filtered_metrics 2024-04-20 21:35:48 +02:00
Jan-Otto Kröpke
6a15aff837 Merge pull request #1402 from simon04/patch-2 2024-04-20 21:26:01 +02:00
Jan-Otto Kröpke
802f0df07a Merge pull request #1401 from simon04/patch-1 2024-04-20 21:25:44 +02:00
Jan-Otto Kröpke
08c67def1e Merge pull request #1444 from prometheus-community/dependabot/go_modules/golang.org/x/net-0.23.0 2024-04-20 21:24:17 +02:00
dependabot[bot]
65c9009db6 chore(deps): bump golang.org/x/net from 0.22.0 to 0.23.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.22.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.22.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 13:26:58 +00:00
Ben Reedy
8e2e867b11 Merge pull request #1441 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.52.3
chore(deps): bump github.com/prometheus/common from 0.52.2 to 0.52.3
2024-04-16 14:16:20 +10:00
dependabot[bot]
7a201e0c16 chore(deps): bump github.com/prometheus/common from 0.52.2 to 0.52.3
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.52.2 to 0.52.3.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.52.2...v0.52.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 11:05:01 +00:00
Ben Reedy
0ebb2d36e8 Merge pull request #1436 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.12.2
chore(deps): bump github.com/Microsoft/hcsshim from 0.11.4 to 0.12.2
2024-04-10 06:35:49 +10:00
dependabot[bot]
3a2c61c19d chore(deps): bump github.com/Microsoft/hcsshim from 0.11.4 to 0.12.2
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.11.4 to 0.12.2.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.4...v0.12.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-09 20:32:11 +00:00
Ben Reedy
8a1972162a Merge pull request #1438 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_model-0.6.1
chore(deps): bump github.com/prometheus/client_model from 0.6.0 to 0.6.1
2024-04-10 06:31:15 +10:00
dependabot[bot]
032b1f5e88 chore(deps): bump github.com/prometheus/client_model from 0.6.0 to 0.6.1
Bumps [github.com/prometheus/client_model](https://github.com/prometheus/client_model) from 0.6.0 to 0.6.1.
- [Release notes](https://github.com/prometheus/client_model/releases)
- [Commits](https://github.com/prometheus/client_model/compare/v0.6.0...v0.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-09 20:26:11 +00:00
Ben Reedy
1daaccceaf Merge pull request #1439 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.52.2
chore(deps): bump github.com/prometheus/common from 0.49.0 to 0.52.2
2024-04-10 06:25:20 +10:00
Ben Reedy
154dec5f4c chore(deps): bump github.com/prometheus/common from 0.49.0 to 0.52.2
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.49.0 to 0.52.2.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.49.0...v0.52.2)

---
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>
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-04-10 06:20:48 +10:00
Ben Reedy
dbb890c00f Merge pull request #1440 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.19.0
chore(deps): bump golang.org/x/sys from 0.17.0 to 0.19.0
2024-04-10 05:58:31 +10:00
dependabot[bot]
1515623618 chore(deps): bump golang.org/x/sys from 0.17.0 to 0.19.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.17.0 to 0.19.0.
- [Commits](https://github.com/golang/sys/compare/v0.17.0...v0.19.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>
2024-04-08 11:12:03 +00:00
Jan-Otto Kröpke
96c1412a5b Merge pull request #1431 from prometheus-community/dependabot/go_modules/google.golang.org/protobuf-1.33.0 2024-03-18 19:06:12 +01:00
dependabot[bot]
e0bdc9828c chore(deps): bump google.golang.org/protobuf from 1.32.0 to 1.33.0
Bumps google.golang.org/protobuf from 1.32.0 to 1.33.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-13 23:27:45 +00:00
Ben Reedy
6e9daff6ed fix: Apply query filter to metrics
Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-03-05 06:33:15 +10:00
Ben Reedy
91da7562e1 Merge pull request #1423 from prometheus-community/dependabot/go_modules/github.com/stretchr/testify-1.9.0
chore(deps): bump github.com/stretchr/testify from 1.8.4 to 1.9.0
2024-03-05 06:32:09 +10:00
dependabot[bot]
c238bbcaf2 chore(deps): bump github.com/stretchr/testify from 1.8.4 to 1.9.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.4 to 1.9.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 20:28:09 +00:00
Ben Reedy
c382d0c217 Merge pull request #1422 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.49.0
chore(deps): bump github.com/prometheus/common from 0.48.0 to 0.49.0
2024-03-05 06:27:06 +10:00
dependabot[bot]
9d1c9fb012 chore(deps): bump github.com/prometheus/common from 0.48.0 to 0.49.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.48.0 to 0.49.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.48.0...v0.49.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>
2024-03-04 20:21:28 +00:00
Ben Reedy
f3ef7583fe Merge pull request #1421 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_golang-1.19.0
chore(deps): bump github.com/prometheus/client_golang from 1.18.0 to 1.19.0
2024-03-05 06:19:24 +10:00
dependabot[bot]
f37d4d7921 chore(deps): bump github.com/prometheus/client_golang
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.18.0 to 1.19.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.18.0...v1.19.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>
2024-03-04 11:46:33 +00:00
Jan-Otto Kröpke
39ab9faa6a Merge pull request #1418 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.48.0 2024-02-26 13:09:25 +01:00
dependabot[bot]
ac7c98e57e chore(deps): bump github.com/prometheus/common from 0.47.0 to 0.48.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.47.0 to 0.48.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.47.0...v0.48.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>
2024-02-26 11:54:34 +00:00
Jan-Otto Kröpke
377fec7b55 Merge pull request #1416 from jaco-van-zyl-derivco/master 2024-02-22 13:20:56 +01:00
jaco-van-zyl-derivco
548b970288 Fix collector.process.iis flag
Signed-off-by: Jaco van Zyl <mail@jaco.vanzyl@derivco.co.im>

Signed-off-by: jaco-van-zyl-derivco <104196755+jaco-van-zyl-derivco@users.noreply.github.com>
2024-02-22 12:02:59 +00:00
Jan-Otto Kröpke
a02d0257b3 Merge pull request #1410 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.47.0 2024-02-19 22:26:22 +01:00
dependabot[bot]
477ec0df50 chore(deps): bump github.com/prometheus/common from 0.46.0 to 0.47.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.46.0 to 0.47.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.46.0...v0.47.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>
2024-02-19 13:58:07 +00:00
Jan-Otto Kröpke
2a88229a0e Merge pull request #1411 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_model-0.6.0 2024-02-19 14:57:26 +01:00
dependabot[bot]
3cbf5dc085 chore(deps): bump github.com/prometheus/client_model from 0.5.0 to 0.6.0
Bumps [github.com/prometheus/client_model](https://github.com/prometheus/client_model) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/prometheus/client_model/releases)
- [Commits](https://github.com/prometheus/client_model/compare/v0.5.0...v0.6.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>
2024-02-19 11:33:18 +00:00
Simon Legner
c4a4da07f8 Fix typo "Labelled"
Signed-off-by: Simon Legner <Simon.Legner@gmail.com>
2024-02-17 10:23:11 +01:00
Simon Legner
e2ea99fadd Fix typo "Privileged"
Signed-off-by: Simon Legner <Simon.Legner@gmail.com>
2024-02-17 10:23:03 +01:00
Jan-Otto Kröpke
6eebfcce57 Merge pull request #1409 from Winter-py/collector.mssql.md 2024-02-16 19:50:04 +01:00
Steven Owatemi
f97ac3fb66 Update collector.mssql.md
Signed-off-by: Steven Owatemi <isosteven@gmail.com>
2024-02-16 16:48:22 +00:00
webalexeu
7f7239f404 Merge branch 'prometheus-community:master' into feat/add_owner_node 2024-02-16 14:50:55 +01:00
Alexandre JARDON
8d1d552351 Create dedicated metric for owner_node
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:56:08 +01:00
Alexandre JARDON
233470cdf0 Add owner_node on resource and resourcegroup for mscluster
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:55:18 +01:00
dependabot[bot]
67fca296bf chore(deps): bump golang.org/x/sys from 0.16.0 to 0.17.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/sys/compare/v0.16.0...v0.17.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>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Ben Reedy
143ab2247a Update README.md
Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de>
Signed-off-by: Ben Reedy <breed808@users.noreply.github.com>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Ben Reedy
7635e6e094 docs!: Remove support for EOL Windows versions
Microsoft currently support Windows Server 2016 or newer, and Windows 10
and Windows 11 (21HR or later). Dropping support for end-of-life Windows
Server versions will reduce maintenance overhead for project
maintainers.

Signed-off-by: Ben Reedy <breed808@breed808.com>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
dependabot[bot]
9541560e43 chore(deps): bump github.com/yusufpapurcu/wmi from 1.2.3 to 1.2.4
Bumps [github.com/yusufpapurcu/wmi](https://github.com/yusufpapurcu/wmi) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/yusufpapurcu/wmi/releases)
- [Commits](https://github.com/yusufpapurcu/wmi/compare/v1.2.3...v1.2.4)

---
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>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
dinifarb
941019ebc9 fix(#1390): global kingpin instead of app var
Signed-off-by: dinifarb <andreas.vogt89@bluewin.ch>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Alexandre JARDON
5ef7c1f0e9 Adapat documentation based on new metric
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Alexandre JARDON
9b5568354c Create dedicated metric for owner_node
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Alexandre JARDON
eab87292c1 Add examples
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Alexandre JARDON
6ca67f7aa2 Add owner_node on resource and resourcegroup for mscluster
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
dependabot[bot]
688ea45e7e chore(deps): bump github.com/containerd/containerd from 1.7.0 to 1.7.11
Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.0 to 1.7.11.
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v1.7.0...v1.7.11)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
dependabot[bot]
4032b7f610 chore(deps): bump github.com/prometheus/common from 0.45.0 to 0.46.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.45.0 to 0.46.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.45.0...v0.46.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>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Dinifarb
e2ceb0d46d fix:(#1382): update TextfileDirFlag to TextfileDirsFlag
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Dinifarb
d07845ca08 fix:(#1382): rename TEXTFILE_DIR to TEXTFILE_DIRS
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
Signed-off-by: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com>
2024-02-16 08:54:06 +01:00
Jan-Otto Kröpke
b5284aca85 Merge pull request #1405 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.17.0 2024-02-12 12:50:17 +01:00
dependabot[bot]
5c1f19d4bc chore(deps): bump golang.org/x/sys from 0.16.0 to 0.17.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/sys/compare/v0.16.0...v0.17.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>
2024-02-12 11:15:08 +00:00
Ben Reedy
c83da9a2f0 Merge pull request #1396 from breed808/supported_operating_systems
docs!: Remove support for EOL Windows versions
2024-02-02 05:40:53 +10:00
Ben Reedy
b09b8a9c36 Update README.md
Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de>
Signed-off-by: Ben Reedy <breed808@users.noreply.github.com>
2024-02-02 05:40:16 +10:00
Jan-Otto Kröpke
265c12b28e Merge pull request #1399 from prometheus-community/dependabot/go_modules/github.com/yusufpapurcu/wmi-1.2.4 2024-01-29 12:44:37 +01:00
dependabot[bot]
2be970e652 chore(deps): bump github.com/yusufpapurcu/wmi from 1.2.3 to 1.2.4
Bumps [github.com/yusufpapurcu/wmi](https://github.com/yusufpapurcu/wmi) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/yusufpapurcu/wmi/releases)
- [Commits](https://github.com/yusufpapurcu/wmi/compare/v1.2.3...v1.2.4)

---
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>
2024-01-29 11:04:27 +00:00
Ben Reedy
2103e7e1b5 Merge pull request #1397 from DiniFarb/issue_#1390
fix(#1390): global kingpin instead of app var
2024-01-29 17:35:12 +10:00
dinifarb
09c0e47fde fix(#1390): global kingpin instead of app var
Signed-off-by: dinifarb <andreas.vogt89@bluewin.ch>
2024-01-29 07:56:59 +01:00
Ben Reedy
e19b8959c4 docs!: Remove support for EOL Windows versions
Microsoft currently support Windows Server 2016 or newer, and Windows 10
and Windows 11 (21HR or later). Dropping support for end-of-life Windows
Server versions will reduce maintenance overhead for project
maintainers.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2024-01-27 08:37:14 +10:00
Ben Reedy
21a7beaee6 Merge pull request #1367 from prometheus-community/dependabot/go_modules/github.com/containerd/containerd-1.7.11
chore(deps): bump github.com/containerd/containerd from 1.7.0 to 1.7.11
2024-01-17 05:47:35 +10:00
dependabot[bot]
a32f83a6de chore(deps): bump github.com/containerd/containerd from 1.7.0 to 1.7.11
Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.0 to 1.7.11.
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v1.7.0...v1.7.11)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 11:15:19 +00:00
162 changed files with 11848 additions and 9112 deletions

6
.editorconfig Normal file
View File

@@ -0,0 +1,6 @@
root = true
[*.wxs]
indent_style = space
indent_size = 2

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
*.go text eol=lf
*.sh text eol=lf
Makefile text eol=lf

92
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@@ -0,0 +1,92 @@
name: 🐞 Bug
description: Something is not working as indended.
labels: [ 🐞 bug ]
body:
- type: markdown
attributes:
value: Thanks for taking the time to fill out this bug report!
- type: markdown
attributes:
value: |-
> [!NOTE]
> If you encounter "Counter not found" issues, try to re-build the performance counter first.
```
PS C:\WINDOWS\system32> cd c:\windows\system32
PS C:\windows\system32> lodctr /R
Error: Unable to rebuild performance counter setting from system backup store, error code is 2
PS C:\windows\system32> cd ..
PS C:\windows> cd syswow64
PS C:\windows\syswow64> lodctr /R
Info: Successfully rebuilt performance counter setting from system backup store
PS C:\windows\syswow64> winmgmt.exe /RESYNCPERF
```
----
- type: textarea
attributes:
label: Current Behavior
description: A concise description of what you're experiencing.
placeholder: |
When I do <X>, <Y> happens and I see the error message attached below:
```...```
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A concise description of what you expected to happen.
placeholder: When I do <X>, <Z> should happen instead.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. In this environment...
2. With this config...
3. Run '...'
4. See error...
render: Markdown
validations:
required: false
- type: textarea
attributes:
label: Environment
description: |
examples:
- **windows_exporter Version**: 0.26
- **Windows Server Version**: 2019
value: |
- windows_exporter Version:
- Windows Server Version:
validations:
required: true
- type: textarea
attributes:
label: windows_exporter logs
description: |
Log of windows_exporter.
⚠️ Without proving logs, we unable to assist here. ⚠️
render: shell
validations:
required: true
- type: textarea
attributes:
label: Anything else?
description: |
Links? References? Anything that will give us more context about the issue you are encountering!
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

41
.github/ISSUE_TEMPLATE/enhancement.yaml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: ✨ Enhancement / Feature / Task
description: Some feature is missing or incomplete.
labels: [ ✨ enhancement ]
body:
- type: textarea
attributes:
label: Problem Statement
description: Without specifying a solution, describe what the project is missing today.
placeholder: |
The rotating project logo has a fixed size and color.
There is no way to make it larger and more shiny.
validations:
required: false
- type: textarea
attributes:
label: Proposed Solution
description: Describe the proposed solution to the problem above.
placeholder: |
- Implement 2 new flags CLI: ```--logo-color=FFD700``` and ```--logo-size=100```
- Let these flags control the size of the rotating project logo.
validations:
required: false
- type: textarea
attributes:
label: Additional information
placeholder: |
We considered adjusting the logo size to the phase of the moon, but there was no
reliable data source in air-gapped environments.
validations:
required: false
- type: textarea
attributes:
label: Acceptance Criteria
placeholder: |
- [ ] As a user, I can control the size of the rotating logo using a CLI flag.
- [ ] As a user, I can control the color of the rotating logo using a CLI flag.
- [ ] Defaults are reasonably set.
- [ ] New settings are appropriately documented.
- [ ] No breaking change for current users of the rotating logo feature.
validations:
required: false

27
.github/ISSUE_TEMPLATE/question.yaml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: ❓ Question
description: Something is not clear.
labels: [ ❓ question ]
body:
- type: textarea
attributes:
label: Problem Statement
description: Without specifying a solution, describe what the project is missing today.
placeholder: |
The rotating project logo has a fixed size and color.
There is no way to make it larger and more shiny.
validations:
required: false
- type: textarea
attributes:
label: Environment
description: |
examples:
- **windows_exporter Version**: 0.26
- **Windows Server Version**: 2019
value: |
- windows_exporter Version:
- Windows Server Version:
validations:
required: true

View File

@@ -1,6 +1,15 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "🛠️ dependencies"
- package-ecosystem: "gomod" - package-ecosystem: "gomod"
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"
labels:
- "🛠️ dependencies"

23
.github/release.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
changelog:
exclude:
labels:
- chore
categories:
- title: 💥 Breaking Changes
labels:
- 💥 breaking-change
- title: ✨ Exciting New Features
labels:
- ✨ enhancement
- title: 🐞 Bug Fixes
labels:
- 🐞 bug
- title: 🛠️ Dependencies
labels:
- 🛠️ dependencies
- title: 📖 Documentation
labels:
- 📖 docs
- title: Other Changes
labels:
- "*"

View File

@@ -0,0 +1,57 @@
---
name: Push README to Docker Hub
on:
push:
paths:
- "README.md"
- "README-containers.md"
- ".github/workflows/container_description.yml"
branches: [ main, master ]
permissions:
contents: read
jobs:
PushDockerHubReadme:
runs-on: ubuntu-latest
name: Push README to Docker Hub
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
steps:
- name: git checkout
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- name: Set docker hub repo name
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
- name: Push README to Dockerhub
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
env:
DOCKER_USER: ${{ secrets.DOCKER_HUB_LOGIN }}
DOCKER_PASS: ${{ secrets.DOCKER_HUB_PASSWORD }}
with:
destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
provider: dockerhub
short_description: ${{ env.DOCKER_REPO_NAME }}
# Empty string results in README-containers.md being pushed if it
# exists. Otherwise, README.md is pushed.
readme_file: ''
PushQuayIoReadme:
runs-on: ubuntu-latest
name: Push README to quay.io
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
steps:
- name: git checkout
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- name: Set quay.io org name
run: echo "DOCKER_REPO=$(echo quay.io/${GITHUB_REPOSITORY_OWNER} | tr -d '-')" >> $GITHUB_ENV
- name: Set quay.io repo name
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
- name: Push README to quay.io
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
env:
DOCKER_APIKEY: ${{ secrets.QUAY_IO_API_TOKEN }}
with:
destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
provider: quay
# Empty string results in README-containers.md being pushed if it
# exists. Otherwise, README.md is pushed.
readme_file: ''

View File

@@ -30,8 +30,8 @@ jobs:
test: test:
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/setup-go@v4 - uses: actions/setup-go@v5
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
@@ -44,7 +44,6 @@ jobs:
Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath . Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath .
Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin" Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin"
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.2.0
# GOPATH\bin dir must be appended to PATH else the `promu` command won't be found # GOPATH\bin dir must be appended to PATH else the `promu` command won't be found
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
@@ -54,8 +53,8 @@ jobs:
promtool: promtool:
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/setup-go@v4 - uses: actions/setup-go@v5
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
@@ -69,8 +68,6 @@ jobs:
Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath . Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath .
Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin" Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin"
# No binaries available so build from source
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.2.0
# GOPATH\bin dir must be appended to PATH else the `promu` command won't be found # GOPATH\bin dir must be appended to PATH else the `promu` command won't be found
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
@@ -95,20 +92,13 @@ jobs:
git config --global core.autocrlf false git config --global core.autocrlf false
git config --global core.eol lf git config --global core.eol lf
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/setup-go@v4 - uses: actions/setup-go@v5
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@v6
with: with:
version: v1.55.2 version: v1.60
args: "--timeout=5m" args: "--timeout=5m --max-same-issues=0"
# golangci-lint action doesn't always provide helpful output, so re-run without the action for
# better output of the problem.
# The cache from the golangci-lint step is re-used here, so this step should finish quickly.
- name: errors
if: ${{ failure() }}
run: golangci-lint run --timeout=5m -c .golangci.yaml

48
.github/workflows/pr-check.yaml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Validate Pull Request
on:
pull_request:
types:
- opened
- reopened
- synchronize
- labeled
- unlabeled
jobs:
required-labels-missing:
name: required labels missing
runs-on: ubuntu-latest
steps:
- name: check
if: >-
!contains(github.event.pull_request.labels.*.name, '💥 breaking-change')
&& !contains(github.event.pull_request.labels.*.name, '✨ enhancement')
&& !contains(github.event.pull_request.labels.*.name, '🐞 bug')
&& !contains(github.event.pull_request.labels.*.name, '📖 docs')
&& !contains(github.event.pull_request.labels.*.name, 'chore')
&& !contains(github.event.pull_request.labels.*.name, '🛠️ dependencies')
run: >-
echo One of the following labels is missing on this PR:
breaking-change
enhancement
bug
docs
chore
&& exit 1
title:
name: check title prefix
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: check
run: |
PR_TITLE_PREFIX=$(echo "$PR_TITLE" | cut -d':' -f1)
if [[ -d "pkg/collector/$PR_TITLE_PREFIX" ]] || [[ -d "$PR_TITLE_PREFIX" ]] || [[ "$PR_TITLE_PREFIX" == "chore" ]] || [[ "$PR_TITLE_PREFIX" == "chore(deps)" ]] || [[ "$PR_TITLE_PREFIX" == "*" ]] || [[ "$PR_TITLE_PREFIX" == "Synchronize common files from prometheus/prometheus" ]]; then
exit 0
fi
echo "PR title must start with an name of an collector package"
echo "Example: 'logical_disk: description'"
exit 1
env:
PR_TITLE: ${{ github.event.pull_request.title }}

View File

@@ -2,6 +2,10 @@ name: Releases
# Trigger on releases. # Trigger on releases.
on: on:
push:
branches:
- master
pull_request:
release: release:
types: types:
- published - published
@@ -18,15 +22,40 @@ jobs:
build: build:
runs-on: windows-2022 runs-on: windows-2022
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
# fetch-depth required for gitversion in `Build` step # fetch-depth required for gitversion in `Build` step
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-go@v3 - uses: actions/setup-go@v5
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
# https://github.com/pl4nty/Windows-Containers/blob/Main/helpful_tools/Install-BuildKit-GitHubActions/workflow.yaml
- name: Setup containerd
run: |
$version = "1.7.20"
curl.exe -L https://github.com/containerd/containerd/releases/download/v$version/containerd-$version-windows-amd64.tar.gz -o containerd.tar.gz
tar.exe xvf containerd.tar.gz
.\bin\containerd.exe --register-service
Start-Service containerd
- name: Setup BuildKit
run: |
$version = "v0.15.0"
curl.exe -L https://github.com/moby/buildkit/releases/download/$version/buildkit-$version.windows-amd64.tar.gz -o buildkit.tar.gz
tar.exe xvf buildkit.tar.gz
.\bin\buildkitd.exe --register-service
Start-Service buildkitd
- name: Setup Docker Buildx
run: |
$version = "v0.16.1"
curl.exe -L https://github.com/docker/buildx/releases/download/$version/buildx-$version.windows-amd64.exe -o $env:ProgramData\Docker\cli-plugins\docker-buildx.exe
- uses: docker/setup-buildx-action@v3
with:
driver: remote
endpoint: npipe:////./pipe/buildkitd
- name: Install WiX - name: Install WiX
run: dotnet tool install --global wix run: dotnet tool install --global wix
@@ -37,60 +66,82 @@ jobs:
- name: Install Build deps - name: Install Build deps
run: | run: |
dotnet tool install --global GitVersion.Tool --version 5.*
Invoke-WebRequest -Uri https://github.com/prometheus/promu/releases/download/v$($Env:PROMU_VER)/promu-$($Env:PROMU_VER).windows-amd64.zip -OutFile promu-$($Env:PROMU_VER).windows-amd64.zip Invoke-WebRequest -Uri https://github.com/prometheus/promu/releases/download/v$($Env:PROMU_VER)/promu-$($Env:PROMU_VER).windows-amd64.zip -OutFile promu-$($Env:PROMU_VER).windows-amd64.zip
Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath . Expand-Archive -Path promu-$($Env:PROMU_VER).windows-amd64.zip -DestinationPath .
Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin" Copy-Item -Path promu-$($Env:PROMU_VER).windows-amd64\promu.exe -Destination "$(go env GOPATH)\bin"
# No binaries available so build from source # GOPATH\bin dir must be added to PATH else the `promu` commands won't be found
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.4.0
# GOPATH\bin dir must be added to PATH else the `promu` and `goversioninfo` commands won't be found
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Build - name: Build
run: | run: |
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
dotnet-gitversion /output json /showvariable FullSemVer | Set-Content VERSION -PassThru $Version = git describe --tags --always
$Version = Get-Content VERSION $Version = $Version -replace 'v', ''
# Windows versioninfo resources need the file version by parts (but product version is free text)
$VersionParts = ($Version -replace '^v?([0-9\.]+).*$','$1').Split(".")
goversioninfo.exe -ver-major $VersionParts[0] -ver-minor $VersionParts[1] -ver-patch $VersionParts[2] -product-version $Version -platform-specific
make crossbuild
# '+' symbols are invalid characters in image tags # '+' symbols are invalid characters in image tags
(Get-Content -Path VERSION) -replace '\+', '_' | Set-Content -Path VERSION $Version = $Version -replace '\+', '_'
$Version | Set-Content VERSION -PassThru
make build-all make build-all
# GH requires all files to have different names, so add version/arch to differentiate # GH requires all files to have different names, so add version/arch to differentiate
foreach($Arch in "amd64", "arm64") { foreach($Arch in "amd64", "arm64") {
Move-Item output\$Arch\windows_exporter.exe output\windows_exporter-$Version-$Arch.exe Move-Item output\$Arch\windows_exporter.exe output\windows_exporter-$Version-$Arch.exe
} }
Get-ChildItem -Path output
- name: Upload Artifacts - name: Upload Artifacts
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: windows_exporter_binaries name: windows_exporter_binaries
path: output\windows_exporter-*.exe path: output\windows_exporter-*.exe
- name: Build Release Artifacts - name: Build Release Artifacts
if: startsWith(github.ref, 'refs/tags/')
run: | run: |
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$BuildVersion = Get-Content VERSION $Version = Get-Content VERSION
$TagName = $env:GITHUB_REF -replace 'refs/tags/', ''
# The MSI version is not semver compliant, so just take the numerical parts
$MSIVersion = $TagName -replace '^v?([0-9\.]+).*$','$1'
foreach($Arch in "amd64", "arm64") { foreach($Arch in "amd64", "arm64") {
Write-Verbose "Building windows_exporter $MSIVersion msi for $Arch" Write-Host "Building windows_exporter $Version msi for $Arch"
.\installer\build.ps1 -PathToExecutable .\output\windows_exporter-$BuildVersion-$Arch.exe -Version $MSIVersion -Arch "$Arch" .\installer\build.ps1 -PathToExecutable .\output\windows_exporter-$Version-$Arch.exe -Version $Version -Arch "$Arch"
Move-Item installer\windows_exporter-$MSIVersion-$Arch.msi output\
} }
Move-Item installer\*.msi output\
Get-ChildItem -Path output\
promu checksum output\ promu checksum output\
- name: Build Docker Artifacts
run: make build-all
env:
VERSION: >-
${{
startsWith(github.ref, 'refs/tags/') && 'latest' ||
(
github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || github.ref_name
)
}}
- name: Login to Docker Hub
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_LOGIN }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
#- name: Login to quay.io
# if: ${{ github.event_name != 'pull_request' }}
# uses: docker/login-action@v3
# with:
# registry: quay.io
# username: 'robot'
# password: ${{ secrets.QUAY_IO_API_TOKEN }}
- name: Login to GitHub container registry - name: Login to GitHub container registry
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
@@ -100,8 +151,8 @@ jobs:
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ startsWith(github.ref, 'refs/tags/') && 'latest' || github.ref_name }}
run: | run: |
$Env:VERSION = 'latest'
make push-all make push-all
- name: Release - name: Release

View File

@@ -17,7 +17,7 @@ jobs:
name: Check for spelling errors name: Check for spelling errors
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: codespell-project/actions-codespell@master - uses: codespell-project/actions-codespell@master
with: with:
check_filenames: true check_filenames: true

View File

@@ -11,7 +11,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v8 - uses: actions/stale@v9
with: with:
stale-issue-message: 'This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.' stale-issue-message: 'This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.'
exempt-issue-labels: 'lifecycle/frozen' exempt-issue-labels: 'lifecycle/frozen'

3
.gitignore vendored
View File

@@ -6,3 +6,6 @@ output/
.vscode .vscode
.idea .idea
*.syso *.syso
installer/*.msi
installer/*.wixpdb
local/

View File

@@ -1,14 +1,57 @@
linters: linters:
disable-all: true enable-all: true
enable: disable:
- deadcode - containedctx
- errcheck - contextcheck
- revive - cyclop
- govet - depguard
- gofmt - dogsled
- ineffassign - dupl
- unconvert - err113
- varcheck - exhaustive
- exhaustruct
- exportloopref
- fatcontext
- funlen
- gochecknoglobals
- gocognit
- goconst
- gocyclo
- godox
- inamedparam
- ireturn
- lll
- mnd
- nlreturn
- noctx
- testpackage
- varnamelen
- wrapcheck
- wsl
- execinquery
- gomnd
- stylecheck
- maintidx
linters-settings:
gosec:
excludes:
- G115 # integer overflow conversion
gci:
sections:
- prefix(github.com/prometheus-community/windows_exporter/pkg/initiate)
- standard # Standard section: captures all standard packages.
- default # Default section: contains all imports that could not be matched to another section type.
custom-order: true
tagliatelle:
case:
use-field-name: true
rules:
# Any struct tag type can be used.
# Support string case: `camel`, `pascal`, `kebab`, `snake`, `upperSnake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header`
json: camel
yaml: snake
issues: issues:
exclude: exclude:

View File

@@ -1,7 +1,7 @@
# Note this image doesn't really matter for hostprocess but it is good to build per OS version # Note this image doesn't really matter for hostprocess but it is good to build per OS version
# the files in the image are copied to $env:CONTAINER_SANDBOX_MOUNT_POINT on the host # the files in the image are copied to $env:CONTAINER_SANDBOX_MOUNT_POINT on the host
# but the file system is the Host NOT the container # but the file system is the Host NOT the container
ARG BASE="mcr.microsoft.com/windows/nanoserver:1809" ARG BASE="mcr.microsoft.com/windows/nanoserver:ltsc2022"
FROM $BASE FROM $BASE
ENV PATH="C:\Windows\system32;C:\Windows;" ENV PATH="C:\Windows\system32;C:\Windows;"

View File

@@ -1,26 +1,35 @@
export GOOS=windows GOOS ?= windows
export DOCKER_IMAGE_NAME ?= windows-exporter VERSION ?= $(shell cat VERSION)
export DOCKER_REPO ?= ghcr.io/prometheus-community DOCKER ?= docker
VERSION?=$(shell cat VERSION) # DOCKER_REPO is the official image repository name at docker.io, quay.io.
DOCKER?=docker DOCKER_REPO ?= prometheuscommunity
DOCKER_IMAGE_NAME ?= windows-exporter
# Image Variables for Hostprocess Container # ALL_DOCKER_REPOS is the list of repositories to push the image to. ghcr.io requires that org name be the same as the image repo name.
ALL_DOCKER_REPOS ?= docker.io/$(DOCKER_REPO) ghcr.io/prometheus-community # quay.io/$(DOCKER_REPO)
# Image Variables for host process Container
# Windows image build is heavily influenced by https://github.com/kubernetes/kubernetes/blob/master/cluster/images/etcd/Makefile # Windows image build is heavily influenced by https://github.com/kubernetes/kubernetes/blob/master/cluster/images/etcd/Makefile
OS=1809 OS ?= ltsc2019
ALL_OS:= 1809 ltsc2022 ALL_OS ?= ltsc2019 ltsc2022
BASE_IMAGE=mcr.microsoft.com/windows/nanoserver BASE_IMAGE ?= mcr.microsoft.com/windows/nanoserver
.PHONY: build .PHONY: build
build: windows_exporter.exe build: generate windows_exporter.exe
windows_exporter.exe: pkg/**/*.go windows_exporter.exe: pkg/**/*.go
promu build -v promu build -v
.PHONY: generate
generate:
go generate ./...
test: test:
go test -v ./... go test -v ./...
bench: bench:
go test -v -bench='benchmarkcollector' ./pkg/collector/{cpu,logical_disk,physical_disk,logon,memory,net,process,service,system,tcp,time} go test -v -bench='benchmarkcollector' ./pkg/collector/{cpu,logical_disk,physical_disk,logon,memory,net,printer,process,service,system,tcp,time}
lint: lint:
golangci-lint -c .golangci.yaml run golangci-lint -c .golangci.yaml run
@@ -36,28 +45,52 @@ promtool: windows_exporter.exe
fmt: fmt:
gofmt -l -w -s . gofmt -l -w -s .
crossbuild: crossbuild: generate
# The prometheus/golang-builder image for promu crossbuild doesn't exist # The prometheus/golang-builder image for promu crossbuild doesn't exist
# on Windows, so for now, we'll just build twice # on Windows, so for now, we'll just build twice
GOARCH=amd64 promu build --prefix=output/amd64 GOARCH=amd64 promu build --prefix=output/amd64
GOARCH=arm64 promu build --prefix=output/arm64 GOARCH=arm64 promu build --prefix=output/arm64
.PHONY: package
package: crossbuild
powershell -NonInteractive -ExecutionPolicy Bypass -File .\installer\build.ps1 -PathToExecutable .\output\amd64\windows_exporter.exe -Version $(shell git describe --tags --abbrev=0)
build-image: crossbuild build-image: crossbuild
$(DOCKER) build --build-arg=BASE=$(BASE_IMAGE):$(OS) -f Dockerfile -t $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$(OS) . $(DOCKER) build --build-arg=BASE=$(BASE_IMAGE):$(OS) -f Dockerfile -t local/$(DOCKER_IMAGE_NAME):$(VERSION)-$(OS) .
build-hostprocess:
$(DOCKER) buildx build --build-arg=BASE=mcr.microsoft.com/oss/kubernetes/windows-host-process-containers-base-image:v1.0.0 -f Dockerfile -t local/$(DOCKER_IMAGE_NAME):$(VERSION)-hostprocess .
sub-build-%: sub-build-%:
$(MAKE) OS=$* build-image $(MAKE) OS=$* build-image
build-all: $(addprefix sub-build-,$(ALL_OS)) build-all: $(addprefix sub-build-,$(ALL_OS)) build-hostprocess
push: push:
set -x; \ set -x; \
for osversion in ${ALL_OS}; do \ for docker_repo in ${DOCKER_REPO}; do \
$(DOCKER) push $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \ for osversion in ${ALL_OS}; do \
$(DOCKER) manifest create --amend $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \ $(DOCKER) tag local/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion} $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
full_version=`$(DOCKER) manifest inspect $(BASE_IMAGE):$${osversion} | grep "os.version" | head -n 1 | awk -F\" '{print $$4}'` || true; \ $(DOCKER) push $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
$(DOCKER) manifest annotate --os windows --arch amd64 --os-version $${full_version} $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \ $(DOCKER) manifest create --amend $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION) $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
full_version=`$(DOCKER) manifest inspect $(BASE_IMAGE):$${osversion} | grep "os.version" | head -n 1 | awk -F\" '{print $$4}'` || true; \
$(DOCKER) manifest annotate --os windows --arch amd64 --os-version $${full_version} $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION) $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION)-$${osversion}; \
done; \
$(DOCKER) manifest push --purge $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION); \
done done
$(DOCKER) manifest push --purge $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(VERSION)
push-all: build-all push # We can't load the image into the local docker store, so we have to build and push it in one go
push-hostprocess:
set -x; \
for docker_repo in ${DOCKER_REPO}; do \
$(DOCKER) buildx build --push --build-arg=BASE=mcr.microsoft.com/oss/kubernetes/windows-host-process-containers-base-image:v1.0.0 -f Dockerfile -t $${docker_repo}/$(DOCKER_IMAGE_NAME):$(VERSION)-hostprocess .; \
done
.PHONY: push-all
push-all: build-all
$(MAKE) DOCKER_REPO="$(ALL_DOCKER_REPOS)" push # push-hostprocess - disabled until it works on Windows
# Mandatory target for container description sync action
.PHONY: docker-repo-name
docker-repo-name:
@echo "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)"

View File

@@ -4,7 +4,6 @@
A Prometheus exporter for Windows machines. A Prometheus exporter for Windows machines.
## Collectors ## Collectors
Name | Description | Enabled by default Name | Description | Enabled by default
@@ -15,8 +14,9 @@ Name | Description | Enabled by default
[cache](docs/collector.cache.md) | Cache metrics | [cache](docs/collector.cache.md) | Cache metrics |
[cpu](docs/collector.cpu.md) | CPU usage | &#10003; [cpu](docs/collector.cpu.md) | CPU usage | &#10003;
[cpu_info](docs/collector.cpu_info.md) | CPU Information | [cpu_info](docs/collector.cpu_info.md) | CPU Information |
[cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) | &#10003; [cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) |
[container](docs/collector.container.md) | Container metrics | [container](docs/collector.container.md) | Container metrics |
[diskdrive](docs/collector.diskdrive.md) | Diskdrive metrics |
[dfsr](docs/collector.dfsr.md) | DFSR metrics | [dfsr](docs/collector.dfsr.md) | DFSR metrics |
[dhcp](docs/collector.dhcp.md) | DHCP Server | [dhcp](docs/collector.dhcp.md) | DHCP Server |
[dns](docs/collector.dns.md) | DNS Server | [dns](docs/collector.dns.md) | DNS Server |
@@ -24,14 +24,11 @@ Name | Description | Enabled by default
[fsrmquota](docs/collector.fsrmquota.md) | Microsoft File Server Resource Manager (FSRM) Quotas collector | [fsrmquota](docs/collector.fsrmquota.md) | Microsoft File Server Resource Manager (FSRM) Quotas collector |
[hyperv](docs/collector.hyperv.md) | Hyper-V hosts | [hyperv](docs/collector.hyperv.md) | Hyper-V hosts |
[iis](docs/collector.iis.md) | IIS sites and applications | [iis](docs/collector.iis.md) | IIS sites and applications |
[license](docs/collector.license.md) | Windows license status |
[logical_disk](docs/collector.logical_disk.md) | Logical disks, disk I/O | &#10003; [logical_disk](docs/collector.logical_disk.md) | Logical disks, disk I/O | &#10003;
[logon](docs/collector.logon.md) | User logon sessions | [logon](docs/collector.logon.md) | User logon sessions |
[memory](docs/collector.memory.md) | Memory usage metrics | [memory](docs/collector.memory.md) | Memory usage metrics |
[mscluster_cluster](docs/collector.mscluster_cluster.md) | MSCluster cluster metrics | [mscluster](docs/collector.mscluster.md) | MSCluster metrics |
[mscluster_network](docs/collector.mscluster_network.md) | MSCluster network metrics |
[mscluster_node](docs/collector.mscluster_node.md) | MSCluster Node metrics |
[mscluster_resource](docs/collector.mscluster_resource.md) | MSCluster Resource metrics |
[mscluster_resourcegroup](docs/collector.mscluster_resourcegroup.md) | MSCluster ResourceGroup metrics |
[msmq](docs/collector.msmq.md) | MSMQ queues | [msmq](docs/collector.msmq.md) | MSMQ queues |
[mssql](docs/collector.mssql.md) | [SQL Server Performance Objects](https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/use-sql-server-objects#SQLServerPOs) metrics | [mssql](docs/collector.mssql.md) | [SQL Server Performance Objects](https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/use-sql-server-objects#SQLServerPOs) metrics |
[netframework_clrexceptions](docs/collector.netframework_clrexceptions.md) | .NET Framework CLR Exceptions | [netframework_clrexceptions](docs/collector.netframework_clrexceptions.md) | .NET Framework CLR Exceptions |
@@ -44,11 +41,14 @@ Name | Description | Enabled by default
[netframework_clrsecurity](docs/collector.netframework_clrsecurity.md) | .NET Framework Security Check metrics | [netframework_clrsecurity](docs/collector.netframework_clrsecurity.md) | .NET Framework Security Check metrics |
[net](docs/collector.net.md) | Network interface I/O | &#10003; [net](docs/collector.net.md) | Network interface I/O | &#10003;
[os](docs/collector.os.md) | OS metrics (memory, processes, users) | &#10003; [os](docs/collector.os.md) | OS metrics (memory, processes, users) | &#10003;
[physical_disk](docs/collector.physical_disk.md) | physical disk metrics | &#10003;
[printer](docs/collector.printer.md) | Printer metrics |
[process](docs/collector.process.md) | Per-process metrics | [process](docs/collector.process.md) | Per-process metrics |
[remote_fx](docs/collector.remote_fx.md) | RemoteFX protocol (RDP) metrics | [remote_fx](docs/collector.remote_fx.md) | RemoteFX protocol (RDP) metrics |
[scheduled_task](docs/collector.scheduled_task.md) | Scheduled Tasks metrics | [scheduled_task](docs/collector.scheduled_task.md) | Scheduled Tasks metrics |
[service](docs/collector.service.md) | Service state metrics | &#10003; [service](docs/collector.service.md) | Service state metrics | &#10003;
[smb](docs/collector.smb.md) | SMB Server | [smb](docs/collector.smb.md) | SMB Server |
[smbclient](docs/collector.smbclient.md) | SMB Client |
[smtp](docs/collector.smtp.md) | IIS SMTP Server | [smtp](docs/collector.smtp.md) | IIS SMTP Server |
[system](docs/collector.system.md) | System calls | &#10003; [system](docs/collector.system.md) | System calls | &#10003;
[tcp](docs/collector.tcp.md) | TCP connections | [tcp](docs/collector.tcp.md) | TCP connections |
@@ -56,7 +56,7 @@ Name | Description | Enabled by default
[time](docs/collector.time.md) | Windows Time Service | [time](docs/collector.time.md) | Windows Time Service |
[thermalzone](docs/collector.thermalzone.md) | Thermal information [thermalzone](docs/collector.thermalzone.md) | Thermal information
[terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS) [terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS)
[textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file | &#10003; [textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file |
[vmware_blast](docs/collector.vmware_blast.md) | VMware Blast session metrics | [vmware_blast](docs/collector.vmware_blast.md) | VMware Blast session metrics |
[vmware](docs/collector.vmware.md) | Performance counters installed by the Vmware Guest agent | [vmware](docs/collector.vmware.md) | Performance counters installed by the Vmware Guest agent |
@@ -81,17 +81,17 @@ This can be useful for having different Prometheus servers collect specific metr
windows_exporter accepts flags to configure certain behaviours. The ones configuring the global behaviour of the exporter are listed below, while collector-specific ones are documented in the respective collector documentation above. windows_exporter accepts flags to configure certain behaviours. The ones configuring the global behaviour of the exporter are listed below, while collector-specific ones are documented in the respective collector documentation above.
Flag | Description | Default value | Flag | Description | Default value |
---------|-------------|-------------------- |--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
`--web.listen-address` | host:port for exporter. | `:9182` | `--web.listen-address` | host:port for exporter. | `:9182` |
`--telemetry.path` | URL path for surfacing collected metrics. | `/metrics` | `--telemetry.path` | URL path for surfacing collected metrics. | `/metrics` |
`--telemetry.max-requests` | Maximum number of concurrent requests. 0 to disable. | `5` | `--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.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. | | `--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` | `--scrape.timeout-margin` | Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads. | `0.5` |
`--web.config.file` | A [web config][web_config] for setting up TLS and Auth | None | `--web.config.file` | A [web config][web_config] for setting up TLS and Auth | None |
`--config.file` | [Using a config file](#using-a-configuration-file) from path or URL | None | `--config.file` | [Using a config file](#using-a-configuration-file) from path or URL | None |
`--config.file.insecure-skip-verify` | Skip TLS when loading config file from URL | false | `--config.file.insecure-skip-verify` | Skip TLS when loading config file from URL | false |
## Installation ## Installation
The latest release can be downloaded from the [releases page](https://github.com/prometheus-community/windows_exporter/releases). The latest release can be downloaded from the [releases page](https://github.com/prometheus-community/windows_exporter/releases).
@@ -100,15 +100,17 @@ Each release provides a .msi installer. The installer will setup the windows_exp
If the installer is run without any parameters, the exporter will run with default settings for enabled collectors, ports, etc. The following parameters are available: If the installer is run without any parameters, the exporter will run with default settings for enabled collectors, ports, etc. The following parameters are available:
Name | Description | Name | Description |
-----|------------ |----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
`ENABLED_COLLECTORS` | As the `--collectors.enabled` flag, provide a comma-separated list of enabled collectors | `ENABLED_COLLECTORS` | As the `--collectors.enabled` flag, provide a comma-separated list of enabled collectors |
`LISTEN_ADDR` | The IP address to bind to. Defaults to 0.0.0.0 | `LISTEN_ADDR` | The IP address to bind to. Defaults to an empty string. (any local address) |
`LISTEN_PORT` | The port to bind to. Defaults to 9182. | `LISTEN_PORT` | The port to bind to. Defaults to `9182`. |
`METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics` | `METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics` |
`TEXTFILE_DIRS` | As the `--collector.textfile.directories` flag, provide a directory to read text files with metrics from | `TEXTFILE_DIRS` | Use the `--collector.textfile.directories` flag to specify one or more directories, separated by commas, where the collector should read text files containing metrics |
`REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (allow list). Defaults to an empty string (any remote address). | `REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (allow list). Defaults to an empty string (any remote address). |
`EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string. | `EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string. |
| `ADD_FIREWALL_EXCEPTION` | Setup an firewall exception for windows_exporter. Defaults to `yes`. |
| `ENABLE_V1_PERFORMANCE_COUNTERS` | Enables V1 performance counter on modern systems. Defaults to `yes`. |
Parameters are sent to the installer via `msiexec`. Example invocations: Parameters are sent to the installer via `msiexec`. Example invocations:
@@ -121,11 +123,25 @@ Example service collector with a custom query.
msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,service --% EXTRA_FLAGS="--collector.service.services-where ""Name LIKE 'sql%'""" msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,service --% EXTRA_FLAGS="--collector.service.services-where ""Name LIKE 'sql%'"""
``` ```
On some older versions of Windows you may need to surround parameter values with double quotes to get the install command parsing properly: On some older versions of Windows,
you may need to surround parameter values with double quotes to get the installation command parsing properly:
```powershell ```powershell
msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,textfile,thermalzone" TEXTFILE_DIRS="C:\custom_metrics\" msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,textfile,thermalzone" TEXTFILE_DIRS="C:\custom_metrics\"
``` ```
To install the exporter with creating a firewall exception, use the following command:
```powershell
msiexec /i <path-to-msi-file> ADD_FIREWALL_EXCEPTION=yes
```
To repair an installation, e.g force re-creating Windows service:
```powershell
msiexec /fa <path-to-msi-file>
```
Powershell versions 7.3 and above require [PSNativeCommandArgumentPassing](https://learn.microsoft.com/en-us/powershell/scripting/learn/experimental-features?view=powershell-7.3) to be set to `Legacy` when using `--% EXTRA_FLAGS`: Powershell 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 ```powershell
@@ -133,6 +149,20 @@ $PSNativeCommandArgumentPassing = 'Legacy'
msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,service --% EXTRA_FLAGS="--collector.service.services-where ""Name LIKE 'sql%'""" msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,service --% EXTRA_FLAGS="--collector.service.services-where ""Name LIKE 'sql%'"""
``` ```
## Docker Implementation
The windows_exporter can be run as a Docker container. The Docker image is available on
* [Docker Hub](https://hub.docker.com/r/prometheuscommunity/windows-exporter): `docker.io/prometheuscommunity/windows-exporter`
* [GitHub Container Registry](https://github.com/prometheus-community/windows_exporter/pkgs/container/windows-exporter): `ghcr.io/prometheus-community/windows-exporter`
<!-- * [quay.io Registry](https://quay.io/repository/prometheuscommunity/windows-exporter): `quay.io/prometheuscommunity/windows-exporter` -->
### Tags
The Docker image is tagged with the version of the exporter. The `latest` tag is also available and points to the latest release.
Additionally, a flavor `hostprocess` with `-hostprocess` as suffix is based on the https://github.com/microsoft/windows-host-process-containers-base-image
which is designed to run as a Windows host process container. The size of that images is smaller than the default one.
## Kubernetes Implementation ## Kubernetes Implementation
@@ -140,7 +170,9 @@ See detailed steps to install on Windows Kubernetes [here](./kubernetes/kubernet
## Supported versions ## Supported versions
windows_exporter supports Windows Server versions 2008R2 and later, and desktop Windows version 7 and later. `windows_exporter` supports Windows Server versions 2016 and later, and desktop Windows version 10 and 11 (21H2 or later).
Windows Server 2012 and 2012R2 are supported as best-effort only, but not guaranteed to work.
## Usage ## Usage

7
config.yaml Normal file
View File

@@ -0,0 +1,7 @@
collectors:
enabled: cpu,cpu_info,cs,exchange,iis,logical_disk,logon,memory,net,os,process,remote_fx,service,system,tcp,time,terminal_services,textfile
collector:
service:
services-where: "Name='windows_exporter'"
log:
level: warn

View File

@@ -21,11 +21,7 @@ This directory contains documentation of the collectors in the windows_exporter,
- [`logical_disk`](collector.logical_disk.md) - [`logical_disk`](collector.logical_disk.md)
- [`logon`](collector.logon.md) - [`logon`](collector.logon.md)
- [`memory`](collector.memory.md) - [`memory`](collector.memory.md)
- [`mscluster_cluster`](collector.mscluster_cluster.md) - [`mscluster`](collector.mscluster.md)
- [`mscluster_network`](collector.mscluster_network.md)
- [`mscluster_node`](collector.mscluster_node.md)
- [`mscluster_resource`](collector.mscluster_resource.md)
- [`mscluster_resourcegroup`](collector.mscluster_resourcegroup.md)
- [`msmq`](collector.msmq.md) - [`msmq`](collector.msmq.md)
- [`mssql`](collector.mssql.md) - [`mssql`](collector.mssql.md)
- [`net`](collector.net.md) - [`net`](collector.net.md)

View File

@@ -35,7 +35,7 @@ Name | Description | Type | Labels
`windows_cpu_processor_mperf_total` | Processor MPerf Total is proportioanl to the number of TSC ticks each core has accumulated while executing instructions. Due to the manner in which it is presented, it should be scaled by 1e2 to properly line up with Processor Performance Total. As above, it is believed to be closely related to the MPERF MSR. | counter | `core` `windows_cpu_processor_mperf_total` | Processor MPerf Total is proportioanl to the number of TSC ticks each core has accumulated while executing instructions. Due to the manner in which it is presented, it should be scaled by 1e2 to properly line up with Processor Performance Total. As above, it is believed to be closely related to the MPERF MSR. | counter | `core`
`windows_cpu_processor_rtc_total` | RTC total is assumed to represent the 64Hz tick rate in Windows. It is not by itself useful, but can be used with `windows_cpu_processor_utility_total` to more accurately measure CPU utilisation than with `windows_cpu_time_total` | counter | `core` `windows_cpu_processor_rtc_total` | RTC total is assumed to represent the 64Hz tick rate in Windows. It is not by itself useful, but can be used with `windows_cpu_processor_utility_total` to more accurately measure CPU utilisation than with `windows_cpu_time_total` | counter | `core`
`windows_cpu_processor_utility_total` | Processor Utility Total is a newer, more accurate measure of CPU utilization, in particular handling modern CPUs with variant CPU frequencies. The rate of this counter divided by the rate of `windows_cpu_processor_rtc_total` should provide an accurate view of CPU utilisation on modern systems, as observed in Task Manager. | counter | `core` `windows_cpu_processor_utility_total` | Processor Utility Total is a newer, more accurate measure of CPU utilization, in particular handling modern CPUs with variant CPU frequencies. The rate of this counter divided by the rate of `windows_cpu_processor_rtc_total` should provide an accurate view of CPU utilisation on modern systems, as observed in Task Manager. | counter | `core`
`windows_cpu_processor_privileged_utility_total` | Processor Privilged Utility Total, when used in a similar fashion to `windows_cpu_processor_utility_total` will show the portion of CPU utilization which is happening in privileged mode. | counter | `core` `windows_cpu_processor_privileged_utility_total` | Processor Privileged Utility Total, when used in a similar fashion to `windows_cpu_processor_utility_total` will show the portion of CPU utilization which is happening in privileged mode. | counter | `core`
### Example metric ### Example metric
Show frequency of host CPU cores Show frequency of host CPU cores

View File

@@ -15,13 +15,39 @@ None
## Metrics ## Metrics
Name | Description | Type | Labels | Name | Description | Type | Labels |
-----|-------------|------|------- |--------------------------------------------|--------------------------------------|-------|--------------------------------------------------------------|
`windows_cpu_info` | Labeled CPU information | gauge | `architecture`, `device_id`, `description`, `family`, `l2_cache_size` `l3_cache_size`, `name` | `windows_cpu_info` | Labelled CPU information | gauge | `architecture`, `description`, `device_id`, `family`, `name` |
| `windows_cpu_info_core` | Number of cores per CPU | gauge | `device_id` |
| `windows_cpu_info_enabled_core` | Number of enabled cores per CPU | gauge | `device_id` |
| `windows_cpu_info_l2_cache_size` | Size of L2 cache per CPU | gauge | `device_id` |
| `windows_cpu_info_l3_cache_size` | Size of L3 cache per CPU | gauge | `device_id` |
| `windows_cpu_info_logical_processor` | Number of logical processors per CPU | gauge | `device_id` |
| `windows_cpu_info_thread` | Number of threads per CPU | gauge | `device_id` |
### Example metric ### Example metric
``` ```
windows_cpu_info{architecture="9",description="AMD64 Family 23 Model 49 Stepping 0",device_id="CPU0",family="107",l2_cache_size="32768",l3_cache_size="262144",name="AMD EPYC 7702P 64-Core Processor"} 1 # HELP windows_cpu_info Labelled CPU information as provided by Win32_Processor
# TYPE windows_cpu_info gauge
windows_cpu_info{architecture="9",description="AMD64 Family 25 Model 33 Stepping 2",device_id="CPU0",family="107",name="AMD Ryzen 9 5900X 12-Core Processor"} 1
# HELP windows_cpu_info_core Number of cores per CPU
# TYPE windows_cpu_info_core gauge
windows_cpu_info_core{device_id="CPU0"} 12
# HELP windows_cpu_info_enabled_core Number of enabled cores per CPU
# TYPE windows_cpu_info_enabled_core gauge
windows_cpu_info_enabled_core{device_id="CPU0"} 12
# HELP windows_cpu_info_l2_cache_size Size of L2 cache per CPU
# TYPE windows_cpu_info_l2_cache_size gauge
windows_cpu_info_l2_cache_size{device_id="CPU0"} 6144
# HELP windows_cpu_info_l3_cache_size Size of L3 cache per CPU
# TYPE windows_cpu_info_l3_cache_size gauge
windows_cpu_info_l3_cache_size{device_id="CPU0"} 65536
# HELP windows_cpu_info_logical_processor Number of logical processors per CPU
# TYPE windows_cpu_info_logical_processor gauge
windows_cpu_info_logical_processor{device_id="CPU0"} 24
# HELP windows_cpu_info_thread Number of threads per CPU
# TYPE windows_cpu_info_thread gauge
windows_cpu_info_thread{device_id="CPU0"} 24
``` ```
The value of the metric is irrelevant, but the labels expose some useful information on the CPU installed in each socket. The value of the metric is irrelevant, but the labels expose some useful information on the CPU installed in each socket.

View File

@@ -18,7 +18,7 @@ Name | Description | Type | Labels
-----|-------------|------|------- -----|-------------|------|-------
`windows_cs_logical_processors` | Number of installed logical processors | gauge | None `windows_cs_logical_processors` | Number of installed logical processors | gauge | None
`windows_cs_physical_memory_bytes` | Total installed physical memory | gauge | None `windows_cs_physical_memory_bytes` | Total installed physical memory | gauge | None
`windows_cs_hostname` | Labeled system hostname information | gauge | `hostname`, `domain`, `fqdn` `windows_cs_hostname` | Labelled system hostname information | gauge | `hostname`, `domain`, `fqdn`
### Example metric ### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_ _This collector does not yet have explained examples, we would appreciate your help adding them!_

View File

@@ -5,7 +5,7 @@ The diskdrive collector exposes metrics about physical disks
| | | | | |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Metric name prefix | `diskdrive` | | Metric name prefix | `diskdrive` |
| Classes | [`Win32_PerfRawData_DNS_DNS`](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive) | | Classes | [`Win32_DiskDrive`](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive) |
| Enabled by default? | No | | Enabled by default? | No |
## Flags ## Flags
@@ -16,11 +16,11 @@ None
| Name | Description | Type | Labels | | Name | Description | Type | Labels |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ |
| `disk_drive_info` | General identifiable information about the disk drive | gauge | name,caption,device_id,model | | `diskdrive_info` | General identifiable information about the disk drive | gauge | name,caption,device_id,model |
| `disk_drive_availability` | The disk drive's current availability | gauge | name,availability | | `diskdrive_availability` | The disk drive's current availability | gauge | name,availability |
| `disk_drive_partitions` | Number of partitions on the drive | gauge | name | | `diskdrive_partitions` | Number of partitions on the drive | gauge | name |
| `disk_drive_size` | Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector. | gauge | name | | `diskdrive_size` | Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector. | gauge | name |
| `disk_drive_status` | Operational status of the drive | gauge | name,status | | `diskdrive_status` | Operational status of the drive | gauge | name,status |
## Alerting examples ## Alerting examples
**prometheus.rules** **prometheus.rules**

53
docs/collector.license.md Normal file
View File

@@ -0,0 +1,53 @@
# license collector
The license collector exposes metrics about the Windows license status.
|||
-|-
Metric name prefix | `license`
Data source | Win32
Enabled by default? | No
## Flags
None
## Metrics
| Name | Description | Type | Labels |
|--------------------------|----------------|-------|---------|
| `windows_license_status` | license status | gauge | `state` |
### Example metric
```
# HELP windows_license_status Status of windows license
# TYPE windows_license_status gauge
windows_license_status{state="genuine"} 1
windows_license_status{state="invalid_license"} 0
windows_license_status{state="last"} 0
windows_license_status{state="offline"} 0
windows_license_status{state="tampered"} 0
```
## Useful queries
Show if the license is genuine
```
windows_license_status{state="genuine"}
```
## Alerting examples
**prometheus.rules**
```yaml
- alert: "WindowsLicense"
expr: 'windows_license_status{state="genuine"} == 0'
for: "10m"
labels:
severity: "high"
annotations:
summary: "Windows system license is not genuine"
description: "The Windows system license is not genuine. Please check the license status."
```

View File

@@ -23,6 +23,7 @@ If given, a disk needs to *not* match the exclude regexp in order for the corres
Name | Description | Type | Labels Name | Description | Type | Labels
-----|-------------|------|------- -----|-------------|------|-------
`windows_logical_disk_info` | A metric with a constant '1' value labeled with logical disk information | gauge | `disk`,`filesystem`,`serial_number`,`volume`,`volume_name`,`type`
`windows_logical_disk_requests_queued` | Number of requests outstanding on the disk at the time the performance data is collected | gauge | `volume` `windows_logical_disk_requests_queued` | Number of requests outstanding on the disk at the time the performance data is collected | gauge | `volume`
`windows_logical_disk_avg_read_requests_queued` | Average number of read requests that were queued for the selected disk during the sample interval | gauge | `volume` `windows_logical_disk_avg_read_requests_queued` | Average number of read requests that were queued for the selected disk during the sample interval | gauge | `volume`
`windows_logical_disk_avg_write_requests_queued` | Average number of write requests that were queued for the selected disk during the sample interval | gauge | `volume` `windows_logical_disk_avg_write_requests_queued` | Average number of write requests that were queued for the selected disk during the sample interval | gauge | `volume`
@@ -36,6 +37,7 @@ Name | Description | Type | Labels
`windows_logical_disk_size_bytes` | Total size of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume` `windows_logical_disk_size_bytes` | Total size of the disk in bytes (not real time, updates every 10-15 min) | gauge | `volume`
`windows_logical_disk_idle_seconds_total` | Seconds the disk was idle (not servicing read/write requests) | counter | `volume` `windows_logical_disk_idle_seconds_total` | Seconds the disk was idle (not servicing read/write requests) | counter | `volume`
`windows_logical_disk_split_ios_total` | Number of I/Os to the disk split into multiple I/Os | counter | `volume` `windows_logical_disk_split_ios_total` | Number of I/Os to the disk split into multiple I/Os | counter | `volume`
`windows_logical_disk_readonly` | Whether the logical disk is read-only | gauge | `volume`
### Warning about size metrics ### Warning about size metrics
The `free_bytes` and `size_bytes` metrics are not updated in real time and might have a delay of 10-15min. The `free_bytes` and `size_bytes` metrics are not updated in real time and might have a delay of 10-15min.
@@ -47,6 +49,15 @@ Query the rate of write operations to a disk
rate(windows_logical_disk_read_bytes_total{instance="localhost", volume=~"C:"}[2m]) rate(windows_logical_disk_read_bytes_total{instance="localhost", volume=~"C:"}[2m])
``` ```
Logical Volume information
```
windows_logical_disk_info{disk_id="0",filesystem="",serial_number="",type="",volume="HarddiskVolume2",volume_name=""} 1
windows_logical_disk_info{disk_id="0",filesystem="",serial_number="",type="",volume="HarddiskVolume3",volume_name=""} 1
windows_logical_disk_info{disk_id="0",filesystem="NTFS",serial_number="668EEC37",type="fixed",volume="C:",volume_name="Windows"} 1
windows_logical_disk_info{disk_id="1",filesystem="NTFS",serial_number="50AE953B",type="fixed",volume="D:",volume_name="Temporary Storage"} 1
windows_logical_disk_info{disk_id="1",filesystem="ReFS",serial_number="C69B59AD",type="fixed",volume="G:",volume_name="Volume"} 1
```
## Useful queries ## Useful queries
Calculate rate of total IOPS for disk Calculate rate of total IOPS for disk
``` ```

186
docs/collector.mscluster.md Normal file
View File

@@ -0,0 +1,186 @@
# mscluster_cluster collector
The MSCluster_Cluster class is a dynamic WMI class that represents a cluster.
|||
-|-
Metric name prefix | `mscluster`
Classes | `MSCluster_Cluster`,`MSCluster_Network`,`MSCluster_Node`,`MSCluster_Resource`,`MSCluster_ResourceGroup`
Enabled by default? | No
## Flags
### `--collectors.mscluster.enabled`
Comma-separated list of collectors to use, for example:
`--collectors.mscluster.enabled=cluster,network,node,resource,resouregroup`.
Matching is case-sensitive.
## Metrics
### Cluster
| Name | Description | Type | Labels |
|-------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|--------|
| `mscluster_cluster_AddEvictDelay` | 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. | gauge | `name` |
| `mscluster_cluster_AdminAccessPoint` | The type of the cluster administrative access point. | gauge | `name` |
| `mscluster_cluster_AutoAssignNodeSite` | Determines whether or not the cluster will attempt to automatically assign nodes to sites based on networks and Active Directory Site information. | gauge | `name` |
| `mscluster_cluster_AutoBalancerLevel` | Determines the level of aggressiveness of AutoBalancer. | gauge | `name` |
| `mscluster_cluster_AutoBalancerMode` | Determines whether or not the auto balancer is enabled. | gauge | `name` |
| `mscluster_cluster_BackupInProgress` | Indicates whether a backup is in progress. | gauge | `name` |
| `mscluster_cluster_BlockCacheSize` | CSV BlockCache Size in MB. | gauge | `name` |
| `mscluster_cluster_ClusSvcHangTimeout` | Controls how long the cluster network driver waits between Failover Cluster Service heartbeats before it determines that the Failover Cluster Service has stopped responding. | gauge | `name` |
| `mscluster_cluster_ClusSvcRegroupOpeningTimeout` | Controls how long a node will wait on other nodes in the opening stage before deciding that they failed. | gauge | `name` |
| `mscluster_cluster_ClusSvcRegroupPruningTimeout` | Controls how long the membership leader will wait to reach full connectivity between cluster nodes. | gauge | `name` |
| `mscluster_cluster_ClusSvcRegroupStageTimeout` | Controls how long a node will wait on other nodes in a membership stage before deciding that they failed. | gauge | `name` |
| `mscluster_cluster_ClusSvcRegroupTickInMilliseconds` | Controls how frequently the membership algorithm is sending periodic membership messages. | gauge | `name` |
| `mscluster_cluster_ClusterEnforcedAntiAffinity` | Enables or disables hard enforcement of group anti-affinity classes. | gauge | `name` |
| `mscluster_cluster_ClusterFunctionalLevel` | The functional level the cluster is currently running in. | gauge | `name` |
| `mscluster_cluster_ClusterGroupWaitDelay` | Maximum time in seconds that a group waits for its preferred node to come online during cluster startup before coming online on a different node. | gauge | `name` |
| `mscluster_cluster_ClusterLogLevel` | Controls the level of cluster logging. | gauge | `name` |
| `mscluster_cluster_ClusterLogSize` | Controls the maximum size of the cluster log files on each of the nodes. | gauge | `name` |
| `mscluster_cluster_ClusterUpgradeVersion` | Specifies the upgrade version the cluster is currently running in. | gauge | `name` |
| `mscluster_cluster_CrossSiteDelay` | Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across sites. | gauge | `name` |
| `mscluster_cluster_CrossSiteThreshold` | Controls how many Cluster Service heartbeats can be missed across sites before it determines that Cluster Service has stopped responding. | gauge | `name` |
| `mscluster_cluster_CrossSubnetDelay` | Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across subnets. | gauge | `name` |
| `mscluster_cluster_CrossSubnetThreshold` | Controls how many Cluster Service heartbeats can be missed across subnets before it determines that Cluster Service has stopped responding. | gauge | `name` |
| `mscluster_cluster_CsvBalancer` | Whether automatic balancing for CSV is enabled. | gauge | `name` |
| `mscluster_cluster_DatabaseReadWriteMode` | Sets the database read and write mode. | gauge | `name` |
| `mscluster_cluster_DefaultNetworkRole` | Provides access to the cluster's DefaultNetworkRole property. | gauge | `name` |
| `mscluster_cluster_DetectedCloudPlatform` | | gauge | `name` |
| `mscluster_cluster_DetectManagedEvents` | | gauge | `name` |
| `mscluster_cluster_DetectManagedEventsThreshold` | | gauge | `name` |
| `mscluster_cluster_DisableGroupPreferredOwnerRandomization` | | gauge | `name` |
| `mscluster_cluster_DrainOnShutdown` | Whether to drain the node when cluster service is being stopped. | gauge | `name` |
| `mscluster_cluster_DynamicQuorumEnabled` | Allows cluster service to adjust node weights as needed to increase availability. | gauge | `name` |
| `mscluster_cluster_EnableSharedVolumes` | Enables or disables cluster shared volumes on this cluster. | gauge | `name` |
| `mscluster_cluster_FixQuorum` | Provides access to the cluster's FixQuorum property, which specifies if the cluster is in a fix quorum state. | gauge | `name` |
| `mscluster_cluster_GracePeriodEnabled` | Whether the node grace period feature of this cluster is enabled. | gauge | `name` |
| `mscluster_cluster_GracePeriodTimeout` | The grace period timeout in milliseconds. | gauge | `name` |
| `mscluster_cluster_GroupDependencyTimeout` | The timeout after which a group will be brought online despite unsatisfied dependencies | gauge | `name` |
| `mscluster_cluster_HangRecoveryAction` | Controls the action to take if the user-mode processes have stopped responding. | gauge | `name` |
| `mscluster_cluster_IgnorePersistentStateOnStartup` | Provides access to the cluster's IgnorePersistentStateOnStartup property, which specifies whether the cluster will bring online groups that were online when the cluster was shut down. | gauge | `name` |
| `mscluster_cluster_LogResourceControls` | Controls the logging of resource controls. | gauge | `name` |
| `mscluster_cluster_LowerQuorumPriorityNodeId` | Specifies the Node ID that has a lower priority when voting for quorum is performed. If the quorum vote is split 50/50%, the specified node's vote would be ignored to break the tie. If this is not set then the cluster will pick a node at random to break the tie. | gauge | `name` |
| `mscluster_cluster_MaxNumberOfNodes` | Indicates the maximum number of nodes that may participate in the Cluster. | gauge | `name` |
| `mscluster_cluster_MessageBufferLength` | The maximum unacknowledged message count for GEM. | gauge | `name` |
| `mscluster_cluster_MinimumNeverPreemptPriority` | Groups with this priority or higher cannot be preempted. | gauge | `name` |
| `mscluster_cluster_MinimumPreemptorPriority` | Minimum priority a cluster group must have to be able to preempt another group. | gauge | `name` |
| `mscluster_cluster_NetftIPSecEnabled` | Whether IPSec is enabled for cluster internal traffic. | gauge | `name` |
| `mscluster_cluster_PlacementOptions` | Various option flags to modify default placement behavior. | gauge | `name` |
| `mscluster_cluster_PlumbAllCrossSubnetRoutes` | Plumbs all possible cross subnet routes to all nodes. | gauge | `name` |
| `mscluster_cluster_PreventQuorum` | Whether the cluster will ignore group persistent state on startup. | gauge | `name` |
| `mscluster_cluster_QuarantineDuration` | The quarantine period timeout in milliseconds. | gauge | `name` |
| `mscluster_cluster_QuarantineThreshold` | Number of node failures before it will be quarantined. | gauge | `name` |
| `mscluster_cluster_QuorumArbitrationTimeMax` | Controls the maximum time necessary to decide the Quorum owner node. | gauge | `name` |
| `mscluster_cluster_QuorumArbitrationTimeMin` | Controls the minimum time necessary to decide the Quorum owner node. | gauge | `name` |
| `mscluster_cluster_QuorumLogFileSize` | This property is obsolete. | gauge | `name` |
| `mscluster_cluster_QuorumTypeValue` | Get the current quorum type value. -1: Unknown; 1: Node; 2: FileShareWitness; 3: Storage; 4: None | gauge | `name` |
| `mscluster_cluster_RequestReplyTimeout` | Controls the request reply time-out period. | gauge | `name` |
| `mscluster_cluster_ResiliencyDefaultPeriod` | The default resiliency period, in seconds, for the cluster. | gauge | `name` |
| `mscluster_cluster_ResiliencyLevel` | The resiliency level for the cluster. | gauge | `name` |
| `mscluster_cluster_ResourceDllDeadlockPeriod` | This property is obsolete. | gauge | `name` |
| `mscluster_cluster_RootMemoryReserved` | Controls the amount of memory reserved for the parent partition on all cluster nodes. | gauge | `name` |
| `mscluster_cluster_RouteHistoryLength` | The history length for routes to help finding network issues. | gauge | `name` |
| `mscluster_cluster_S2DBusTypes` | Bus types for storage spaces direct. | gauge | `name` |
| `mscluster_cluster_S2DCacheDesiredState` | Desired state of the storage spaces direct cache. | gauge | `name` |
| `mscluster_cluster_S2DCacheFlashReservePercent` | Percentage of allocated flash space to utilize when caching. | gauge | `name` |
| `mscluster_cluster_S2DCachePageSizeKBytes` | Page size in KB used by S2D cache. | gauge | `name` |
| `mscluster_cluster_S2DEnabled` | Whether direct attached storage (DAS) is enabled. | gauge | `name` |
| `mscluster_cluster_S2DIOLatencyThreshold` | The I/O latency threshold for storage spaces direct. | gauge | `name` |
| `mscluster_cluster_S2DOptimizations` | Optimization flags for storage spaces direct. | gauge | `name` |
| `mscluster_cluster_SameSubnetDelay` | Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats on the same subnet. | gauge | `name` |
| `mscluster_cluster_SameSubnetThreshold` | Controls how many Cluster Service heartbeats can be missed on the same subnet before it determines that Cluster Service has stopped responding. | gauge | `name` |
| `mscluster_cluster_SecurityLevel` | Controls the level of security that should apply to intracluster messages. 0: Clear Text; 1: Sign; 2: Encrypt | gauge | `name` |
| `mscluster_cluster_SecurityLevelForStorage` | | gauge | `name` |
| `mscluster_cluster_SharedVolumeVssWriterOperationTimeout` | CSV VSS Writer operation timeout in seconds. | gauge | `name` |
| `mscluster_cluster_ShutdownTimeoutInMinutes` | The maximum time in minutes allowed for cluster resources to come offline during cluster service shutdown. | gauge | `name` |
| `mscluster_cluster_UseClientAccessNetworksForSharedVolumes` | Whether the use of client access networks for cluster shared volumes feature of this cluster is enabled. 0: Disabled; 1: Enabled; 2: Auto | gauge | `name` |
| `mscluster_cluster_WitnessDatabaseWriteTimeout` | Controls the maximum time in seconds that a cluster database write to a witness can take before the write is abandoned. | gauge | `name` |
| `mscluster_cluster_WitnessDynamicWeight` | The weight of the configured witness. | gauge | `name` |
| `mscluster_cluster_WitnessRestartInterval` | Controls the witness restart interval. | gauge | `name` |
### Network
| Name | Description | Type | Labels |
|-------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|--------|
| `mscluster_network_Characteristics` | Provides the characteristics of the network. The cluster defines characteristics only for resources. For a description of these characteristics, see [CLUSCTL_RESOURCE_GET_CHARACTERISTICS](https://msdn.microsoft.com/library/aa367466). | gauge | `name` |
| `mscluster_network_Flags` | Provides access to the flags set for the network. The cluster defines flags only for resources. For a description of these flags, see [CLUSCTL_RESOURCE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-flags). | gauge | `name` |
| `mscluster_network_Metric` | The metric of a cluster network (networks with lower values are used first). If this value is set, then the AutoMetric property is set to false. | gauge | `name` |
| `mscluster_network_Role` | Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both | gauge | `name` |
| `mscluster_network_State` | Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up | gauge | `name` |
### Network
| Name | Description | Type | Labels |
|----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|--------|
| `mscluster_node_BuildNumber` | Provides access to the node's BuildNumber property. | gauge | `name` |
| `mscluster_node_Characteristics` | Provides access to the characteristics set for the node. For a list of possible characteristics, see [CLUSCTL_NODE_GET_CHARACTERISTICS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-node-get-characteristics). | gauge | `name` |
| `mscluster_node_DetectedCloudPlatform` | The dynamic vote weight of the node adjusted by dynamic quorum feature. | gauge | `name` |
| `mscluster_node_DynamicWeight` | The dynamic vote weight of the node adjusted by dynamic quorum feature. | gauge | `name` |
| `mscluster_node_Flags` | Provides access to the flags set for the node. For a list of possible characteristics, see [CLUSCTL_NODE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-node-get-flags). | gauge | `name` |
| `mscluster_node_MajorVersion` | Provides access to the node's MajorVersion property, which specifies the major portion of the Windows version installed. | gauge | `name` |
| `mscluster_node_MinorVersion` | Provides access to the node's MinorVersion property, which specifies the minor portion of the Windows version installed. | gauge | `name` |
| `mscluster_node_NeedsPreventQuorum` | Whether the cluster service on that node should be started with prevent quorum flag. | gauge | `name` |
| `mscluster_node_NodeDrainStatus` | The current node drain status of a node. 0: Not Initiated; 1: In Progress; 2: Completed; 3: Failed | gauge | `name` |
| `mscluster_node_NodeHighestVersion` | Provides access to the node's NodeHighestVersion property, which specifies the highest possible version of the cluster service with which the node can join or communicate. | gauge | `name` |
| `mscluster_node_NodeLowestVersion` | Provides access to the node's NodeLowestVersion property, which specifies the lowest possible version of the cluster service with which the node can join or communicate. | gauge | `name` |
| `mscluster_node_NodeWeight` | The vote weight of the node. | gauge | `name` |
| `mscluster_node_State` | Returns the current state of a node. -1: Unknown; 0: Up; 1: Down; 2: Paused; 3: Joining | gauge | `name` |
| `mscluster_node_StatusInformation` | The isolation or quarantine status of the node. | gauge | `name` |
### Resource
| Name | Description | Type | Labels |
|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|--------------------------------------------|
| `mscluster_resource_Characteristics` | Provides the characteristics of the object. The cluster defines characteristics only for resources. For a description of these characteristics, see [CLUSCTL_RESOURCE_GET_CHARACTERISTICS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-characteristics). | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_DeadlockTimeout` | Indicates the length of time to wait, in milliseconds, before declaring a deadlock in any call into a resource. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_EmbeddedFailureAction` | The time, in milliseconds, that a resource should remain in a failed state before the Cluster service attempts to restart it. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_Flags` | Provides access to the flags set for the object. The cluster defines flags only for resources. For a description of these flags, see [CLUSCTL_RESOURCE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-flags). | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_IsAlivePollInterval` | Provides access to the resource's IsAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it is operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the IsAlivePollInterval property for the resource type associated with the resource. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_LooksAlivePollInterval` | Provides access to the resource's LooksAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it appears operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the LooksAlivePollInterval property for the resource type associated with the resource. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_MonitorProcessId` | Provides the process ID of the resource host service that is currently hosting the resource. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_OwnerNode` | The node hosting the resource. | gauge | `type`, `owner_group`, `node_name`, `name` |
| `mscluster_resource_PendingTimeout` | Provides access to the resource's PendingTimeout property. If a resource cannot be brought online or taken offline in the number of milliseconds specified by the PendingTimeout property, the resource is forcibly terminated. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_ResourceClass` | Gets or sets the resource class of a resource. 0: Unknown; 1: Storage; 2: Network; 32768: Unknown | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_RestartAction` | Provides access to the resource's RestartAction property, which is the action to be taken by the Cluster Service if the resource fails. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_RestartDelay` | Indicates the time delay before a failed resource is restarted. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_RestartPeriod` | Provides access to the resource's RestartPeriod property, which is interval of time, in milliseconds, during which a specified number of restart attempts can be made on a nonresponsive resource. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_RestartThreshold` | Provides access to the resource's RestartThreshold property which is the maximum number of restart attempts that can be made on a resource within an interval defined by the RestartPeriod property before the Cluster Service initiates the action specified by the RestartAction property. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_RetryPeriodOnFailure` | Provides access to the resource's RetryPeriodOnFailure property, which is the interval of time (in milliseconds) that a resource should remain in a failed state before the Cluster service attempts to restart it. | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_State` | The current state of the resource. -1: Unknown; 0: Inherited; 1: Initializing; 2: Online; 3: Offline; 4: Failed; 128: Pending; 129: Online Pending; 130: Offline Pending | gauge | `type`, `owner_group`, `name` |
| `mscluster_resource_Subclass` | Provides the list of references to nodes that can be the owner of this resource. | gauge | `type`, `owner_group`, `name` |
## ResourceGroup
| Name | Description | Type | Labels |
|-----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|---------------------|
| `mscluster_resourcegroup_AutoFailbackType` | Provides access to the group's AutoFailbackType property. | gauge | `name` |
| `mscluster_resourcegroup_Characteristics` | Provides the characteristics of the group. The cluster defines characteristics only for resources. For a description of these characteristics, see [CLUSCTL_RESOURCE_GET_CHARACTERISTICS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-characteristics). | gauge | `name` |
| `mscluster_resourcegroup_ColdStartSetting` | Indicates whether a group can start after a cluster cold start. | gauge | `name` |
| `mscluster_resourcegroup_DefaultOwner` | Number of the last node the resource group was activated on or explicitly moved to. | gauge | `name` |
| `mscluster_resourcegroup_FailbackWindowEnd` | The FailbackWindowEnd property provides the latest time that the group can be moved back to the node identified as its preferred node. | gauge | `name` |
| `mscluster_resourcegroup_FailbackWindowStart` | The FailbackWindowStart property provides the earliest time (that is, local time as kept by the cluster) that the group can be moved back to the node identified as its preferred node. | gauge | `name` |
| `mscluster_resourcegroup_FailoverPeriod` | The FailoverPeriod property specifies a number of hours during which a maximum number of failover attempts, specified by the FailoverThreshold property, can occur. | gauge | `name` |
| `mscluster_resourcegroup_FailoverThreshold` | The FailoverThreshold property specifies the maximum number of failover attempts. | gauge | `name` |
| `mscluster_resourcegroup_Flags` | Provides access to the flags set for the group. The cluster defines flags only for resources. For a description of these flags, see [CLUSCTL_RESOURCE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-flags). | gauge | `name` |
| `mscluster_resourcegroup_GroupType` | The Type of the resource group. | gauge | `name` |
| `mscluster_resourcegroup_OwnerNode` | The node hosting the resource group. | gauge | `node_name`, `name` |
| `mscluster_resourcegroup_Priority` | Priority value of the resource group | gauge | `name` |
| `mscluster_resourcegroup_ResiliencyPeriod` | The resiliency period for this group, in seconds. | gauge | `name` |
| `mscluster_resourcegroup_State` | The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending | gauge | `name` |
| `mscluster_resourcegroup_UpdateDomain` | | gauge | `name` |
### Example metric
Query the state of all cluster resource owned by node1
```
windows_mscluster_resource_owner_node{node_name="node1"}
```
## Useful queries
Counts the number of Network Name cluster resource
```
count(windows_mscluster_resource_state{type="Network Name"})
```
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -1,104 +0,0 @@
# mscluster_cluster collector
The MSCluster_Cluster class is a dynamic WMI class that represents a cluster.
|||
-|-
Metric name prefix | `mscluster_cluster`
Classes | `MSCluster_Cluster`
Enabled by default? | No
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`AddEvictDelay` | 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. | gauge | `name`
`AdminAccessPoint` | The type of the cluster administrative access point. | gauge | `name`
`AutoAssignNodeSite` | Determines whether or not the cluster will attempt to automatically assign nodes to sites based on networks and Active Directory Site information. | gauge | `name`
`AutoBalancerLevel` | Determines the level of aggressiveness of AutoBalancer. | gauge | `name`
`AutoBalancerMode` | Determines whether or not the auto balancer is enabled. | gauge | `name`
`BackupInProgress` | Indicates whether a backup is in progress. | gauge | `name`
`BlockCacheSize` | CSV BlockCache Size in MB. | gauge | `name`
`ClusSvcHangTimeout` | Controls how long the cluster network driver waits between Failover Cluster Service heartbeats before it determines that the Failover Cluster Service has stopped responding. | gauge | `name`
`ClusSvcRegroupOpeningTimeout` | Controls how long a node will wait on other nodes in the opening stage before deciding that they failed. | gauge | `name`
`ClusSvcRegroupPruningTimeout` | Controls how long the membership leader will wait to reach full connectivity between cluster nodes. | gauge | `name`
`ClusSvcRegroupStageTimeout` | Controls how long a node will wait on other nodes in a membership stage before deciding that they failed. | gauge | `name`
`ClusSvcRegroupTickInMilliseconds` | Controls how frequently the membership algorithm is sending periodic membership messages. | gauge | `name`
`ClusterEnforcedAntiAffinity` | Enables or disables hard enforcement of group anti-affinity classes. | gauge | `name`
`ClusterFunctionalLevel` | The functional level the cluster is currently running in. | gauge | `name`
`ClusterGroupWaitDelay` | Maximum time in seconds that a group waits for its preferred node to come online during cluster startup before coming online on a different node. | gauge | `name`
`ClusterLogLevel` | Controls the level of cluster logging. | gauge | `name`
`ClusterLogSize` | Controls the maximum size of the cluster log files on each of the nodes. | gauge | `name`
`ClusterUpgradeVersion` | Specifies the upgrade version the cluster is currently running in. | gauge | `name`
`CrossSiteDelay` | Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across sites. | gauge | `name`
`CrossSiteThreshold` | Controls how many Cluster Service heartbeats can be missed across sites before it determines that Cluster Service has stopped responding. | gauge | `name`
`CrossSubnetDelay` | Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across subnets. | gauge | `name`
`CrossSubnetThreshold` | Controls how many Cluster Service heartbeats can be missed across subnets before it determines that Cluster Service has stopped responding. | gauge | `name`
`CsvBalancer` | Whether automatic balancing for CSV is enabled. | gauge | `name`
`DatabaseReadWriteMode` | Sets the database read and write mode. | gauge | `name`
`DefaultNetworkRole` | Provides access to the cluster's DefaultNetworkRole property. | gauge | `name`
`DetectedCloudPlatform` | | gauge | `name`
`DetectManagedEvents` | | gauge | `name`
`DetectManagedEventsThreshold` | | gauge | `name`
`DisableGroupPreferredOwnerRandomization` | | gauge | `name`
`DrainOnShutdown` | Whether to drain the node when cluster service is being stopped. | gauge | `name`
`DynamicQuorumEnabled` | Allows cluster service to adjust node weights as needed to increase availability. | gauge | `name`
`EnableSharedVolumes` | Enables or disables cluster shared volumes on this cluster. | gauge | `name`
`FixQuorum` | Provides access to the cluster's FixQuorum property, which specifies if the cluster is in a fix quorum state. | gauge | `name`
`GracePeriodEnabled` | Whether the node grace period feature of this cluster is enabled. | gauge | `name`
`GracePeriodTimeout` | The grace period timeout in milliseconds. | gauge | `name`
`GroupDependencyTimeout` | The timeout after which a group will be brought online despite unsatisfied dependencies | gauge | `name`
`HangRecoveryAction` | Controls the action to take if the user-mode processes have stopped responding. | gauge | `name`
`IgnorePersistentStateOnStartup` | Provides access to the cluster's IgnorePersistentStateOnStartup property, which specifies whether the cluster will bring online groups that were online when the cluster was shut down. | gauge | `name`
`LogResourceControls` | Controls the logging of resource controls. | gauge | `name`
`LowerQuorumPriorityNodeId` | Specifies the Node ID that has a lower priority when voting for quorum is performed. If the quorum vote is split 50/50%, the specified node's vote would be ignored to break the tie. If this is not set then the cluster will pick a node at random to break the tie. | gauge | `name`
`MaxNumberOfNodes` | Indicates the maximum number of nodes that may participate in the Cluster. | gauge | `name`
`MessageBufferLength` | The maximum unacknowledged message count for GEM. | gauge | `name`
`MinimumNeverPreemptPriority` | Groups with this priority or higher cannot be preempted. | gauge | `name`
`MinimumPreemptorPriority` | Minimum priority a cluster group must have to be able to preempt another group. | gauge | `name`
`NetftIPSecEnabled` | Whether IPSec is enabled for cluster internal traffic. | gauge | `name`
`PlacementOptions` | Various option flags to modify default placement behavior. | gauge | `name`
`PlumbAllCrossSubnetRoutes` | Plumbs all possible cross subnet routes to all nodes. | gauge | `name`
`PreventQuorum` | Whether the cluster will ignore group persistent state on startup. | gauge | `name`
`QuarantineDuration` | The quarantine period timeout in milliseconds. | gauge | `name`
`QuarantineThreshold` | Number of node failures before it will be quarantined. | gauge | `name`
`QuorumArbitrationTimeMax` | Controls the maximum time necessary to decide the Quorum owner node. | gauge | `name`
`QuorumArbitrationTimeMin` | Controls the minimum time necessary to decide the Quorum owner node. | gauge | `name`
`QuorumLogFileSize` | This property is obsolete. | gauge | `name`
`QuorumTypeValue` | Get the current quorum type value. -1: Unknown; 1: Node; 2: FileShareWitness; 3: Storage; 4: None | gauge | `name`
`RequestReplyTimeout` | Controls the request reply time-out period. | gauge | `name`
`ResiliencyDefaultPeriod` | The default resiliency period, in seconds, for the cluster. | gauge | `name`
`ResiliencyLevel` | The resiliency level for the cluster. | gauge | `name`
`ResourceDllDeadlockPeriod` | This property is obsolete. | gauge | `name`
`RootMemoryReserved` | Controls the amount of memory reserved for the parent partition on all cluster nodes. | gauge | `name`
`RouteHistoryLength` | The history length for routes to help finding network issues. | gauge | `name`
`S2DBusTypes` | Bus types for storage spaces direct. | gauge | `name`
`S2DCacheDesiredState` | Desired state of the storage spaces direct cache. | gauge | `name`
`S2DCacheFlashReservePercent` | Percentage of allocated flash space to utilize when caching. | gauge | `name`
`S2DCachePageSizeKBytes` | Page size in KB used by S2D cache. | gauge | `name`
`S2DEnabled` | Whether direct attached storage (DAS) is enabled. | gauge | `name`
`S2DIOLatencyThreshold` | The I/O latency threshold for storage spaces direct. | gauge | `name`
`S2DOptimizations` | Optimization flags for storage spaces direct. | gauge | `name`
`SameSubnetDelay` | Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats on the same subnet. | gauge | `name`
`SameSubnetThreshold` | Controls how many Cluster Service heartbeats can be missed on the same subnet before it determines that Cluster Service has stopped responding. | gauge | `name`
`SecurityLevel` | Controls the level of security that should apply to intracluster messages. 0: Clear Text; 1: Sign; 2: Encrypt | gauge | `name`
`SecurityLevelForStorage` | | gauge | `name`
`SharedVolumeVssWriterOperationTimeout` | CSV VSS Writer operation timeout in seconds. | gauge | `name`
`ShutdownTimeoutInMinutes` | The maximum time in minutes allowed for cluster resources to come offline during cluster service shutdown. | gauge | `name`
`UseClientAccessNetworksForSharedVolumes` | Whether the use of client access networks for cluster shared volumes feature of this cluster is enabled. 0: Disabled; 1: Enabled; 2: Auto | gauge | `name`
`WitnessDatabaseWriteTimeout` | Controls the maximum time in seconds that a cluster database write to a witness can take before the write is abandoned. | gauge | `name`
`WitnessDynamicWeight` | The weight of the configured witness. | gauge | `name`
`WitnessRestartInterval` | Controls the witness restart interval. | gauge | `name`
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -1,32 +0,0 @@
# mscluster_network collector
The MSCluster_Network class is a dynamic WMI class that represents cluster networks.
|||
-|-
Metric name prefix | `mscluster_network`
Classes | `MSCluster_Network`
Enabled by default? | No
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`Characteristics` | Provides the characteristics of the network. The cluster defines characteristics only for resources. For a description of these characteristics, see [CLUSCTL_RESOURCE_GET_CHARACTERISTICS](https://msdn.microsoft.com/library/aa367466). | gauge | `name`
`Flags` | Provides access to the flags set for the network. The cluster defines flags only for resources. For a description of these flags, see [CLUSCTL_RESOURCE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-flags). | gauge | `name`
`Metric` | The metric of a cluster network (networks with lower values are used first). If this value is set, then the AutoMetric property is set to false. | gauge | `name`
`Role` | Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both | gauge | `name`
`State` | Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up | gauge | `name`
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -1,41 +0,0 @@
# mscluster_node collector
The MSCluster_Node class is a dynamic WMI class that represents a cluster node.
|||
-|-
Metric name prefix | `mscluster_node`
Classes | `MSCluster_Node`
Enabled by default? | No
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`BuildNumber` | Provides access to the node's BuildNumber property. | gauge | `name`
`Characteristics` | Provides access to the characteristics set for the node. For a list of possible characteristics, see [CLUSCTL_NODE_GET_CHARACTERISTICS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-node-get-characteristics). | gauge | `name`
`DetectedCloudPlatform` | The dynamic vote weight of the node adjusted by dynamic quorum feature. | gauge | `name`
`DynamicWeight` | The dynamic vote weight of the node adjusted by dynamic quorum feature. | gauge | `name`
`Flags` | Provides access to the flags set for the node. For a list of possible characteristics, see [CLUSCTL_NODE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-node-get-flags). | gauge | `name`
`MajorVersion` | Provides access to the node's MajorVersion property, which specifies the major portion of the Windows version installed. | gauge | `name`
`MinorVersion` | Provides access to the node's MinorVersion property, which specifies the minor portion of the Windows version installed. | gauge | `name`
`NeedsPreventQuorum` | Whether the cluster service on that node should be started with prevent quorum flag. | gauge | `name`
`NodeDrainStatus` | The current node drain status of a node. 0: Not Initiated; 1: In Progress; 2: Completed; 3: Failed | gauge | `name`
`NodeHighestVersion` | Provides access to the node's NodeHighestVersion property, which specifies the highest possible version of the cluster service with which the node can join or communicate. | gauge | `name`
`NodeLowestVersion` | Provides access to the node's NodeLowestVersion property, which specifies the lowest possible version of the cluster service with which the node can join or communicate. | gauge | `name`
`NodeWeight` | The vote weight of the node. | gauge | `name`
`State` | Returns the current state of a node. -1: Unknown; 0: Up; 1: Down; 2: Paused; 3: Joining | gauge | `name`
`StatusInformation` | The isolation or quarantine status of the node. | gauge | `name`
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -1,43 +0,0 @@
# mscluster_resource collector
The MSCluster_resource class is a dynamic WMI class that represents a cluster resource.
|||
-|-
Metric name prefix | `mscluster_resource`
Classes | `MSCluster_Resource`
Enabled by default? | No
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`Characteristics` | Provides the characteristics of the object. The cluster defines characteristics only for resources. For a description of these characteristics, see [CLUSCTL_RESOURCE_GET_CHARACTERISTICS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-characteristics). | gauge | `type`, `owner_group`, `name`
`DeadlockTimeout` | Indicates the length of time to wait, in milliseconds, before declaring a deadlock in any call into a resource. | gauge | `type`, `owner_group`, `name`
`EmbeddedFailureAction` | The time, in milliseconds, that a resource should remain in a failed state before the Cluster service attempts to restart it. | gauge | `type`, `owner_group`, `name`
`Flags` | Provides access to the flags set for the object. The cluster defines flags only for resources. For a description of these flags, see [CLUSCTL_RESOURCE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-flags). | gauge | `type`, `owner_group`, `name`
`IsAlivePollInterval` | Provides access to the resource's IsAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it is operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the IsAlivePollInterval property for the resource type associated with the resource. | gauge | `type`, `owner_group`, `name`
`LooksAlivePollInterval` | Provides access to the resource's LooksAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it appears operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the LooksAlivePollInterval property for the resource type associated with the resource. | gauge | `type`, `owner_group`, `name`
`MonitorProcessId` | Provides the process ID of the resource host service that is currently hosting the resource. | gauge | `type`, `owner_group`, `name`
`PendingTimeout` | Provides access to the resource's PendingTimeout property. If a resource cannot be brought online or taken offline in the number of milliseconds specified by the PendingTimeout property, the resource is forcibly terminated. | gauge | `type`, `owner_group`, `name`
`ResourceClass` | Gets or sets the resource class of a resource. 0: Unknown; 1: Storage; 2: Network; 32768: Unknown | gauge | `type`, `owner_group`, `name`
`RestartAction` | Provides access to the resource's RestartAction property, which is the action to be taken by the Cluster Service if the resource fails. | gauge | `type`, `owner_group`, `name`
`RestartDelay` | Indicates the time delay before a failed resource is restarted. | gauge | `type`, `owner_group`, `name`
`RestartPeriod` | Provides access to the resource's RestartPeriod property, which is interval of time, in milliseconds, during which a specified number of restart attempts can be made on a nonresponsive resource. | gauge | `type`, `owner_group`, `name`
`RestartThreshold` | Provides access to the resource's RestartThreshold property which is the maximum number of restart attempts that can be made on a resource within an interval defined by the RestartPeriod property before the Cluster Service initiates the action specified by the RestartAction property. | gauge | `type`, `owner_group`, `name`
`RetryPeriodOnFailure` | Provides access to the resource's RetryPeriodOnFailure property, which is the interval of time (in milliseconds) that a resource should remain in a failed state before the Cluster service attempts to restart it. | gauge | `type`, `owner_group`, `name`
`State` | The current state of the resource. -1: Unknown; 0: Inherited; 1: Initializing; 2: Online; 3: Offline; 4: Failed; 128: Pending; 129: Online Pending; 130: Offline Pending | gauge | `type`, `owner_group`, `name`
`Subclass` | Provides the list of references to nodes that can be the owner of this resource. | gauge | `type`, `owner_group`, `name`
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -1,41 +0,0 @@
# mscluster_resourcegroup collector
The MSCluster_ResourceGroup class is a dynamic WMI class that represents a cluster group.
|||
-|-
Metric name prefix | `mscluster_resourcegroup`
Classes | `MSCluster_ResourceGroup`
Enabled by default? | No
## Flags
None
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`AutoFailbackType` | Provides access to the group's AutoFailbackType property. | gauge | `name`
`Characteristics` | Provides the characteristics of the group. The cluster defines characteristics only for resources. For a description of these characteristics, see [CLUSCTL_RESOURCE_GET_CHARACTERISTICS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-characteristics). | gauge | `name`
`ColdStartSetting` | Indicates whether a group can start after a cluster cold start. | gauge | `name`
`DefaultOwner` | Number of the last node the resource group was activated on or explicitly moved to. | gauge | `name`
`FailbackWindowEnd` | The FailbackWindowEnd property provides the latest time that the group can be moved back to the node identified as its preferred node. | gauge | `name`
`FailbackWindowStart` | The FailbackWindowStart property provides the earliest time (that is, local time as kept by the cluster) that the group can be moved back to the node identified as its preferred node. | gauge | `name`
`FailoverPeriod` | The FailoverPeriod property specifies a number of hours during which a maximum number of failover attempts, specified by the FailoverThreshold property, can occur. | gauge | `name`
`FailoverThreshold` | The FailoverThreshold property specifies the maximum number of failover attempts. | gauge | `name`
`Flags` | Provides access to the flags set for the group. The cluster defines flags only for resources. For a description of these flags, see [CLUSCTL_RESOURCE_GET_FLAGS](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mscs/clusctl-resource-get-flags). | gauge | `name`
`GroupType` | The Type of the resource group. | gauge | `name`
`Priority` | Priority value of the resource group | gauge | `name`
`ResiliencyPeriod` | The resiliency period for this group, in seconds. | gauge | `name`
`State` | The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending | gauge | `name`
`UpdateDomain` | | gauge | `name`
### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -258,10 +258,23 @@ Name | Description | Type | Labels
`windows_mssql_waitstats_transaction_ownership_waits` | Statistics relevant to processes synchronizing access to transaction | gauge | `mssql_instance`, `item` `windows_mssql_waitstats_transaction_ownership_waits` | Statistics relevant to processes synchronizing access to transaction | gauge | `mssql_instance`, `item`
### Example metric ### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
Query Full table scans
```
rate(windows_mssql_accessmethods_full_scans{instance='host:9182'}[$__rate_interval])
```
## Useful queries ## Useful queries
### Database file size
This collector retrieves the two values (data file and log file) and sums the total in PromQL to give the Database file size.
```
windows_mssql_databases_data_files_size_bytes{database='DatabaseName',instance='host:9182'} + windows_mssql_databases_log_files_size_bytes{database='DatabaseName',instance='host:9182'}
```
### Buffer Cache Hit Ratio ### Buffer Cache Hit Ratio
When you read the counter in perfmon you will get the the percentage pages found in the buffer cache. This percentage is calculated internally based on the total number of cache hits divided by the total number of cache lookups over the last few thousand page accesses. When you read the counter in perfmon you will get the the percentage pages found in the buffer cache. This percentage is calculated internally based on the total number of cache hits divided by the total number of cache lookups over the last few thousand page accesses.
@@ -284,4 +297,18 @@ This principal can be used for following metrics too:
- locks_count - locks_count
## Alerting examples ## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
```
groups:
- name: database_alerts
rules:
- alert: DatabaseSizeExceeded
expr: windows_mssql_databases_data_files_size_bytes{database='DatabaseName',instance='host:9182'} + windows_mssql_databases_log_files_size_bytes{database='DatabaseName',instance='host:9182'} > 1e10 # 10 GB in bytes
for: 5m # Trigger the alert if the condition persists for 5 mins
labels:
severity: critical
annotations:
summary: "SQl EXpress Database size exceeded 10GB"
description: "The database size has grown larger than 10GB. Instance: {{ $labels.instance }}"
```

28
docs/collector.printer.md Normal file
View File

@@ -0,0 +1,28 @@
# printer collector
The printer collector exposes metrics about printers and their jobs.
| | |
|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Metric name prefix | `printer` |
| Data source | WMI |
| Classes | [Win32_Printer](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-printer) <br> [Win32_PrintJob](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-printjob) |
| Enabled by default? | false |
## Flags
### `--collector.printer.include`
If given, a printer needs to match the include regexp in order for the corresponding printer metrics to be reported
### `--collector.printer.exclude`
If given, a printer needs to *not* match the exclude regexp in order for the corresponding printer metrics to be reported
## Metrics
Name | Description | Type | Labels
-----|-------------|---------|-------
`windows_printer_status` | Status of the printer at the time the performance data is collected | counter | `printer`, `status`
`windows_printer_job_count` | Number of jobs processed by the printer since the last reset | gauge | `printer`
`windows_printer_job_status` | A counter of printer jobs by status | gauge | `printer`, `status`

View File

@@ -2,16 +2,23 @@
The process collector exposes metrics about processes. The process collector exposes metrics about processes.
||| Note, on Windows Server 2022, the `Process` counter set is disabled by default. To enable it, run the following command in an elevated PowerShell session:
-|-
Metric name prefix | `process` ```powershell
Data source | Perflib lodctr.exe /E:Lsa
Counters | `Process` lodctr.exe /E:PerfProc
Enabled by default? | No lodctr.exe /R
```
| | |
|---------------------|-----------|
| Metric name prefix | `process` |
| Data source | Perflib |
| Counters | `Process` |
| Enabled by default? | No |
## Flags ## Flags
<<<<<<< HEAD
### `--collector.process.include` ### `--collector.process.include`
Regexp of processes to include. Process name must both match `include` and not Regexp of processes to include. Process name must both match `include` and not
@@ -30,6 +37,7 @@ Enables IIS process name queries. IIS process names are combined with their app
Disabled by default, and can be enabled with `--collector.process.iis=true`. Disabled by default, and can be enabled with `--collector.process.iis=true`.
### Example ### Example
To match all firefox processes: `--collector.process.include="firefox.*"`. To match all firefox processes: `--collector.process.include="firefox.*"`.
Note that multiple processes with the same name will be disambiguated by Note that multiple processes with the same name will be disambiguated by
@@ -61,23 +69,24 @@ w3wp_Test
## Metrics ## Metrics
Name | Description | Type | Labels | Name | Description | Type | Labels |
-----|-------------|------|------- |---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------|
`windows_process_start_time` | Time of process start | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_info` | A metric with a constant '1' value labeled with process information | gauge | `process`, `process_id`, `creating_process_id`, `process_group_id`,`owner`, `cmdline` |
`windows_process_cpu_time_total` | Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user). An instruction is the basic unit of execution in a computer, a thread is the object that executes instructions, and a process is the object created when a program is run. Code executed to handle some hardware interrupts and trap conditions is included in this count. | counter | `process`, `process_id`, `creating_process_id` | `windows_process_start_time` | Time of process start | gauge | `process`, `process_id` |
`windows_process_handles` | Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_cpu_time_total` | Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user). An instruction is the basic unit of execution in a computer, a thread is the object that executes instructions, and a process is the object created when a program is run. Code executed to handle some hardware interrupts and trap conditions is included in this count. | counter | `process`, `process_id`, `mode` |
`windows_process_io_bytes_total` | Bytes issued to I/O operations in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. | counter | `process`, `process_id`, `creating_process_id` | `windows_process_handles` | Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process. | gauge | `process`, `process_id` |
`windows_process_io_operations_total` | I/O operations issued in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. | counter | `process`, `process_id`, `creating_process_id` | `windows_process_io_bytes_total` | Bytes issued to I/O operations in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. | counter | `process`, `process_id`, `mode` |
`windows_process_page_faults_total` | Page faults by the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. This can cause the page not to be fetched from disk if it is on the standby list and hence already in main memory, or if it is in use by another process with which the page is shared. | counter | `process`, `process_id`, `creating_process_id` | `windows_process_io_operations_total` | I/O operations issued in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. | counter | `process`, `process_id`, `mode` |
`windows_process_page_file_bytes` | Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_page_faults_total` | Page faults by the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. This can cause the page not to be fetched from disk if it is on the standby list and hence already in main memory, or if it is in use by another process with which the page is shared. | counter | `process`, `process_id` |
`windows_process_pool_bytes` | Pool Bytes is the last observed number of bytes in the paged or nonpaged pool. The nonpaged pool is an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. The paged pool is an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. Nonpaged pool bytes is calculated differently than paged pool bytes, so it might not equal the total of paged pool bytes. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_page_file_bytes` | Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory. | gauge | `process`, `process_id` |
`windows_process_priority_base` | Current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process base priority of the process. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_pool_bytes` | Pool Bytes is the last observed number of bytes in the paged or nonpaged pool. The nonpaged pool is an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. The paged pool is an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. Nonpaged pool bytes is calculated differently than paged pool bytes, so it might not equal the total of paged pool bytes. | gauge | `process`, `process_id`, `pool` |
`windows_process_private_bytes` | Current number of bytes this process has allocated that cannot be shared with other processes. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_priority_base` | Current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process base priority of the process. | gauge | `process`, `process_id` |
`windows_process_threads` | Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_private_bytes` | Current number of bytes this process has allocated that cannot be shared with other processes. | gauge | `process`, `process_id` |
`windows_process_virtual_bytes` | Current size, in bytes, of the virtual address space that the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_threads` | Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread. | gauge | `process`, `process_id` |
`windows_process_working_set_private_bytes` | Size of the working set, in bytes, that is use for this process only and not shared nor shareable by other processes. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_virtual_bytes` | Current size, in bytes, of the virtual address space that the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries. | gauge | `process`, `process_id` |
`windows_process_working_set_peak_bytes` | Maximum size, in bytes, of the Working Set of this process at any point in time. The Working Set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the Working Set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from Working Sets. If they are needed they will then be soft-faulted back into the Working Set before they leave main memory. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_working_set_private_bytes` | Size of the working set, in bytes, that is use for this process only and not shared nor shareable by other processes. | gauge | `process`, `process_id` |
`windows_process_working_set_bytes` | Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory. | gauge | `process`, `process_id`, `creating_process_id` | `windows_process_working_set_peak_bytes` | Maximum size, in bytes, of the Working Set of this process at any point in time. The Working Set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the Working Set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from Working Sets. If they are needed they will then be soft-faulted back into the Working Set before they leave main memory. | gauge | `process`, `process_id` |
| `windows_process_working_set_bytes` | Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory. | gauge | `process`, `process_id` |
### Example metric ### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_ _This collector does not yet have explained examples, we would appreciate your help adding them!_

View File

@@ -24,10 +24,15 @@ Name | Description | Type | Labels
`windows_remote_fx_net_current_tcp_rtt_seconds` | Average TCP round-trip time (RTT) detected in seconds. | gauge | `session_name` `windows_remote_fx_net_current_tcp_rtt_seconds` | Average TCP round-trip time (RTT) detected in seconds. | gauge | `session_name`
`windows_remote_fx_net_current_udp_bandwidth` | UDP Bandwidth detected in bytes per second. | gauge | `session_name` `windows_remote_fx_net_current_udp_bandwidth` | UDP Bandwidth detected in bytes per second. | gauge | `session_name`
`windows_remote_fx_net_current_udp_rtt_seconds` | Average UDP round-trip time (RTT) detected in seconds. | gauge | `session_name` `windows_remote_fx_net_current_udp_rtt_seconds` | Average UDP round-trip time (RTT) detected in seconds. | gauge | `session_name`
`windows_remote_fx_net_received_bytes_total` | _Not yet documented_ | counter | `session_name` `windows_remote_fx_net_received_bytes_total` | Total bytes received over the network session. | counter | `session_name`
`windows_remote_fx_net_sent_bytes_total` | _Not yet documented_ | counter | `session_name` `windows_remote_fx_net_sent_bytes_total` | Total bytes sent over the network session. | counter | `session_name`
`windows_remote_fx_net_udp_packets_received_total` | Rate in packets per second at which packets are received over UDP. | counter | `session_name` `windows_remote_fx_net_udp_packets_received_total` | Rate in packets per second at which packets are received over UDP. | counter | `session_name`
`windows_remote_fx_net_udp_packets_sent_total` | Rate in packets per second at which packets are sent over UDP. | counter | `session_name` `windows_remote_fx_net_udp_packets_sent_total` | Rate in packets per second at which packets are sent over UDP. | counter | `session_name`
`windows_remote_fx_net_loss_rate` | Network packet loss rate detected over the RemoteFX session, expressed as a percentage. | counter | `session_name`
`windows_remote_fx_net_fec_rate` | Forward Error Correction (FEC) rate applied to packets sent over the RemoteFX session, expressed as a percentage. | counter | `session_name`
`windows_remote_fx_net_retransmission_rate` Rate of packets retransmitted over the RemoteFX session, expressed as a percentage. | counter | `session_name`
## Metrics (Graphics) ## Metrics (Graphics)

View File

@@ -2,11 +2,9 @@
The service collector exposes metrics about Windows Services The service collector exposes metrics about Windows Services
||| The collector exists in 2 different version. Version 1 is using WMI to query all services and is able to provide additional
-|- information. Version 2 is a more efficient solution by directly connecting to the service manager, but is not able to
Metric name prefix | `service` provide additional information like `run_as` or start configuration
Classes | [`Win32_Service`](https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx)
Enabled by default? | Yes
## Flags ## Flags
@@ -22,6 +20,19 @@ Example config win_exporter.yml for multiple services: `services-where: Name='SQ
Uses API calls instead of WMI for performance optimization. **Note** the previous flag (`--collector.service.services-where`) won't have any effect on this mode. Uses API calls instead of WMI for performance optimization. **Note** the previous flag (`--collector.service.services-where`) won't have any effect on this mode.
### `--collector.service.v2`
Version 2 of the service collector. Is using API calls for performance optimization. **Note** the previous flag (`--collector.service.services-where`) won't have any effect on this mode.
For additional performance reasons, it doesn't provide any additional information like `run_as` or start configuration.
# collector V1
|||
-|-
Metric name prefix | `service`
Classes | [`Win32_Service`](https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx)
Enabled by default? | Yes
## Metrics ## Metrics
Name | Description | Type | Labels Name | Description | Type | Labels
@@ -91,6 +102,53 @@ Counts the number of Microsoft SQL Server/Agent Processes
count(windows_service_state{exported_name=~"(sqlserveragent|mssqlserver)",state="running"}) count(windows_service_state{exported_name=~"(sqlserveragent|mssqlserver)",state="running"})
``` ```
# collector V2
|||
-|-
Metric name prefix | `service`
Classes | none
Enabled by default? | No
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_service_state` | The state of the service, 1 if the current state, 0 otherwise | gauge | name, display_name, state
### States
A service can be in the following states:
- `stopped`
- `start pending`
- `stop pending`
- `running`
- `continue pending`
- `pause pending`
- `paused`
- `unknown`
### Example metric
```
windows_service_state{display_name="Declared Configuration(DC) service",name="dcsvc",status="continue pending"} 0
windows_service_state{display_name="Declared Configuration(DC) service",name="dcsvc",status="pause pending"} 0
windows_service_state{display_name="Declared Configuration(DC) service",name="dcsvc",status="paused"} 0
windows_service_state{display_name="Declared Configuration(DC) service",name="dcsvc",status="running"} 0
windows_service_state{display_name="Declared Configuration(DC) service",name="dcsvc",status="start pending"} 0
windows_service_state{display_name="Declared Configuration(DC) service",name="dcsvc",status="stop pending"} 0
windows_service_state{display_name="Declared Configuration(DC) service",name="dcsvc",status="stopped"} 1
```
## Useful queries
Counts the number of Microsoft SQL Server/Agent Processes
```
count(windows_service_state{name=~"(sqlserveragent|mssqlserver)",state="running"})
```
## Alerting examples ## Alerting examples
**prometheus.rules** **prometheus.rules**
```yaml ```yaml
@@ -100,7 +158,7 @@ groups:
# Sends an alert when the 'sqlserveragent' service is not in the running state for 3 minutes. # Sends an alert when the 'sqlserveragent' service is not in the running state for 3 minutes.
- alert: SQL Server Agent DOWN - alert: SQL Server Agent DOWN
expr: windows_service_state{instance="SQL",exported_name="sqlserveragent",state="running"} == 0 expr: windows_service_state{instance="SQL",name="sqlserveragent",state="running"} == 0
for: 3m for: 3m
labels: labels:
severity: high severity: high
@@ -110,7 +168,7 @@ groups:
# Sends an alert when the 'mssqlserver' service is not in the running state for 3 minutes. # Sends an alert when the 'mssqlserver' service is not in the running state for 3 minutes.
- alert: SQL Server DOWN - alert: SQL Server DOWN
expr: windows_service_state{instance="SQL",exported_name="mssqlserver",state="running"} == 0 expr: windows_service_state{instance="SQL",name="mssqlserver",state="running"} == 0
for: 3m for: 3m
labels: labels:
severity: high severity: high

View File

@@ -0,0 +1,50 @@
# smbclient collector
The smbclient collector collects metrics from MS SmbClient hosts through perflib
|||
-|-
Metric name prefix | `windows_smbclient`
Classes | [Win32_PerfRawData_SMB](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-smb/)<br/>
Enabled by default? | No
## Flags
### `--collectors.smbclient.list`
Lists the Perflib Objects that are queried for data along with the perlfib object id
### `--collectors.smbclient.enabled`
Comma-separated list of collectors to use, for example: `--collectors.smbclient.enabled=ServerShares`. Matching is case-sensitive. Depending on the smb protocol version not all performance counters may be available. Use `--collectors.smbclient.list` to obtain a list of supported collectors.
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`windows_smbclient_data_queue_seconds_total` | Seconds requests waited on queue on this share | counter | `server`, `share`|
`windows_smbclient_read_queue_seconds_total` | Seconds read requests waited on queue on this share | counter | `server`, `share`|
`windows_smbclient_write_queue_seconds_total` | Seconds write requests waited on queue on this share | counter | `server`, `share`|
`windows_smbclient_request_seconds_total` | Seconds waiting for requests on this share | counter | `server`, `share`|
`windows_smbclient_stalls_total` | The number of requests delayed based on insufficient credits on this share | counter | `server`, `share`|
`windows_smbclient_requests_queued` | The point in time (current) number of requests outstanding on this share | counter | `server`, `share`|
`windows_smbclient_data_bytes_total` | The bytes read or written on this share | counter | `server`, `share`|
`windows_smbclient_requests_total` | The requests on this share | counter | `server`, `share`|
`windows_smbclient_metadata_requests_total` | The metadata requests on this share | counter | `server`, `share`|
`windows_smbclient_read_bytes_via_smbdirect_total` | The bytes read from this share via RDMA direct placement | TBD | `server`, `share`|
`windows_smbclient_read_bytes_total` | The bytes read on this share | counter | `server`, `share`|
`windows_smbclient_read_requests_via_smbdirect_total` | The read requests on this share via RDMA direct placement | TBD | `server`, `share`|
`windows_smbclient_read_requests_total` | The read requests on this share | counter | `server`, `share`|
`windows_smbclient_turbo_io_reads_total` | The read requests that go through Turbo I/O | TBD | `server`, `share`|
`windows_smbclient_turbo_io_writes_total` | The write requests that go through Turbo I/O | TBD | `server`, `share`|
`windows_smbclient_write_bytes_via_smbdirect_total` | The written bytes to this share via RDMA direct placement | TBD | `server`, `share`|
`windows_smbclient_write_bytes_total` | The bytes written on this share | counter | `server`, `share`|
`windows_smbclient_write_requests_via_smbdirect_total` | The write requests to this share via RDMA direct placement | TBD | `server`, `share`|
`windows_smbclient_write_requests_total` | The write requests on this share | counter | `server`, `share`|
`windows_smbclient_read_seconds_total` | Seconds waiting for read requests on this share | counter | `server`, `share`|
`windows_smbclient_write_seconds_total` | Seconds waiting for write requests on this share | counter | `server`, `share`|
## Useful queries
```
# Average request queue length (includes read and write).
irate(windows_smbclient_data_queue_seconds_total)
# Request latency milliseconds (includes read and write).
irate(windows_smbclient_request_seconds_total) / irate(windows_smbclient_requests_total) * 1000
```
## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -2,12 +2,13 @@
The terminal_services collector exposes terminal services (Remote Desktop Services) performance metrics. The terminal_services collector exposes terminal services (Remote Desktop Services) performance metrics.
||| | | |
-|- |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Metric name prefix | `terminal_services` | __Metric name prefix__ | `terminal_services` |
Data source | Perflib/WMI | __Data source__ | Perflib/WMI, Win32 |
Classes | [`Win32_PerfRawData_LocalSessionManager_TerminalServices`](https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/), [`Win32_PerfRawData_TermService_TerminalServicesSession`](https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85)), [`Win32_PerfRawData_RemoteDesktopConnectionBrokerPerformanceCounterProvider_RemoteDesktopConnectionBrokerCounterset`](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/mt729067(v%3Dws.11)) | __Classes__ | [`Win32_PerfRawData_LocalSessionManager_TerminalServices`](https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/), [`Win32_PerfRawData_TermService_TerminalServicesSession`](https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85)), [`Win32_PerfRawData_RemoteDesktopConnectionBrokerPerformanceCounterProvider_RemoteDesktopConnectionBrokerCounterset`](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/mt729067(v%3Dws.11)) |
Enabled by default? | No | __Win32 API__ | [WTSEnumerateSessionsEx](https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumeratesessionsexw) |
| __Enabled by default?__ | No |
## Flags ## Flags
@@ -15,34 +16,115 @@ None
## Metrics ## Metrics
Name | Description | Type | Labels | Name | Description | Type | Labels |
-----|-------------|------|------- |------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------------|
`windows_terminal_services_local_session_count` | Number of local Terminal Services sessions. | gauge | `session` | `windows_terminal_services_session_info` | Info about active WTS sessions | gauge | host,user,state |
`windows_terminal_services_connection_broker_performance_total`* | The total number of connections handled by the Connection Brokers since the service started. | counter | `connection` | `windows_terminal_services_connection_broker_performance_total`* | The total number of connections handled by the Connection Brokers since the service started. | counter | `connection` |
`windows_terminal_services_handles` | Total number of handles currently opened by this process. This number is the sum of the handles currently opened by each thread in this process. | gauge | `session_name` | `windows_terminal_services_handles` | Total number of handles currently opened by this process. This number is the sum of the handles currently opened by each thread in this process. | gauge | `session_name` |
`windows_terminal_services_page_fault_total` | Rate at which page faults occur in the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. The page may not be retrieved from disk if it is on the standby list and therefore already in main memory. The page also may not be retrieved if it is in use by another process which shares the page. | counter | `session_name` | `windows_terminal_services_page_fault_total` | Rate at which page faults occur in the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. The page may not be retrieved from disk if it is on the standby list and therefore already in main memory. The page also may not be retrieved if it is in use by another process which shares the page. | counter | `session_name` |
`windows_terminal_services_page_file_bytes` | Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory. | gauge | `session_name` | `windows_terminal_services_page_file_bytes` | Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory. | gauge | `session_name` |
`windows_terminal_services_page_file_bytes_peak` | Maximum number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory. | gauge | `session_name` | `windows_terminal_services_page_file_bytes_peak` | Maximum number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory. | gauge | `session_name` |
`windows_terminal_services_privileged_time_seconds_total` | total elapsed time that the threads of the process have spent executing code in privileged mode. | Counter | `session_name` | `windows_terminal_services_privileged_time_seconds_total` | total elapsed time that the threads of the process have spent executing code in privileged mode. | Counter | `session_name` |
`windows_terminal_services_processor_time_seconds_total` | total elapsed time that all of the threads of this process used the processor to execute instructions. | Counter | `session_name` | `windows_terminal_services_processor_time_seconds_total` | total elapsed time that all of the threads of this process used the processor to execute instructions. | Counter | `session_name` |
`windows_terminal_services_user_time_seconds_total` | total elapsed time that this process's threads have spent executing code in user mode. Applications, environment subsystems, and integral subsystems execute in user mode. | Counter | `session_name` | `windows_terminal_services_user_time_seconds_total` | total elapsed time that this process's threads have spent executing code in user mode. Applications, environment subsystems, and integral subsystems execute in user mode. | Counter | `session_name` |
`windows_terminal_services_pool_non_paged_bytes` | Number of bytes in the non-paged pool, an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. This property displays the last observed value only; it is not an average. | gauge | `session_name` | `windows_terminal_services_pool_non_paged_bytes` | Number of bytes in the non-paged pool, an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. This property displays the last observed value only; it is not an average. | gauge | `session_name` |
`windows_terminal_services_pool_paged_bytes` | Number of bytes in the paged pool, an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. This property displays the last observed value only; it is not an average. | gauge | `session_name` | `windows_terminal_services_pool_paged_bytes` | Number of bytes in the paged pool, an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. This property displays the last observed value only; it is not an average. | gauge | `session_name` |
`windows_terminal_services_private_bytes` | Current number of bytes this process has allocated that cannot be shared with other processes. | gauge | `session_name` | `windows_terminal_services_private_bytes` | Current number of bytes this process has allocated that cannot be shared with other processes. | gauge | `session_name` |
`windows_terminal_services_threads` | Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread. | gauge | `session_name` | `windows_terminal_services_threads` | Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread. | gauge | `session_name` |
`windows_terminal_services_virtual_bytes` | Current size, in bytes, of the virtual address space the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries. | gauge | `session_name` | `windows_terminal_services_virtual_bytes` | Current size, in bytes, of the virtual address space the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries. | gauge | `session_name` |
`windows_terminal_services_virtual_bytes_peak` | Maximum number of bytes of virtual address space the process has used at any one time. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process might limit its ability to load libraries. | gauge | `session_name` | `windows_terminal_services_virtual_bytes_peak` | Maximum number of bytes of virtual address space the process has used at any one time. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process might limit its ability to load libraries. | gauge | `session_name` |
`windows_terminal_services_working_set_bytes` | Current number of bytes in the working set of this process. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory. | gauge | `session_name` | `windows_terminal_services_working_set_bytes` | Current number of bytes in the working set of this process. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory. | gauge | `session_name` |
`windows_terminal_services_working_set_bytes_peak` | Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory. | gauge | `session_name` | `windows_terminal_services_working_set_bytes_peak` | Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory. | gauge | `session_name` |
`* windows_terminal_services_connection_broker_performance_total` only collected if server has `Remote Desktop Connection Broker` role. `* windows_terminal_services_connection_broker_performance_total` only collected if server has `Remote Desktop Connection Broker` role.
### Example metric ### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_
```
windows_remote_fx_net_udp_packets_sent_total{session_name="RDP-Tcp 0"} 0
# HELP windows_terminal_services_cpu_time_seconds_total Total elapsed time that this process's threads have spent executing code.
# TYPE windows_terminal_services_cpu_time_seconds_total counter
windows_terminal_services_cpu_time_seconds_total{mode="RDP-Tcp 0",session_name="privileged"} 98.4843739
windows_terminal_services_cpu_time_seconds_total{mode="RDP-Tcp 0",session_name="processor"} 620.4687488999999
windows_terminal_services_cpu_time_seconds_total{mode="RDP-Tcp 0",session_name="user"} 521.9843741
# HELP windows_terminal_services_handles Total number of handles currently opened by this process. This number is the sum of the handles currently opened by each thread in this process.
# TYPE windows_terminal_services_handles gauge
windows_terminal_services_handles{session_name="RDP-Tcp 0"} 20999
# HELP windows_terminal_services_page_fault_total Rate at which page faults occur in the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. The page may not be retrieved from disk if it is on the standby list and therefore already in main memory. The page also may not be retrieved if it is in use by another process which shares the page.
# TYPE windows_terminal_services_page_fault_total counter
windows_terminal_services_page_fault_total{session_name="RDP-Tcp 0"} 1.0436271e+07
# HELP windows_terminal_services_page_file_bytes Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.
# TYPE windows_terminal_services_page_file_bytes gauge
windows_terminal_services_page_file_bytes{session_name="RDP-Tcp 0"} 4.310188032e+09
# HELP windows_terminal_services_page_file_bytes_peak Maximum number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.
# TYPE windows_terminal_services_page_file_bytes_peak gauge
windows_terminal_services_page_file_bytes_peak{session_name="RDP-Tcp 0"} 4.817412096e+09
# HELP windows_terminal_services_pool_non_paged_bytes Number of bytes in the non-paged pool, an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. This property displays the last observed value only; it is not an average.
# TYPE windows_terminal_services_pool_non_paged_bytes gauge
windows_terminal_services_pool_non_paged_bytes{session_name="RDP-Tcp 0"} 1.325456e+06
# HELP windows_terminal_services_pool_paged_bytes Number of bytes in the paged pool, an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. This property displays the last observed value only; it is not an average.
# TYPE windows_terminal_services_pool_paged_bytes gauge
windows_terminal_services_pool_paged_bytes{session_name="RDP-Tcp 0"} 2.4651264e+07
# HELP windows_terminal_services_private_bytes Current number of bytes this process has allocated that cannot be shared with other processes.
# TYPE windows_terminal_services_private_bytes gauge
windows_terminal_services_private_bytes{session_name="RDP-Tcp 0"} 4.310188032e+09
# HELP windows_terminal_services_session_info Terminal Services sessions info
# TYPE windows_terminal_services_session_info gauge
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="active",user="domain\\user"} 1
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="connect_query",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="connected",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="disconnected",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="down",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="idle",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="init",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="listen",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="reset",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="RDP-Tcp 0",state="shadow",user="domain\\user"} 0
windows_terminal_services_session_info{host="",session_name="console",state="active",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="connect_query",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="connected",user=""} 1
windows_terminal_services_session_info{host="",session_name="console",state="disconnected",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="down",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="idle",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="init",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="listen",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="reset",user=""} 0
windows_terminal_services_session_info{host="",session_name="console",state="shadow",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="active",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="connect_query",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="connected",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="disconnected",user=""} 1
windows_terminal_services_session_info{host="",session_name="services",state="down",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="idle",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="init",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="listen",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="reset",user=""} 0
windows_terminal_services_session_info{host="",session_name="services",state="shadow",user=""} 0
# HELP windows_terminal_services_threads Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.
# TYPE windows_terminal_services_threads gauge
windows_terminal_services_threads{session_name="RDP-Tcp 0"} 676
# HELP windows_terminal_services_virtual_bytes Current size, in bytes, of the virtual address space the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.
# TYPE windows_terminal_services_virtual_bytes gauge
windows_terminal_services_virtual_bytes{session_name="RDP-Tcp 0"} 9.3228347629568e+13
# HELP windows_terminal_services_virtual_bytes_peak Maximum number of bytes of virtual address space the process has used at any one time. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process might limit its ability to load libraries.
# TYPE windows_terminal_services_virtual_bytes_peak gauge
windows_terminal_services_virtual_bytes_peak{session_name="RDP-Tcp 0"} 9.323192164352e+13
# HELP windows_terminal_services_working_set_bytes Current number of bytes in the working set of this process. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.
# TYPE windows_terminal_services_working_set_bytes gauge
windows_terminal_services_working_set_bytes{session_name="RDP-Tcp 0"} 6.0632064e+09
# HELP windows_terminal_services_working_set_bytes_peak Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.
# TYPE windows_terminal_services_working_set_bytes_peak gauge
windows_terminal_services_working_set_bytes_peak{session_name="RDP-Tcp 0"} 6.74854912e+09
```
## Useful queries ## Useful queries
_This collector does not yet have any useful queries added, we would appreciate your help adding them!_
Use metrics can be combined with other metrics to create useful queries. For example, with remote_fx metrics:
```
windows_remote_fx_net_loss_rate * on(session_name) group_left(user) (windows_terminal_services_session_info == 1)
```
## Alerting examples ## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_ _This collector does not yet have alerting examples, we would appreciate your help adding them!_

View File

@@ -5,11 +5,11 @@ If the Windows Time Service is stopped after collection has started, collector m
Please note the Time Service perflib counters are only available on [Windows Server 2016 or newer](https://docs.microsoft.com/en-us/windows-server/networking/windows-time-service/windows-server-2016-improvements). Please note the Time Service perflib counters are only available on [Windows Server 2016 or newer](https://docs.microsoft.com/en-us/windows-server/networking/windows-time-service/windows-server-2016-improvements).
||| | | |
-|- |---------------------|---------|
Metric name prefix | `time` | Metric name prefix | `time` |
Data source | Perflib | Data source | Perflib |
Enabled by default? | No | Enabled by default? | No |
## Flags ## Flags
@@ -17,14 +17,14 @@ None
## Metrics ## Metrics
Name | Description | Type | Labels | Name | Description | Type | Labels |
-----|-------------|------|------- |-----------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|
`windows_time_clock_frequency_Adjustment_ppb_total` | Total adjustment made to the local system clock frequency by W32Time in parts per billion (PPB) units. 1 PPB adjustment implies the system clock was adjusted at a rate of 1 nanosecond per second (1 ns/s). The smallest possible adjustment can vary and is expected to be in the order of 100's of PPB. | counter | None | `windows_time_clock_frequency_adjustment_ppb_total` | Total adjustment made to the local system clock frequency by W32Time in parts per billion (PPB) units. 1 PPB adjustment implies the system clock was adjusted at a rate of 1 nanosecond per second (1 ns/s). The smallest possible adjustment can vary and is expected to be in the order of 100's of PPB. | counter | None |
`windows_time_computed_time_offset_seconds` | Absolute time offset between the system clock and the chosen time source, in seconds. | counter | None | `windows_time_computed_time_offset_seconds` | The absolute time offset between the system clock and the chosen time source, as computed by the W32Time service in microseconds. When a new valid sample is available, the computed time is updated with the time offset indicated by the sample. This time is the actual time offset of the local clock. W32Time initiates clock correction by using this offset and updates the computed time in between samples with the remaining time offset that needs to be applied to the local clock. Clock accuracy can be tracked by using this performance counter with a low polling interval (for example, 256 seconds or less) and looking for the counter value to be smaller than the desired clock accuracy limit. | gauge | None |
`windows_time_ntp_client_time_sources` | Active number of NTP Time sources being used by the client. This is a count of active, distinct IP addresses of time servers that are responding to this client's requests. | gauge | None | `windows_time_ntp_client_time_sources` | Active number of NTP Time sources being used by the client. This is a count of active, distinct IP addresses of time servers that are responding to this client's requests. | gauge | None |
`windows_time_ntp_round_trip_delay_seconds` | Total roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds. This is the time elapsed on the NTP client between transmitting a request to the NTP server and receiving a valid response from the server. | gauge | None | `windows_time_ntp_round_trip_delay_seconds` | Total roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds. This is the time elapsed on the NTP client between transmitting a request to the NTP server and receiving a valid response from the server. | gauge | None |
`windows_time_ntp_server_outgoing_responses_total` | Total number of requests responded to by the NTP server. | counter | None | `windows_time_ntp_server_outgoing_responses_total` | Total number of requests responded to by the NTP server. | counter | None |
`windows_time_ntp_server_incoming_requests_total` | Total number of requests received by the NTP server. | counter | None | `windows_time_ntp_server_incoming_requests_total` | Total number of requests received by the NTP server. | counter | None |
### Example metric ### Example metric
_This collector does not yet have explained examples, we would appreciate your help adding them!_ _This collector does not yet have explained examples, we would appreciate your help adding them!_

View File

@@ -1,7 +1,7 @@
--- ---
# Note this is not an exhaustive list of all configuration values # Note this is not an exhaustive list of all configuration values
collectors: collectors:
enabled: cpu,cs,logical_disk,net,os,service,system,textfile enabled: cpu,cs,logical_disk,net,os,service,system
collector: collector:
service: service:
services-where: Name='windows_exporter' services-where: Name='windows_exporter'

View File

@@ -1,37 +1,45 @@
//go:build windows //go:build windows
//go:generate go run github.com/tc-hib/go-winres@v0.3.3 make --product-version=git-tag --file-version=git-tag --arch=amd64,arm64
package main package main
//goland:noinspection GoUnsortedImport
//nolint:gofumpt
import ( import (
// Its important that we do these first so that we can register with the Windows service control ASAP to avoid timeouts.
"github.com/prometheus-community/windows_exporter/pkg/initiate"
"context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"net/http" "net/http"
_ "net/http/pprof" "net/http/pprof"
"os" "os"
"os/signal"
"os/user" "os/user"
"runtime" "runtime"
"sort" "sort"
"strings" "strings"
"time"
// Its important that we do these first so that we can register with the windows service control ASAP to avoid timeouts
"github.com/prometheus-community/windows_exporter/pkg/initiate"
winlog "github.com/prometheus-community/windows_exporter/pkg/log"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/collector" "github.com/prometheus-community/windows_exporter/pkg/collector"
"github.com/prometheus-community/windows_exporter/pkg/config" "github.com/prometheus-community/windows_exporter/pkg/config"
winlog "github.com/prometheus-community/windows_exporter/pkg/log"
"github.com/prometheus-community/windows_exporter/pkg/log/flag" "github.com/prometheus-community/windows_exporter/pkg/log/flag"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/common/version" "github.com/prometheus/common/version"
"github.com/prometheus/exporter-toolkit/web" "github.com/prometheus/exporter-toolkit/web"
webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag" webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag"
"golang.org/x/sys/windows"
) )
// Same struct prometheus uses for their /version endpoint. // Same struct prometheus uses for their /version endpoint.
// Separate copy to avoid pulling all of prometheus as a dependency // Separate copy to avoid pulling all of prometheus as a dependency.
type prometheusVersion struct { type prometheusVersion struct {
Version string `json:"version"` Version string `json:"version"`
Revision string `json:"revision"` Revision string `json:"revision"`
@@ -41,6 +49,37 @@ type prometheusVersion struct {
GoVersion string `json:"goVersion"` GoVersion string `json:"goVersion"`
} }
// Mapping of priority names to uin32 values required by windows.SetPriorityClass.
var priorityStringToInt = map[string]uint32{
"realtime": windows.REALTIME_PRIORITY_CLASS,
"high": windows.HIGH_PRIORITY_CLASS,
"abovenormal": windows.ABOVE_NORMAL_PRIORITY_CLASS,
"normal": windows.NORMAL_PRIORITY_CLASS,
"belownormal": windows.BELOW_NORMAL_PRIORITY_CLASS,
"low": windows.IDLE_PRIORITY_CLASS,
}
func setPriorityWindows(pid int, priority uint32) error {
// https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
handle, err := windows.OpenProcess(
windows.STANDARD_RIGHTS_REQUIRED|windows.SYNCHRONIZE|windows.SPECIFIC_RIGHTS_ALL,
false, uint32(pid),
)
if err != nil {
return err
}
if err = windows.SetPriorityClass(handle, priority); err != nil {
return err
}
if err = windows.CloseHandle(handle); err != nil {
return fmt.Errorf("failed to close handle: %w", err)
}
return nil
}
func main() { func main() {
app := kingpin.New("windows_exporter", "A metrics collector for Windows.") app := kingpin.New("windows_exporter", "A metrics collector for Windows.")
var ( var (
@@ -48,7 +87,7 @@ func main() {
"config.file", "config.file",
"YAML configuration file to use. Values set in this file will be overridden by CLI flags.", "YAML configuration file to use. Values set in this file will be overridden by CLI flags.",
).String() ).String()
insecure_skip_verify = app.Flag( insecureSkipVerify = app.Flag(
"config.file.insecure-skip-verify", "config.file.insecure-skip-verify",
"Skip TLS verification in loading YAML configuration.", "Skip TLS verification in loading YAML configuration.",
).Default("false").Bool() ).Default("false").Bool()
@@ -77,6 +116,14 @@ func main() {
"scrape.timeout-margin", "scrape.timeout-margin",
"Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.", "Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.",
).Default("0.5").Float64() ).Default("0.5").Float64()
debugEnabled = app.Flag(
"debug.enabled",
"If true, windows_exporter will expose debug endpoints under /debug/pprof.",
).Default("false").Bool()
processPriority = app.Flag(
"process.priority",
"Priority of the exporter process. Higher priorities may improve exporter responsiveness during periods of system load. Can be one of [\"realtime\", \"high\", \"abovenormal\", \"normal\", \"belownormal\", \"low\"]",
).Default("normal").String()
) )
winlogConfig := &winlog.Config{} winlogConfig := &winlog.Config{}
@@ -100,7 +147,7 @@ func main() {
_ = level.Debug(logger).Log("msg", "Logging has Started") _ = level.Debug(logger).Log("msg", "Logging has Started")
if *configFile != "" { if *configFile != "" {
resolver, err := config.NewResolver(*configFile, logger, *insecure_skip_verify) resolver, err := config.NewResolver(*configFile, logger, *insecureSkipVerify)
if err != nil { if err != nil {
_ = level.Error(logger).Log("msg", "could not load config file", "err", err) _ = level.Error(logger).Log("msg", "could not load config file", "err", err)
os.Exit(1) os.Exit(1)
@@ -130,30 +177,34 @@ func main() {
collectorNames := collector.Available() collectorNames := collector.Available()
sort.Strings(collectorNames) sort.Strings(collectorNames)
fmt.Printf("Available collectors:\n") fmt.Printf("Available collectors:\n") //nolint:forbidigo
for _, n := range collectorNames { for _, n := range collectorNames {
fmt.Printf(" - %s\n", n) fmt.Printf(" - %s\n", n) //nolint:forbidigo
} }
return return
} }
if err = wmi.InitWbem(logger); err != nil { // Only set process priority if a non-default and valid value has been set
_ = level.Error(logger).Log("err", err) if *processPriority != "normal" && priorityStringToInt[*processPriority] != 0 {
os.Exit(1) _ = level.Debug(logger).Log("msg", "setting process priority to "+*processPriority)
err = setPriorityWindows(os.Getpid(), priorityStringToInt[*processPriority])
if err != nil {
_ = level.Error(logger).Log("msg", "failed to set process priority", "err", err)
os.Exit(1)
}
} }
enabledCollectorList := utils.ExpandEnabledCollectors(*enabledCollectors) enabledCollectorList := utils.ExpandEnabledCollectors(*enabledCollectors)
collectors.Enable(enabledCollectorList) collectors.Enable(enabledCollectorList)
collectors.SetLogger(logger)
// Initialize collectors before loading // Initialize collectors before loading
err = collectors.Build() err = collectors.Build(logger)
if err != nil { if err != nil {
_ = level.Error(logger).Log("msg", "Couldn't load collectors", "err", err) _ = level.Error(logger).Log("msg", "Couldn't load collectors", "err", err)
os.Exit(1) os.Exit(1)
} }
err = collectors.SetPerfCounterQuery() err = collectors.SetPerfCounterQuery(logger)
if err != nil { if err != nil {
_ = level.Error(logger).Log("msg", "Couldn't set performance counter query", "err", err) _ = level.Error(logger).Log("msg", "Couldn't set performance counter query", "err", err)
os.Exit(1) os.Exit(1)
@@ -171,15 +222,16 @@ func main() {
_ = level.Info(logger).Log("msg", fmt.Sprintf("Enabled collectors: %v", strings.Join(enabledCollectorList, ", "))) _ = level.Info(logger).Log("msg", fmt.Sprintf("Enabled collectors: %v", strings.Join(enabledCollectorList, ", ")))
http.HandleFunc(*metricsPath, withConcurrencyLimit(*maxRequests, collectors.BuildServeHTTP(*disableExporterMetrics, *timeoutMargin))) mux := http.NewServeMux()
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(*metricsPath, withConcurrencyLimit(*maxRequests, collectors.BuildServeHTTP(logger, *disableExporterMetrics, *timeoutMargin)))
mux.HandleFunc("/health", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
_, err := fmt.Fprintln(w, `{"status":"ok"}`) _, err := fmt.Fprintln(w, `{"status":"ok"}`)
if err != nil { if err != nil {
_ = level.Debug(logger).Log("Failed to write to stream", "err", err) _ = level.Debug(logger).Log("msg", "Failed to write to stream", "err", err)
} }
}) })
http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/version", func(w http.ResponseWriter, _ *http.Request) {
// we can't use "version" directly as it is a package, and not an object that // we can't use "version" directly as it is a package, and not an object that
// can be serialized. // can be serialized.
err := json.NewEncoder(w).Encode(prometheusVersion{ err := json.NewEncoder(w).Encode(prometheusVersion{
@@ -194,52 +246,50 @@ func main() {
http.Error(w, fmt.Sprintf("error encoding JSON: %s", err), http.StatusInternalServerError) http.Error(w, fmt.Sprintf("error encoding JSON: %s", err), http.StatusInternalServerError)
} }
}) })
if *metricsPath != "/" && *metricsPath != "" {
landingConfig := web.LandingConfig{ if *debugEnabled {
Name: "Windows Exporter", mux.HandleFunc("/debug/pprof/", pprof.Index)
Description: "Prometheus Exporter for Windows servers", mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
Version: version.Info(), mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
Links: []web.LandingLinks{ mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
{ mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
Address: *metricsPath,
Text: "Metrics",
},
{
Address: "/health",
Text: "Health Check",
},
{
Address: "/version",
Text: "Version Info",
},
},
}
landingPage, err := web.NewLandingPage(landingConfig)
if err != nil {
_ = level.Error(logger).Log("msg", "failed to generate landing page", "err", err)
os.Exit(1)
}
http.Handle("/", landingPage)
} }
_ = level.Info(logger).Log("msg", "Starting windows_exporter", "version", version.Info()) _ = level.Info(logger).Log("msg", "Starting windows_exporter", "version", version.Info())
_ = level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext()) _ = level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext())
_ = level.Debug(logger).Log("msg", "Go MAXPROCS", "procs", runtime.GOMAXPROCS(0)) _ = level.Debug(logger).Log("msg", "Go MAXPROCS", "procs", runtime.GOMAXPROCS(0))
server := &http.Server{
ReadHeaderTimeout: 5 * time.Second,
IdleTimeout: 60 * time.Second,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Minute,
Handler: mux,
}
go func() { go func() {
server := &http.Server{} if err := web.ListenAndServe(server, webConfig, logger); err != nil && !errors.Is(err, http.ErrServerClosed) {
if err := web.ListenAndServe(server, webConfig, logger); err != nil {
_ = level.Error(logger).Log("msg", "cannot start windows_exporter", "err", err) _ = level.Error(logger).Log("msg", "cannot start windows_exporter", "err", err)
os.Exit(1) os.Exit(1)
} }
}() }()
for { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
if <-initiate.StopCh { defer stop()
_ = level.Info(logger).Log("msg", "Shutting down windows_exporter")
break select {
} case <-ctx.Done():
_ = level.Info(logger).Log("msg", "Shutting down windows_exporter via kill signal")
case <-initiate.StopCh:
_ = level.Info(logger).Log("msg", "Shutting down windows_exporter via service control")
} }
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = server.Shutdown(ctx)
_ = level.Info(logger).Log("msg", "windows_exporter has shut down")
} }
func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc { func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc {

55
go.mod
View File

@@ -1,55 +1,56 @@
module github.com/prometheus-community/windows_exporter module github.com/prometheus-community/windows_exporter
go 1.21 go 1.22
require ( require (
github.com/Microsoft/hcsshim v0.11.4 github.com/Microsoft/hcsshim v0.12.6
github.com/alecthomas/kingpin/v2 v2.4.0 github.com/alecthomas/kingpin/v2 v2.4.0
github.com/dimchansky/utfbom v1.1.1 github.com/dimchansky/utfbom v1.1.1
github.com/go-kit/log v0.2.1 github.com/go-kit/log v0.2.1
github.com/go-ole/go-ole v1.3.0 github.com/go-ole/go-ole v1.3.0
github.com/prometheus/client_golang v1.18.0 github.com/prometheus/client_golang v1.20.2
github.com/prometheus/client_model v0.5.0 github.com/prometheus/client_model v0.6.1
github.com/prometheus/common v0.46.0 github.com/prometheus/common v0.55.0
github.com/prometheus/exporter-toolkit v0.11.0 github.com/prometheus/exporter-toolkit v0.11.0
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.9.0
github.com/yusufpapurcu/wmi v1.2.3 github.com/yusufpapurcu/wmi v1.2.4
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/sys v0.16.0 golang.org/x/sys v0.24.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
github.com/Microsoft/go-winio v0.6.1 // indirect github.com/google/uuid v1.6.0
github.com/pkg/errors v0.9.1
)
require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect
github.com/containerd/containerd v1.7.0 // indirect github.com/containerd/errdefs v0.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/jpillora/backoff v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
golang.org/x/crypto v0.18.0 // indirect golang.org/x/crypto v0.25.0 // indirect
golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.27.0 // indirect
golang.org/x/net v0.20.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect golang.org/x/sync v0.7.0 // indirect
golang.org/x/sync v0.5.0 // indirect golang.org/x/text v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
golang.org/x/tools v0.15.0 // indirect google.golang.org/grpc v1.65.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.34.2 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.3 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )

127
go.sum
View File

@@ -1,9 +1,9 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.12.6 h1:qEnZjoHXv+4/s0LmKZWE0/AiZmMWEIkFfWBSf1a0wlU=
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/Microsoft/hcsshim v0.12.6/go.mod h1:ZABCLVcvLMjIkzr9rUGcQ1QA0p0P3Ps+d3N1g2DsFfk=
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
@@ -11,14 +11,14 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8V
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
github.com/containerd/containerd v1.7.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg= github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc= github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -38,15 +38,12 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -55,44 +52,46 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g=
github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
@@ -105,53 +104,40 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -159,43 +145,32 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -205,10 +180,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@@ -10,6 +10,9 @@ Param (
) )
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
# The MSI version is not semver compliant, so just take the numerical parts
$MsiVersion = $Version -replace '^v?([0-9\.]+).*$','$1'
# Get absolute path to executable before switching directories # Get absolute path to executable before switching directories
$PathToExecutable = Resolve-Path $PathToExecutable $PathToExecutable = Resolve-Path $PathToExecutable
# Set working dir to this directory, reset previous on exit # Set working dir to this directory, reset previous on exit
@@ -24,8 +27,8 @@ Copy-Item -Force $PathToExecutable Work/windows_exporter.exe
Write-Verbose "Creating windows_exporter-${Version}-${Arch}.msi" Write-Verbose "Creating windows_exporter-${Version}-${Arch}.msi"
$wixArch = @{"amd64" = "x64"; "arm64" = "arm64"}[$Arch] $wixArch = @{"amd64" = "x64"; "arm64" = "arm64"}[$Arch]
$wixOpts = "-ext WixFirewallExtension -ext WixUtilExtension"
Invoke-Expression "wix build -arch $wixArch -o .\windows_exporter-$($Version)-$($Arch).msi .\windows_exporter.wxs -d Version=$($Version) -ext WixToolset.Firewall.wixext -ext WixToolset.Util.wixext" Invoke-Expression "wix build -arch $wixArch -o .\windows_exporter-$($Version)-$($Arch).msi .\windows_exporter.wxs -d Version=$($MsiVersion) -ext WixToolset.Firewall.wixext -ext WixToolset.Util.wixext"
Write-Verbose "Done!" Write-Verbose "Done!"
Pop-Location Pop-Location

View File

@@ -5,7 +5,9 @@
<?define PlatformProgramFiles = "ProgramFilesFolder" ?> <?define PlatformProgramFiles = "ProgramFilesFolder" ?>
<?endif?> <?endif?>
<Package UpgradeCode="66a6eb5b-1fc2-4b14-a362-5ceec6413308" Name="windows_exporter" Version="$(var.Version)" Manufacturer="prometheus-community" Language="1033" Codepage="1252"><SummaryInformation Manufacturer="prometheus-community" Description="windows_exporter $(var.Version) installer" /> <Package UpgradeCode="66a6eb5b-1fc2-4b14-a362-5ceec6413308" Name="windows_exporter" Version="$(var.Version)" Manufacturer="prometheus-community" Language="1033" Codepage="1252">
<SummaryInformation Manufacturer="prometheus-community" Description="windows_exporter $(var.Version) installer" />
<Media Id="1" Cabinet="windows_exporter.cab" EmbedCab="yes" /> <Media Id="1" Cabinet="windows_exporter.cab" EmbedCab="yes" />
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." /> <MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
@@ -15,8 +17,12 @@
<Property Id="EXTRA_FLAGS" Secure="yes" /> <Property Id="EXTRA_FLAGS" Secure="yes" />
<SetProperty Id="ExtraFlags" After="InstallFiles" Sequence="execute" Value="[EXTRA_FLAGS]" Condition="EXTRA_FLAGS" /> <SetProperty Id="ExtraFlags" After="InstallFiles" Sequence="execute" Value="[EXTRA_FLAGS]" Condition="EXTRA_FLAGS" />
<Property Id="LISTEN_ADDR" Secure="yes" Value="0.0.0.0" /> <Property Id="ADD_FIREWALL_EXCEPTION" Secure="yes" />
<Property Id="ENABLE_V1_PERFORMANCE_COUNTERS" Secure="yes" />
<Property Id="LISTEN_PORT" Secure="yes" Value="9182" /> <Property Id="LISTEN_PORT" Secure="yes" Value="9182" />
<SetProperty Id="ListenFlag" After="InstallFiles" Sequence="execute" Value="--web.listen-address [LISTEN_ADDR]:[LISTEN_PORT]" Condition="LISTEN_ADDR&lt;&gt;&quot;&quot; OR LISTEN_PORT&lt;&gt;9182" />
<Property Id="METRICS_PATH" Secure="yes" /> <Property Id="METRICS_PATH" Secure="yes" />
<SetProperty Id="MetricsPathFlag" After="InstallFiles" Sequence="execute" Value="--telemetry.path [METRICS_PATH]" Condition="METRICS_PATH" /> <SetProperty Id="MetricsPathFlag" After="InstallFiles" Sequence="execute" Value="--telemetry.path [METRICS_PATH]" Condition="METRICS_PATH" />
@@ -44,17 +50,32 @@
<Custom Action="RemoveEventSource" After="InstallInitialize" /> <Custom Action="RemoveEventSource" After="InstallInitialize" />
</InstallExecuteSequence> </InstallExecuteSequence>
<SetProperty
Id="EnableV1PerformanceCounters"
Value="&quot;[%ComSpec]&quot; /c lodctr.exe /E:Lsa &amp; lodctr.exe /E:PerfProc &amp; lodctr.exe /R"
Before="EnableV1PerformanceCounters"
Sequence="execute"
/>
<CustomAction
Id="EnableV1PerformanceCounters"
BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)"
DllEntry="WixSilentExec"
Execute="deferred"
Impersonate="no"
Return="check"
/>
<InstallExecuteSequence>
<Custom Action="EnableV1PerformanceCounters" Before="InstallFinalize" Condition="ENABLE_V1_PERFORMANCE_COUNTERS=&quot;yes&quot;"/>
</InstallExecuteSequence>
<Property Id="TEXTFILE_DIRS" Secure="yes" /> <Property Id="TEXTFILE_DIRS" Secure="yes" />
<SetProperty Id="TextfileDirsFlag" After="InstallFiles" Sequence="execute" Value="--collector.textfile.directories [TEXTFILE_DIRS]" Condition="TEXTFILE_DIRS" /> <SetProperty Id="TextfileDirsFlag" After="InstallFiles" Sequence="execute" Value="--collector.textfile.directories [TEXTFILE_DIRS]" Condition="TEXTFILE_DIRS" />
<ComponentGroup Id="Files"> <ComponentGroup Id="Files">
<Component Directory="APPLICATIONROOTDIRECTORY"> <Component Directory="APPLICATIONROOTDIRECTORY">
<File Id="windows_exporter.exe" Name="windows_exporter.exe" Source="Work\windows_exporter.exe" KeyPath="yes"> <File Id="windows_exporter.exe" Name="windows_exporter.exe" Source="Work\windows_exporter.exe" KeyPath="yes" />
<fw:FirewallException Id="MetricsEndpoint" Name="windows_exporter (HTTP [LISTEN_PORT])" Description="windows_exporter HTTP endpoint" Port="[LISTEN_PORT]" Protocol="tcp" IgnoreFailure="yes"> <ServiceInstall Id="InstallExporterService" Name="windows_exporter" DisplayName="windows_exporter" Description="Exports Prometheus metrics about the system" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="--log.file eventlog [CollectorsFlag] [ListenFlag] [MetricsPathFlag] [TextfileDirsFlag] [ExtraFlags]">
<fw:RemoteAddress Value="[REMOTE_ADDR]" />
</fw:FirewallException>
</File>
<ServiceInstall Id="InstallExporterService" Name="windows_exporter" DisplayName="windows_exporter" Description="Exports Prometheus metrics about the system" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="--log.file eventlog [CollectorsFlag] --web.listen-address [LISTEN_ADDR]:[LISTEN_PORT] [MetricsPathFlag] [TextfileDirsFlag] [ExtraFlags]">
<util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" RestartServiceDelayInSeconds="60" /> <util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" RestartServiceDelayInSeconds="60" />
<ServiceDependency Id="wmiApSrv" /> <ServiceDependency Id="wmiApSrv" />
</ServiceInstall> </ServiceInstall>
@@ -64,15 +85,26 @@
<CreateFolder /> <CreateFolder />
</Component> </Component>
</ComponentGroup> </ComponentGroup>
<ComponentGroup Id="CG_FirewallException">
<Component Condition="ADD_FIREWALL_EXCEPTION=&quot;yes&quot;" Directory="APPLICATIONROOTDIRECTORY" Id="C_FirewallException" Guid="9f522655-ac0e-42d2-a512-a7b19ebec7f7">
<fw:FirewallException Id="MetricsEndpoint" Name="windows_exporter (HTTP [LISTEN_PORT])" Description="windows_exporter HTTP endpoint" Port="[LISTEN_PORT]" Protocol="tcp" IgnoreFailure="yes">
<fw:RemoteAddress Value="[REMOTE_ADDR]" />
</fw:FirewallException>
</Component>
</ComponentGroup>
<Feature Id="DefaultFeature" Level="1"> <Feature Id="DefaultFeature" Level="1">
<ComponentGroupRef Id="Files" /> <ComponentGroupRef Id="Files" />
</Feature> </Feature>
<Directory Id="$(var.PlatformProgramFiles)"> <Feature Id="FirewallException" Level="1">
<ComponentGroupRef Id="CG_FirewallException" />
</Feature>
<StandardDirectory Id="ProgramFiles64Folder">
<Directory Id="APPLICATIONROOTDIRECTORY" Name="windows_exporter"> <Directory Id="APPLICATIONROOTDIRECTORY" Name="windows_exporter">
<Directory Id="textfile_inputs" Name="textfile_inputs" /> <Directory Id="textfile_inputs" Name="textfile_inputs" />
</Directory> </Directory>
</Directory> </StandardDirectory>
</Package> </Package>
</Wix> </Wix>

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "adcs" const Name = "adcs"
@@ -21,120 +22,126 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type collector struct { type Collector struct {
logger log.Logger config Config
RequestsPerSecond *prometheus.Desc challengeResponseProcessingTime *prometheus.Desc
RequestProcessingTime *prometheus.Desc challengeResponsesPerSecond *prometheus.Desc
RetrievalsPerSecond *prometheus.Desc failedRequestsPerSecond *prometheus.Desc
RetrievalProcessingTime *prometheus.Desc issuedRequestsPerSecond *prometheus.Desc
FailedRequestsPerSecond *prometheus.Desc pendingRequestsPerSecond *prometheus.Desc
IssuedRequestsPerSecond *prometheus.Desc requestCryptographicSigningTime *prometheus.Desc
PendingRequestsPerSecond *prometheus.Desc requestPolicyModuleProcessingTime *prometheus.Desc
RequestCryptographicSigningTime *prometheus.Desc requestProcessingTime *prometheus.Desc
RequestPolicyModuleProcessingTime *prometheus.Desc requestsPerSecond *prometheus.Desc
ChallengeResponsesPerSecond *prometheus.Desc retrievalProcessingTime *prometheus.Desc
ChallengeResponseProcessingTime *prometheus.Desc retrievalsPerSecond *prometheus.Desc
SignedCertificateTimestampListsPerSecond *prometheus.Desc signedCertificateTimestampListProcessingTime *prometheus.Desc
SignedCertificateTimestampListProcessingTime *prometheus.Desc signedCertificateTimestampListsPerSecond *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Certification Authority"}, nil return []string{"Certification Authority"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.RequestsPerSecond = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.requestsPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "requests_total"), prometheus.BuildFQName(types.Namespace, Name, "requests_total"),
"Total certificate requests processed", "Total certificate requests processed",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.RequestProcessingTime = prometheus.NewDesc( c.requestProcessingTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "request_processing_time_seconds"), prometheus.BuildFQName(types.Namespace, Name, "request_processing_time_seconds"),
"Last time elapsed for certificate requests", "Last time elapsed for certificate requests",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.RetrievalsPerSecond = prometheus.NewDesc( c.retrievalsPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "retrievals_total"), prometheus.BuildFQName(types.Namespace, Name, "retrievals_total"),
"Total certificate retrieval requests processed", "Total certificate retrieval requests processed",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.RetrievalProcessingTime = prometheus.NewDesc( c.retrievalProcessingTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "retrievals_processing_time_seconds"), prometheus.BuildFQName(types.Namespace, Name, "retrievals_processing_time_seconds"),
"Last time elapsed for certificate retrieval request", "Last time elapsed for certificate retrieval request",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.FailedRequestsPerSecond = prometheus.NewDesc( c.failedRequestsPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failed_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "failed_requests_total"),
"Total failed certificate requests processed", "Total failed certificate requests processed",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.IssuedRequestsPerSecond = prometheus.NewDesc( c.issuedRequestsPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "issued_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "issued_requests_total"),
"Total issued certificate requests processed", "Total issued certificate requests processed",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.PendingRequestsPerSecond = prometheus.NewDesc( c.pendingRequestsPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pending_requests_total"), prometheus.BuildFQName(types.Namespace, Name, "pending_requests_total"),
"Total pending certificate requests processed", "Total pending certificate requests processed",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.RequestCryptographicSigningTime = prometheus.NewDesc( c.requestCryptographicSigningTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "request_cryptographic_signing_time_seconds"), prometheus.BuildFQName(types.Namespace, Name, "request_cryptographic_signing_time_seconds"),
"Last time elapsed for signing operation request", "Last time elapsed for signing operation request",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.RequestPolicyModuleProcessingTime = prometheus.NewDesc( c.requestPolicyModuleProcessingTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "request_policy_module_processing_time_seconds"), prometheus.BuildFQName(types.Namespace, Name, "request_policy_module_processing_time_seconds"),
"Last time elapsed for policy module processing request", "Last time elapsed for policy module processing request",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.ChallengeResponsesPerSecond = prometheus.NewDesc( c.challengeResponsesPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "challenge_responses_total"), prometheus.BuildFQName(types.Namespace, Name, "challenge_responses_total"),
"Total certificate challenge responses processed", "Total certificate challenge responses processed",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.ChallengeResponseProcessingTime = prometheus.NewDesc( c.challengeResponseProcessingTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "challenge_response_processing_time_seconds"), prometheus.BuildFQName(types.Namespace, Name, "challenge_response_processing_time_seconds"),
"Last time elapsed for challenge response", "Last time elapsed for challenge response",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.SignedCertificateTimestampListsPerSecond = prometheus.NewDesc( c.signedCertificateTimestampListsPerSecond = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "signed_certificate_timestamp_lists_total"), prometheus.BuildFQName(types.Namespace, Name, "signed_certificate_timestamp_lists_total"),
"Total Signed Certificate Timestamp Lists processed", "Total Signed Certificate Timestamp Lists processed",
[]string{"cert_template"}, []string{"cert_template"},
nil, nil,
) )
c.SignedCertificateTimestampListProcessingTime = prometheus.NewDesc( c.signedCertificateTimestampListProcessingTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "signed_certificate_timestamp_list_processing_time_seconds"), prometheus.BuildFQName(types.Namespace, Name, "signed_certificate_timestamp_list_processing_time_seconds"),
"Last time elapsed for Signed Certificate Timestamp List", "Last time elapsed for Signed Certificate Timestamp List",
[]string{"cert_template"}, []string{"cert_template"},
@@ -144,9 +151,10 @@ func (c *collector) Build() error {
return nil return nil
} }
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collectADCSCounters(ctx, ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting ADCS metrics", "desc", desc, "err", err) if err := c.collectADCSCounters(ctx, logger, ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting ADCS metrics", "err", err)
return err return err
} }
return nil return nil
@@ -169,17 +177,17 @@ type perflibADCS struct {
SignedCertificateTimestampListProcessingTime float64 `perflib:"Signed Certificate Timestamp List processing time (ms)"` SignedCertificateTimestampListProcessingTime float64 `perflib:"Signed Certificate Timestamp List processing time (ms)"`
} }
func (c *collector) collectADCSCounters(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collectADCSCounters(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
dst := make([]perflibADCS, 0) dst := make([]perflibADCS, 0)
if _, ok := ctx.PerfObjects["Certification Authority"]; !ok { if _, ok := ctx.PerfObjects["Certification Authority"]; !ok {
return nil, errors.New("perflib did not contain an entry for Certification Authority") return errors.New("perflib did not contain an entry for Certification Authority")
} }
err := perflib.UnmarshalObject(ctx.PerfObjects["Certification Authority"], &dst, c.logger) err := perflib.UnmarshalObject(ctx.PerfObjects["Certification Authority"], &dst, logger)
if err != nil { if err != nil {
return nil, err return err
} }
if len(dst) == 0 { if len(dst) == 0 {
return nil, errors.New("perflib query for Certification Authority (ADCS) returned empty result set") return errors.New("perflib query for Certification Authority (ADCS) returned empty result set")
} }
for _, d := range dst { for _, d := range dst {
@@ -188,84 +196,84 @@ func (c *collector) collectADCSCounters(ctx *types.ScrapeContext, ch chan<- prom
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RequestsPerSecond, c.requestsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
d.RequestsPerSecond, d.RequestsPerSecond,
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RequestProcessingTime, c.requestProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(d.RequestProcessingTime), utils.MilliSecToSec(d.RequestProcessingTime),
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RetrievalsPerSecond, c.retrievalsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
d.RetrievalsPerSecond, d.RetrievalsPerSecond,
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RetrievalProcessingTime, c.retrievalProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(d.RetrievalProcessingTime), utils.MilliSecToSec(d.RetrievalProcessingTime),
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailedRequestsPerSecond, c.failedRequestsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
d.FailedRequestsPerSecond, d.FailedRequestsPerSecond,
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.IssuedRequestsPerSecond, c.issuedRequestsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
d.IssuedRequestsPerSecond, d.IssuedRequestsPerSecond,
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PendingRequestsPerSecond, c.pendingRequestsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
d.PendingRequestsPerSecond, d.PendingRequestsPerSecond,
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RequestCryptographicSigningTime, c.requestCryptographicSigningTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(d.RequestCryptographicSigningTime), utils.MilliSecToSec(d.RequestCryptographicSigningTime),
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RequestPolicyModuleProcessingTime, c.requestPolicyModuleProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(d.RequestPolicyModuleProcessingTime), utils.MilliSecToSec(d.RequestPolicyModuleProcessingTime),
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ChallengeResponsesPerSecond, c.challengeResponsesPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
d.ChallengeResponsesPerSecond, d.ChallengeResponsesPerSecond,
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ChallengeResponseProcessingTime, c.challengeResponseProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(d.ChallengeResponseProcessingTime), utils.MilliSecToSec(d.ChallengeResponseProcessingTime),
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SignedCertificateTimestampListsPerSecond, c.signedCertificateTimestampListsPerSecond,
prometheus.CounterValue, prometheus.CounterValue,
d.SignedCertificateTimestampListsPerSecond, d.SignedCertificateTimestampListsPerSecond,
d.Name, d.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SignedCertificateTimestampListProcessingTime, c.signedCertificateTimestampListProcessingTime,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.MilliSecToSec(d.SignedCertificateTimestampListProcessingTime), utils.MilliSecToSec(d.SignedCertificateTimestampListProcessingTime),
d.Name, d.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -10,6 +10,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "adfs" const Name = "adfs"
@@ -18,20 +19,21 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type collector struct { type Collector struct {
logger log.Logger config Config
adLoginConnectionFailures *prometheus.Desc adLoginConnectionFailures *prometheus.Desc
artifactDBFailures *prometheus.Desc
avgArtifactDBQueryTime *prometheus.Desc
avgConfigDBQueryTime *prometheus.Desc
certificateAuthentications *prometheus.Desc certificateAuthentications *prometheus.Desc
configDBFailures *prometheus.Desc
deviceAuthentications *prometheus.Desc deviceAuthentications *prometheus.Desc
externalAuthenticationFailures *prometheus.Desc
externalAuthentications *prometheus.Desc
extranetAccountLockouts *prometheus.Desc extranetAccountLockouts *prometheus.Desc
federatedAuthentications *prometheus.Desc federatedAuthentications *prometheus.Desc
passportAuthentications *prometheus.Desc federationMetadataRequests *prometheus.Desc
passiveRequests *prometheus.Desc
passwordChangeFailed *prometheus.Desc
passwordChangeSucceeded *prometheus.Desc
tokenRequests *prometheus.Desc
windowsIntegratedAuthentications *prometheus.Desc
oAuthAuthZRequests *prometheus.Desc oAuthAuthZRequests *prometheus.Desc
oAuthClientAuthentications *prometheus.Desc oAuthClientAuthentications *prometheus.Desc
oAuthClientAuthenticationsFailures *prometheus.Desc oAuthClientAuthenticationsFailures *prometheus.Desc
@@ -50,45 +52,50 @@ type collector struct {
oAuthPasswordGrantRequestFailures *prometheus.Desc oAuthPasswordGrantRequestFailures *prometheus.Desc
oAuthPasswordGrantRequests *prometheus.Desc oAuthPasswordGrantRequests *prometheus.Desc
oAuthTokenRequests *prometheus.Desc oAuthTokenRequests *prometheus.Desc
passiveRequests *prometheus.Desc
passportAuthentications *prometheus.Desc
passwordChangeFailed *prometheus.Desc
passwordChangeSucceeded *prometheus.Desc
samlPTokenRequests *prometheus.Desc samlPTokenRequests *prometheus.Desc
ssoAuthenticationFailures *prometheus.Desc ssoAuthenticationFailures *prometheus.Desc
ssoAuthentications *prometheus.Desc ssoAuthentications *prometheus.Desc
wsfedTokenRequests *prometheus.Desc tokenRequests *prometheus.Desc
wstrustTokenRequests *prometheus.Desc
upAuthenticationFailures *prometheus.Desc upAuthenticationFailures *prometheus.Desc
upAuthentications *prometheus.Desc upAuthentications *prometheus.Desc
externalAuthenticationFailures *prometheus.Desc windowsIntegratedAuthentications *prometheus.Desc
externalAuthentications *prometheus.Desc wsfedTokenRequests *prometheus.Desc
artifactDBFailures *prometheus.Desc wstrustTokenRequests *prometheus.Desc
avgArtifactDBQueryTime *prometheus.Desc
configDBFailures *prometheus.Desc
avgConfigDBQueryTime *prometheus.Desc
federationMetadataRequests *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"AD FS"}, nil return []string{"AD FS"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.adLoginConnectionFailures = prometheus.NewDesc( c.adLoginConnectionFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "ad_login_connection_failures_total"), prometheus.BuildFQName(types.Namespace, Name, "ad_login_connection_failures_total"),
"Total number of connection failures to an Active Directory domain controller", "Total number of connection failures to an Active Directory domain controller",
@@ -397,9 +404,10 @@ type perflibADFS struct {
FederationMetadataRequests float64 `perflib:"Federation Metadata Requests"` FederationMetadataRequests float64 `perflib:"Federation Metadata Requests"`
} }
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var adfsData []perflibADFS var adfsData []perflibADFS
err := perflib.UnmarshalObject(ctx.PerfObjects["AD FS"], &adfsData, c.logger) err := perflib.UnmarshalObject(ctx.PerfObjects["AD FS"], &adfsData, logger)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -6,9 +6,11 @@ import (
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/pkg/errors"
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "cache" const Name = "cache"
@@ -17,233 +19,239 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for Perflib Cache metrics // A Collector is a Prometheus Collector for Perflib Cache metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
AsyncCopyReadsTotal *prometheus.Desc asyncCopyReadsTotal *prometheus.Desc
AsyncDataMapsTotal *prometheus.Desc asyncDataMapsTotal *prometheus.Desc
AsyncFastReadsTotal *prometheus.Desc asyncFastReadsTotal *prometheus.Desc
AsyncMDLReadsTotal *prometheus.Desc asyncMDLReadsTotal *prometheus.Desc
AsyncPinReadsTotal *prometheus.Desc asyncPinReadsTotal *prometheus.Desc
CopyReadHitsTotal *prometheus.Desc copyReadHitsTotal *prometheus.Desc
CopyReadsTotal *prometheus.Desc copyReadsTotal *prometheus.Desc
DataFlushesTotal *prometheus.Desc dataFlushesTotal *prometheus.Desc
DataFlushPagesTotal *prometheus.Desc dataFlushPagesTotal *prometheus.Desc
DataMapHitsPercent *prometheus.Desc dataMapHitsPercent *prometheus.Desc
DataMapPinsTotal *prometheus.Desc dataMapPinsTotal *prometheus.Desc
DataMapsTotal *prometheus.Desc dataMapsTotal *prometheus.Desc
DirtyPages *prometheus.Desc dirtyPages *prometheus.Desc
DirtyPageThreshold *prometheus.Desc dirtyPageThreshold *prometheus.Desc
FastReadNotPossiblesTotal *prometheus.Desc fastReadNotPossiblesTotal *prometheus.Desc
FastReadResourceMissesTotal *prometheus.Desc fastReadResourceMissesTotal *prometheus.Desc
FastReadsTotal *prometheus.Desc fastReadsTotal *prometheus.Desc
LazyWriteFlushesTotal *prometheus.Desc lazyWriteFlushesTotal *prometheus.Desc
LazyWritePagesTotal *prometheus.Desc lazyWritePagesTotal *prometheus.Desc
MDLReadHitsTotal *prometheus.Desc mdlReadHitsTotal *prometheus.Desc
MDLReadsTotal *prometheus.Desc mdlReadsTotal *prometheus.Desc
PinReadHitsTotal *prometheus.Desc pinReadHitsTotal *prometheus.Desc
PinReadsTotal *prometheus.Desc pinReadsTotal *prometheus.Desc
ReadAheadsTotal *prometheus.Desc readAheadsTotal *prometheus.Desc
SyncCopyReadsTotal *prometheus.Desc syncCopyReadsTotal *prometheus.Desc
SyncDataMapsTotal *prometheus.Desc syncDataMapsTotal *prometheus.Desc
SyncFastReadsTotal *prometheus.Desc syncFastReadsTotal *prometheus.Desc
SyncMDLReadsTotal *prometheus.Desc syncMDLReadsTotal *prometheus.Desc
SyncPinReadsTotal *prometheus.Desc syncPinReadsTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Cache"}, nil return []string{"Cache"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.AsyncCopyReadsTotal = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.asyncCopyReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "async_copy_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "async_copy_reads_total"),
"(AsyncCopyReadsTotal)", "(AsyncCopyReadsTotal)",
nil, nil,
nil, nil,
) )
c.AsyncDataMapsTotal = prometheus.NewDesc( c.asyncDataMapsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "async_data_maps_total"), prometheus.BuildFQName(types.Namespace, Name, "async_data_maps_total"),
"(AsyncDataMapsTotal)", "(AsyncDataMapsTotal)",
nil, nil,
nil, nil,
) )
c.AsyncFastReadsTotal = prometheus.NewDesc( c.asyncFastReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "async_fast_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "async_fast_reads_total"),
"(AsyncFastReadsTotal)", "(AsyncFastReadsTotal)",
nil, nil,
nil, nil,
) )
c.AsyncMDLReadsTotal = prometheus.NewDesc( c.asyncMDLReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "async_mdl_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "async_mdl_reads_total"),
"(AsyncMDLReadsTotal)", "(AsyncMDLReadsTotal)",
nil, nil,
nil, nil,
) )
c.AsyncPinReadsTotal = prometheus.NewDesc( c.asyncPinReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "async_pin_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "async_pin_reads_total"),
"(AsyncPinReadsTotal)", "(AsyncPinReadsTotal)",
nil, nil,
nil, nil,
) )
c.CopyReadHitsTotal = prometheus.NewDesc( c.copyReadHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "copy_read_hits_total"), prometheus.BuildFQName(types.Namespace, Name, "copy_read_hits_total"),
"(CopyReadHitsTotal)", "(CopyReadHitsTotal)",
nil, nil,
nil, nil,
) )
c.CopyReadsTotal = prometheus.NewDesc( c.copyReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "copy_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "copy_reads_total"),
"(CopyReadsTotal)", "(CopyReadsTotal)",
nil, nil,
nil, nil,
) )
c.DataFlushesTotal = prometheus.NewDesc( c.dataFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "data_flushes_total"), prometheus.BuildFQName(types.Namespace, Name, "data_flushes_total"),
"(DataFlushesTotal)", "(DataFlushesTotal)",
nil, nil,
nil, nil,
) )
c.DataFlushPagesTotal = prometheus.NewDesc( c.dataFlushPagesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "data_flush_pages_total"), prometheus.BuildFQName(types.Namespace, Name, "data_flush_pages_total"),
"(DataFlushPagesTotal)", "(DataFlushPagesTotal)",
nil, nil,
nil, nil,
) )
c.DataMapHitsPercent = prometheus.NewDesc( c.dataMapHitsPercent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "data_map_hits_percent"), prometheus.BuildFQName(types.Namespace, Name, "data_map_hits_percent"),
"(DataMapHitsPercent)", "(DataMapHitsPercent)",
nil, nil,
nil, nil,
) )
c.DataMapPinsTotal = prometheus.NewDesc( c.dataMapPinsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "data_map_pins_total"), prometheus.BuildFQName(types.Namespace, Name, "data_map_pins_total"),
"(DataMapPinsTotal)", "(DataMapPinsTotal)",
nil, nil,
nil, nil,
) )
c.DataMapsTotal = prometheus.NewDesc( c.dataMapsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "data_maps_total"), prometheus.BuildFQName(types.Namespace, Name, "data_maps_total"),
"(DataMapsTotal)", "(DataMapsTotal)",
nil, nil,
nil, nil,
) )
c.DirtyPages = prometheus.NewDesc( c.dirtyPages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dirty_pages"), prometheus.BuildFQName(types.Namespace, Name, "dirty_pages"),
"(DirtyPages)", "(DirtyPages)",
nil, nil,
nil, nil,
) )
c.DirtyPageThreshold = prometheus.NewDesc( c.dirtyPageThreshold = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dirty_page_threshold"), prometheus.BuildFQName(types.Namespace, Name, "dirty_page_threshold"),
"(DirtyPageThreshold)", "(DirtyPageThreshold)",
nil, nil,
nil, nil,
) )
c.FastReadNotPossiblesTotal = prometheus.NewDesc( c.fastReadNotPossiblesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "fast_read_not_possibles_total"), prometheus.BuildFQName(types.Namespace, Name, "fast_read_not_possibles_total"),
"(FastReadNotPossiblesTotal)", "(FastReadNotPossiblesTotal)",
nil, nil,
nil, nil,
) )
c.FastReadResourceMissesTotal = prometheus.NewDesc( c.fastReadResourceMissesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "fast_read_resource_misses_total"), prometheus.BuildFQName(types.Namespace, Name, "fast_read_resource_misses_total"),
"(FastReadResourceMissesTotal)", "(FastReadResourceMissesTotal)",
nil, nil,
nil, nil,
) )
c.FastReadsTotal = prometheus.NewDesc( c.fastReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "fast_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "fast_reads_total"),
"(FastReadsTotal)", "(FastReadsTotal)",
nil, nil,
nil, nil,
) )
c.LazyWriteFlushesTotal = prometheus.NewDesc( c.lazyWriteFlushesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "lazy_write_flushes_total"), prometheus.BuildFQName(types.Namespace, Name, "lazy_write_flushes_total"),
"(LazyWriteFlushesTotal)", "(LazyWriteFlushesTotal)",
nil, nil,
nil, nil,
) )
c.LazyWritePagesTotal = prometheus.NewDesc( c.lazyWritePagesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "lazy_write_pages_total"), prometheus.BuildFQName(types.Namespace, Name, "lazy_write_pages_total"),
"(LazyWritePagesTotal)", "(LazyWritePagesTotal)",
nil, nil,
nil, nil,
) )
c.MDLReadHitsTotal = prometheus.NewDesc( c.mdlReadHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "mdl_read_hits_total"), prometheus.BuildFQName(types.Namespace, Name, "mdl_read_hits_total"),
"(MDLReadHitsTotal)", "(MDLReadHitsTotal)",
nil, nil,
nil, nil,
) )
c.MDLReadsTotal = prometheus.NewDesc( c.mdlReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "mdl_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "mdl_reads_total"),
"(MDLReadsTotal)", "(MDLReadsTotal)",
nil, nil,
nil, nil,
) )
c.PinReadHitsTotal = prometheus.NewDesc( c.pinReadHitsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pin_read_hits_total"), prometheus.BuildFQName(types.Namespace, Name, "pin_read_hits_total"),
"(PinReadHitsTotal)", "(PinReadHitsTotal)",
nil, nil,
nil, nil,
) )
c.PinReadsTotal = prometheus.NewDesc( c.pinReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pin_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "pin_reads_total"),
"(PinReadsTotal)", "(PinReadsTotal)",
nil, nil,
nil, nil,
) )
c.ReadAheadsTotal = prometheus.NewDesc( c.readAheadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "read_aheads_total"), prometheus.BuildFQName(types.Namespace, Name, "read_aheads_total"),
"(ReadAheadsTotal)", "(ReadAheadsTotal)",
nil, nil,
nil, nil,
) )
c.SyncCopyReadsTotal = prometheus.NewDesc( c.syncCopyReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "sync_copy_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "sync_copy_reads_total"),
"(SyncCopyReadsTotal)", "(SyncCopyReadsTotal)",
nil, nil,
nil, nil,
) )
c.SyncDataMapsTotal = prometheus.NewDesc( c.syncDataMapsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "sync_data_maps_total"), prometheus.BuildFQName(types.Namespace, Name, "sync_data_maps_total"),
"(SyncDataMapsTotal)", "(SyncDataMapsTotal)",
nil, nil,
nil, nil,
) )
c.SyncFastReadsTotal = prometheus.NewDesc( c.syncFastReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "sync_fast_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "sync_fast_reads_total"),
"(SyncFastReadsTotal)", "(SyncFastReadsTotal)",
nil, nil,
nil, nil,
) )
c.SyncMDLReadsTotal = prometheus.NewDesc( c.syncMDLReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "sync_mdl_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "sync_mdl_reads_total"),
"(SyncMDLReadsTotal)", "(SyncMDLReadsTotal)",
nil, nil,
nil, nil,
) )
c.SyncPinReadsTotal = prometheus.NewDesc( c.syncPinReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "sync_pin_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "sync_pin_reads_total"),
"(SyncPinReadsTotal)", "(SyncPinReadsTotal)",
nil, nil,
@@ -252,12 +260,15 @@ func (c *collector) Build() error {
return nil return nil
} }
// Collect implements the Collector interface // Collect implements the Collector interface.
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting cache metrics", "desc", desc, "err", err) if err := c.collect(ctx, logger, ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting cache metrics", "err", err)
return err return err
} }
return nil return nil
} }
@@ -295,185 +306,190 @@ type perflibCache struct {
SyncPinReadsTotal float64 `perflib:"Sync Pin Reads/sec"` SyncPinReadsTotal float64 `perflib:"Sync Pin Reads/sec"`
} }
func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var dst []perflibCache // Single-instance class, array is required but will have single entry. var dst []perflibCache // Single-instance class, array is required but will have single entry.
if err := perflib.UnmarshalObject(ctx.PerfObjects["Cache"], &dst, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["Cache"], &dst, logger); err != nil {
return nil, err return err
}
if len(dst) != 1 {
return errors.New("expected single instance of Cache")
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AsyncCopyReadsTotal, c.asyncCopyReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].AsyncCopyReadsTotal, dst[0].AsyncCopyReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AsyncDataMapsTotal, c.asyncDataMapsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].AsyncDataMapsTotal, dst[0].AsyncDataMapsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AsyncFastReadsTotal, c.asyncFastReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].AsyncFastReadsTotal, dst[0].AsyncFastReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AsyncMDLReadsTotal, c.asyncMDLReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].AsyncMDLReadsTotal, dst[0].AsyncMDLReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AsyncPinReadsTotal, c.asyncPinReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].AsyncPinReadsTotal, dst[0].AsyncPinReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CopyReadHitsTotal, c.copyReadHitsTotal,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].CopyReadHitsTotal, dst[0].CopyReadHitsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CopyReadsTotal, c.copyReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].CopyReadsTotal, dst[0].CopyReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DataFlushesTotal, c.dataFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].DataFlushesTotal, dst[0].DataFlushesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DataFlushPagesTotal, c.dataFlushPagesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].DataFlushPagesTotal, dst[0].DataFlushPagesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DataMapHitsPercent, c.dataMapHitsPercent,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].DataMapHitsPercent, dst[0].DataMapHitsPercent,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DataMapPinsTotal, c.dataMapPinsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].DataMapPinsTotal, dst[0].DataMapPinsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DataMapsTotal, c.dataMapsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].DataMapsTotal, dst[0].DataMapsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DirtyPages, c.dirtyPages,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].DirtyPages, dst[0].DirtyPages,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DirtyPageThreshold, c.dirtyPageThreshold,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].DirtyPageThreshold, dst[0].DirtyPageThreshold,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FastReadNotPossiblesTotal, c.fastReadNotPossiblesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].FastReadNotPossiblesTotal, dst[0].FastReadNotPossiblesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FastReadResourceMissesTotal, c.fastReadResourceMissesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].FastReadResourceMissesTotal, dst[0].FastReadResourceMissesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FastReadsTotal, c.fastReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].FastReadsTotal, dst[0].FastReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LazyWriteFlushesTotal, c.lazyWriteFlushesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].LazyWriteFlushesTotal, dst[0].LazyWriteFlushesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LazyWritePagesTotal, c.lazyWritePagesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].LazyWritePagesTotal, dst[0].LazyWritePagesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MDLReadHitsTotal, c.mdlReadHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].MDLReadHitsTotal, dst[0].MDLReadHitsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MDLReadsTotal, c.mdlReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].MDLReadsTotal, dst[0].MDLReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PinReadHitsTotal, c.pinReadHitsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PinReadHitsTotal, dst[0].PinReadHitsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PinReadsTotal, c.pinReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PinReadsTotal, dst[0].PinReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadAheadsTotal, c.readAheadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].ReadAheadsTotal, dst[0].ReadAheadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SyncCopyReadsTotal, c.syncCopyReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].SyncCopyReadsTotal, dst[0].SyncCopyReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SyncDataMapsTotal, c.syncDataMapsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].SyncDataMapsTotal, dst[0].SyncDataMapsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SyncFastReadsTotal, c.syncFastReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].SyncFastReadsTotal, dst[0].SyncFastReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SyncMDLReadsTotal, c.syncMDLReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].SyncMDLReadsTotal, dst[0].SyncMDLReadsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SyncPinReadsTotal, c.syncPinReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].SyncPinReadsTotal, dst[0].SyncPinReadsTotal,
) )
return nil, nil return nil
} }

12
pkg/collector/cache/cache_test.go vendored Normal file
View File

@@ -0,0 +1,12 @@
package cache_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/pkg/collector/cache"
"github.com/prometheus-community/windows_exporter/pkg/testutils"
)
func BenchmarkCollector(b *testing.B) {
testutils.FuncBenchmarkCollector(b, cache.Name, cache.NewWithFlags)
}

View File

@@ -3,6 +3,8 @@
package collector package collector
import ( import (
"errors"
"fmt"
"slices" "slices"
"strings" "strings"
@@ -21,16 +23,14 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/diskdrive" "github.com/prometheus-community/windows_exporter/pkg/collector/diskdrive"
"github.com/prometheus-community/windows_exporter/pkg/collector/dns" "github.com/prometheus-community/windows_exporter/pkg/collector/dns"
"github.com/prometheus-community/windows_exporter/pkg/collector/exchange" "github.com/prometheus-community/windows_exporter/pkg/collector/exchange"
"github.com/prometheus-community/windows_exporter/pkg/collector/fsrmquota"
"github.com/prometheus-community/windows_exporter/pkg/collector/hyperv" "github.com/prometheus-community/windows_exporter/pkg/collector/hyperv"
"github.com/prometheus-community/windows_exporter/pkg/collector/iis" "github.com/prometheus-community/windows_exporter/pkg/collector/iis"
"github.com/prometheus-community/windows_exporter/pkg/collector/license"
"github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk" "github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk"
"github.com/prometheus-community/windows_exporter/pkg/collector/logon" "github.com/prometheus-community/windows_exporter/pkg/collector/logon"
"github.com/prometheus-community/windows_exporter/pkg/collector/memory" "github.com/prometheus-community/windows_exporter/pkg/collector/memory"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_cluster" "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_network"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_node"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resource"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resourcegroup"
"github.com/prometheus-community/windows_exporter/pkg/collector/msmq" "github.com/prometheus-community/windows_exporter/pkg/collector/msmq"
"github.com/prometheus-community/windows_exporter/pkg/collector/mssql" "github.com/prometheus-community/windows_exporter/pkg/collector/mssql"
"github.com/prometheus-community/windows_exporter/pkg/collector/net" "github.com/prometheus-community/windows_exporter/pkg/collector/net"
@@ -45,11 +45,13 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/nps" "github.com/prometheus-community/windows_exporter/pkg/collector/nps"
"github.com/prometheus-community/windows_exporter/pkg/collector/os" "github.com/prometheus-community/windows_exporter/pkg/collector/os"
"github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk" "github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk"
"github.com/prometheus-community/windows_exporter/pkg/collector/printer"
"github.com/prometheus-community/windows_exporter/pkg/collector/process" "github.com/prometheus-community/windows_exporter/pkg/collector/process"
"github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx" "github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx"
"github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task" "github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task"
"github.com/prometheus-community/windows_exporter/pkg/collector/service" "github.com/prometheus-community/windows_exporter/pkg/collector/service"
"github.com/prometheus-community/windows_exporter/pkg/collector/smb" "github.com/prometheus-community/windows_exporter/pkg/collector/smb"
"github.com/prometheus-community/windows_exporter/pkg/collector/smbclient"
"github.com/prometheus-community/windows_exporter/pkg/collector/smtp" "github.com/prometheus-community/windows_exporter/pkg/collector/smtp"
"github.com/prometheus-community/windows_exporter/pkg/collector/system" "github.com/prometheus-community/windows_exporter/pkg/collector/system"
"github.com/prometheus-community/windows_exporter/pkg/collector/tcp" "github.com/prometheus-community/windows_exporter/pkg/collector/tcp"
@@ -62,20 +64,14 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/vmware_blast" "github.com/prometheus-community/windows_exporter/pkg/collector/vmware_blast"
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/yusufpapurcu/wmi"
) )
type Collectors struct { // NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse.
logger log.Logger func NewWithFlags(app *kingpin.Application) *Collectors {
collectors := map[string]Collector{}
collectors map[string]types.Collector for name, builder := range BuildersWithFlags {
perfCounterQuery string
}
// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse
func NewWithFlags(app *kingpin.Application) Collectors {
collectors := map[string]types.Collector{}
for name, builder := range Map {
collectors[name] = builder(app) collectors[name] = builder(app)
} }
@@ -83,91 +79,88 @@ func NewWithFlags(app *kingpin.Application) Collectors {
} }
// NewWithConfig To be called by the external libraries for collector initialization without running kingpin.Parse // NewWithConfig To be called by the external libraries for collector initialization without running kingpin.Parse
func NewWithConfig(logger log.Logger, config Config) Collectors { //
collectors := map[string]types.Collector{} //goland:noinspection GoUnusedExportedFunction
collectors[ad.Name] = ad.New(logger, &config.Ad) func NewWithConfig(config Config) *Collectors {
collectors[adcs.Name] = adcs.New(logger, &config.Adcs) collectors := map[string]Collector{}
collectors[adfs.Name] = adfs.New(logger, &config.Adfs) collectors[ad.Name] = ad.New(&config.AD)
collectors[cache.Name] = cache.New(logger, &config.Cache) collectors[adcs.Name] = adcs.New(&config.ADCS)
collectors[container.Name] = container.New(logger, &config.Container) collectors[adfs.Name] = adfs.New(&config.ADFS)
collectors[cpu.Name] = cpu.New(logger, &config.Cpu) collectors[cache.Name] = cache.New(&config.Cache)
collectors[cpu_info.Name] = cpu_info.New(logger, &config.CpuInfo) collectors[container.Name] = container.New(&config.Container)
collectors[cs.Name] = cs.New(logger, &config.Cs) collectors[cpu.Name] = cpu.New(&config.CPU)
collectors[dfsr.Name] = dfsr.New(logger, &config.Dfsr) collectors[cpu_info.Name] = cpu_info.New(&config.CPUInfo)
collectors[dhcp.Name] = dhcp.New(logger, &config.Dhcp) collectors[cs.Name] = cs.New(&config.Cs)
collectors[diskdrive.Name] = diskdrive.New(logger, &config.Diskdrive) collectors[dfsr.Name] = dfsr.New(&config.DFSR)
collectors[dns.Name] = dns.New(logger, &config.Dns) collectors[dhcp.Name] = dhcp.New(&config.Dhcp)
collectors[exchange.Name] = exchange.New(logger, &config.Exchange) collectors[diskdrive.Name] = diskdrive.New(&config.DiskDrive)
collectors[exchange.Name] = exchange.New(logger, &config.Fsrmquota) collectors[dns.Name] = dns.New(&config.DNS)
collectors[hyperv.Name] = hyperv.New(logger, &config.Hyperv) collectors[exchange.Name] = exchange.New(&config.Exchange)
collectors[iis.Name] = iis.New(logger, &config.Iis) collectors[fsrmquota.Name] = fsrmquota.New(&config.Fsrmquota)
collectors[logical_disk.Name] = logical_disk.New(logger, &config.LogicalDisk) collectors[hyperv.Name] = hyperv.New(&config.Hyperv)
collectors[logon.Name] = logon.New(logger, &config.Logon) collectors[iis.Name] = iis.New(&config.IIS)
collectors[memory.Name] = memory.New(logger, &config.Memory) collectors[license.Name] = license.New(&config.License)
collectors[mscluster_cluster.Name] = mscluster_cluster.New(logger, &config.MsclusterCluster) collectors[logical_disk.Name] = logical_disk.New(&config.LogicalDisk)
collectors[mscluster_network.Name] = mscluster_network.New(logger, &config.MsclusterNetwork) collectors[logon.Name] = logon.New(&config.Logon)
collectors[mscluster_node.Name] = mscluster_node.New(logger, &config.MsclusterNode) collectors[memory.Name] = memory.New(&config.Memory)
collectors[mscluster_resource.Name] = mscluster_resource.New(logger, &config.MsclusterResource) collectors[mscluster.Name] = mscluster.New(&config.Mscluster)
collectors[mscluster_resourcegroup.Name] = mscluster_resourcegroup.New(logger, &config.MsclusterResourceGroup) collectors[msmq.Name] = msmq.New(&config.Msmq)
collectors[msmq.Name] = msmq.New(logger, &config.Msmq) collectors[mssql.Name] = mssql.New(&config.Mssql)
collectors[mssql.Name] = mssql.New(logger, &config.Mssql) collectors[net.Name] = net.New(&config.Net)
collectors[net.Name] = net.New(logger, &config.Net) collectors[netframework_clrexceptions.Name] = netframework_clrexceptions.New(&config.NetframeworkClrexceptions)
collectors[netframework_clrexceptions.Name] = netframework_clrexceptions.New(logger, &config.NetframeworkClrexceptions) collectors[netframework_clrinterop.Name] = netframework_clrinterop.New(&config.NetframeworkClrinterop)
collectors[netframework_clrinterop.Name] = netframework_clrinterop.New(logger, &config.NetframeworkClrinterop) collectors[netframework_clrjit.Name] = netframework_clrjit.New(&config.NetframeworkClrjit)
collectors[netframework_clrjit.Name] = netframework_clrjit.New(logger, &config.NetframeworkClrjit) collectors[netframework_clrloading.Name] = netframework_clrloading.New(&config.NetframeworkClrloading)
collectors[netframework_clrloading.Name] = netframework_clrloading.New(logger, &config.NetframeworkClrloading) collectors[netframework_clrlocksandthreads.Name] = netframework_clrlocksandthreads.New(&config.NetframeworkClrlocksandthreads)
collectors[netframework_clrlocksandthreads.Name] = netframework_clrlocksandthreads.New(logger, &config.NetframeworkClrlocksandthreads) collectors[netframework_clrmemory.Name] = netframework_clrmemory.New(&config.NetframeworkClrmemory)
collectors[netframework_clrmemory.Name] = netframework_clrmemory.New(logger, &config.NetframeworkClrmemory) collectors[netframework_clrremoting.Name] = netframework_clrremoting.New(&config.NetframeworkClrremoting)
collectors[netframework_clrremoting.Name] = netframework_clrremoting.New(logger, &config.NetframeworkClrremoting) collectors[netframework_clrsecurity.Name] = netframework_clrsecurity.New(&config.NetframeworkClrsecurity)
collectors[netframework_clrsecurity.Name] = netframework_clrsecurity.New(logger, &config.NetframeworkClrsecurity) collectors[nps.Name] = nps.New(&config.Nps)
collectors[nps.Name] = nps.New(logger, &config.Nps) collectors[os.Name] = os.New(&config.Os)
collectors[os.Name] = os.New(logger, &config.Os) collectors[physical_disk.Name] = physical_disk.New(&config.PhysicalDisk)
collectors[physical_disk.Name] = physical_disk.New(logger, &config.PhysicalDisk) collectors[printer.Name] = printer.New(&config.Printer)
collectors[process.Name] = process.New(logger, &config.Process) collectors[process.Name] = process.New(&config.Process)
collectors[remote_fx.Name] = remote_fx.New(logger, &config.RemoteFx) collectors[remote_fx.Name] = remote_fx.New(&config.RemoteFx)
collectors[scheduled_task.Name] = scheduled_task.New(logger, &config.ScheduledTask) collectors[scheduled_task.Name] = scheduled_task.New(&config.ScheduledTask)
collectors[service.Name] = service.New(logger, &config.Service) collectors[service.Name] = service.New(&config.Service)
collectors[smb.Name] = smb.New(logger, &config.Smb) collectors[smb.Name] = smb.New(&config.SMB)
collectors[smtp.Name] = smtp.New(logger, &config.Smtp) collectors[smbclient.Name] = smbclient.New(&config.SMBClient)
collectors[system.Name] = system.New(logger, &config.System) collectors[smtp.Name] = smtp.New(&config.SMTP)
collectors[teradici_pcoip.Name] = teradici_pcoip.New(logger, &config.TeradiciPcoip) collectors[system.Name] = system.New(&config.System)
collectors[tcp.Name] = tcp.New(logger, &config.Tcp) collectors[teradici_pcoip.Name] = teradici_pcoip.New(&config.TeradiciPcoip)
collectors[terminal_services.Name] = terminal_services.New(logger, &config.TerminalServices) collectors[tcp.Name] = tcp.New(&config.TCP)
collectors[textfile.Name] = textfile.New(logger, &config.Textfile) collectors[terminal_services.Name] = terminal_services.New(&config.TerminalServices)
collectors[thermalzone.Name] = thermalzone.New(logger, &config.Thermalzone) collectors[textfile.Name] = textfile.New(&config.Textfile)
collectors[time.Name] = time.New(logger, &config.Time) collectors[thermalzone.Name] = thermalzone.New(&config.Thermalzone)
collectors[vmware.Name] = vmware.New(logger, &config.Vmware) collectors[time.Name] = time.New(&config.Time)
collectors[vmware_blast.Name] = vmware_blast.New(logger, &config.VmwareBlast) collectors[vmware.Name] = vmware.New(&config.Vmware)
collectors[vmware_blast.Name] = vmware_blast.New(&config.VmwareBlast)
return New(collectors) return New(collectors)
} }
// New To be called by the external libraries for collector initialization // New To be called by the external libraries for collector initialization.
func New(collectors map[string]types.Collector) Collectors { func New(collectors Map) *Collectors {
return Collectors{ return &Collectors{
collectors: collectors, collectors: collectors,
wmiClient: &wmi.Client{
AllowMissingFields: true,
},
} }
} }
func (c *Collectors) SetLogger(logger log.Logger) { func (c *Collectors) SetPerfCounterQuery(logger log.Logger) error {
c.logger = logger
for _, collector := range c.collectors {
collector.SetLogger(logger)
}
}
func (c *Collectors) SetPerfCounterQuery() error {
var ( var (
err error err error
perfCounterDependencies []string perfCounterNames []string
perfCounterNames []string perfIndicies []string
perfIndicies []string
) )
perfCounterDependencies := make([]string, 0, len(c.collectors))
for _, collector := range c.collectors { for _, collector := range c.collectors {
perfCounterNames, err = collector.GetPerfCounter() perfCounterNames, err = collector.GetPerfCounter(logger)
if err != nil { if err != nil {
return err return err
} }
@@ -185,7 +178,7 @@ func (c *Collectors) SetPerfCounterQuery() error {
return nil return nil
} }
// Enable removes all collectors that not enabledCollectors // Enable removes all collectors that not enabledCollectors.
func (c *Collectors) Enable(enabledCollectors []string) { func (c *Collectors) Enable(enabledCollectors []string) {
for name := range c.collectors { for name := range c.collectors {
if !slices.Contains(enabledCollectors, name) { if !slices.Contains(enabledCollectors, name) {
@@ -194,19 +187,25 @@ func (c *Collectors) Enable(enabledCollectors []string) {
} }
} }
// Build To be called by the exporter for collector initialization // Build To be called by the exporter for collector initialization.
func (c *Collectors) Build() error { func (c *Collectors) Build(logger log.Logger) error {
var err error var err error
c.wmiClient.SWbemServicesClient, err = wmi.InitializeSWbemServices(c.wmiClient)
if err != nil {
return fmt.Errorf("initialize SWbemServices: %w", err)
}
for _, collector := range c.collectors { for _, collector := range c.collectors {
if err = collector.Build(); err != nil { if err = collector.Build(logger, c.wmiClient); err != nil {
return err return fmt.Errorf("error build collector %s: %w", collector.GetName(), err)
} }
} }
return nil return nil
} }
// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape // PrepareScrapeContext creates a ScrapeContext to be used during a single scrape.
func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) { func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) {
objs, err := perflib.GetPerflibSnapshot(c.perfCounterQuery) objs, err := perflib.GetPerflibSnapshot(c.perfCounterQuery)
if err != nil { if err != nil {
@@ -215,3 +214,22 @@ func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) {
return &types.ScrapeContext{PerfObjects: objs}, nil return &types.ScrapeContext{PerfObjects: objs}, nil
} }
// Close To be called by the exporter for collector cleanup.
func (c *Collectors) Close() error {
errs := make([]error, 0, len(c.collectors))
for _, collector := range c.collectors {
if err := collector.Close(); err != nil {
errs = append(errs, err)
}
}
if c.wmiClient != nil && c.wmiClient.SWbemServicesClient != nil {
if err := c.wmiClient.SWbemServicesClient.Close(); err != nil {
errs = append(errs, err)
}
}
return errors.Join(errs...)
}

View File

@@ -14,16 +14,14 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/diskdrive" "github.com/prometheus-community/windows_exporter/pkg/collector/diskdrive"
"github.com/prometheus-community/windows_exporter/pkg/collector/dns" "github.com/prometheus-community/windows_exporter/pkg/collector/dns"
"github.com/prometheus-community/windows_exporter/pkg/collector/exchange" "github.com/prometheus-community/windows_exporter/pkg/collector/exchange"
"github.com/prometheus-community/windows_exporter/pkg/collector/fsrmquota"
"github.com/prometheus-community/windows_exporter/pkg/collector/hyperv" "github.com/prometheus-community/windows_exporter/pkg/collector/hyperv"
"github.com/prometheus-community/windows_exporter/pkg/collector/iis" "github.com/prometheus-community/windows_exporter/pkg/collector/iis"
"github.com/prometheus-community/windows_exporter/pkg/collector/license"
"github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk" "github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk"
"github.com/prometheus-community/windows_exporter/pkg/collector/logon" "github.com/prometheus-community/windows_exporter/pkg/collector/logon"
"github.com/prometheus-community/windows_exporter/pkg/collector/memory" "github.com/prometheus-community/windows_exporter/pkg/collector/memory"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_cluster" "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_network"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_node"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resource"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resourcegroup"
"github.com/prometheus-community/windows_exporter/pkg/collector/msmq" "github.com/prometheus-community/windows_exporter/pkg/collector/msmq"
"github.com/prometheus-community/windows_exporter/pkg/collector/mssql" "github.com/prometheus-community/windows_exporter/pkg/collector/mssql"
"github.com/prometheus-community/windows_exporter/pkg/collector/net" "github.com/prometheus-community/windows_exporter/pkg/collector/net"
@@ -38,11 +36,13 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/nps" "github.com/prometheus-community/windows_exporter/pkg/collector/nps"
"github.com/prometheus-community/windows_exporter/pkg/collector/os" "github.com/prometheus-community/windows_exporter/pkg/collector/os"
"github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk" "github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk"
"github.com/prometheus-community/windows_exporter/pkg/collector/printer"
"github.com/prometheus-community/windows_exporter/pkg/collector/process" "github.com/prometheus-community/windows_exporter/pkg/collector/process"
"github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx" "github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx"
"github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task" "github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task"
"github.com/prometheus-community/windows_exporter/pkg/collector/service" "github.com/prometheus-community/windows_exporter/pkg/collector/service"
"github.com/prometheus-community/windows_exporter/pkg/collector/smb" "github.com/prometheus-community/windows_exporter/pkg/collector/smb"
"github.com/prometheus-community/windows_exporter/pkg/collector/smbclient"
"github.com/prometheus-community/windows_exporter/pkg/collector/smtp" "github.com/prometheus-community/windows_exporter/pkg/collector/smtp"
"github.com/prometheus-community/windows_exporter/pkg/collector/system" "github.com/prometheus-community/windows_exporter/pkg/collector/system"
"github.com/prometheus-community/windows_exporter/pkg/collector/tcp" "github.com/prometheus-community/windows_exporter/pkg/collector/tcp"
@@ -56,30 +56,27 @@ import (
) )
type Config struct { type Config struct {
Ad ad.Config `yaml:"ad"` AD ad.Config `yaml:"ad"`
Adcs adcs.Config `yaml:"adcs"` ADCS adcs.Config `yaml:"adcs"`
Adfs adfs.Config `yaml:"adfs"` ADFS adfs.Config `yaml:"adfs"`
Cache cache.Config `yaml:"cache"` Cache cache.Config `yaml:"cache"`
Container container.Config `yaml:"container"` Container container.Config `yaml:"container"`
Cpu cpu.Config `yaml:"cpu"` CPU cpu.Config `yaml:"cpu"`
CpuInfo cpu_info.Config `yaml:"cpu_info"` CPUInfo cpu_info.Config `yaml:"cpu_info"`
Cs cs.Config `yaml:"cs"` Cs cs.Config `yaml:"cs"`
Dfsr dfsr.Config `yaml:"dfsr"` DFSR dfsr.Config `yaml:"dfsr"`
Dhcp dhcp.Config `yaml:"dhcp"` Dhcp dhcp.Config `yaml:"dhcp"`
Diskdrive diskdrive.Config `yaml:"diskdrive"` DiskDrive diskdrive.Config `yaml:"diskdrive"` //nolint:tagliatelle
Dns dns.Config `yaml:"dns"` DNS dns.Config `yaml:"dns"`
Exchange exchange.Config `yaml:"exchange"` Exchange exchange.Config `yaml:"exchange"`
Fsrmquota exchange.Config `yaml:"fsrmquota"` Fsrmquota fsrmquota.Config `yaml:"fsrmquota"`
Hyperv hyperv.Config `yaml:"hyperv"` Hyperv hyperv.Config `yaml:"hyperv"`
Iis iis.Config `yaml:"iis"` IIS iis.Config `yaml:"iis"`
License license.Config `yaml:"license"`
LogicalDisk logical_disk.Config `yaml:"logical_disk"` LogicalDisk logical_disk.Config `yaml:"logical_disk"`
Logon logon.Config `yaml:"logon"` Logon logon.Config `yaml:"logon"`
Memory memory.Config `yaml:"memory"` Memory memory.Config `yaml:"memory"`
MsclusterCluster mscluster_cluster.Config `yaml:"mscluster_cluster"` Mscluster mscluster.Config `yaml:"mscluster"`
MsclusterNetwork mscluster_network.Config `yaml:"mscluster_network"`
MsclusterNode mscluster_node.Config `yaml:"mscluster_node"`
MsclusterResource mscluster_resource.Config `yaml:"mscluster_resource"`
MsclusterResourceGroup mscluster_resourcegroup.Config `yaml:"mscluster_resourcegroup"`
Msmq msmq.Config `yaml:"msmq"` Msmq msmq.Config `yaml:"msmq"`
Mssql mssql.Config `yaml:"mssql"` Mssql mssql.Config `yaml:"mssql"`
Net net.Config `yaml:"net"` Net net.Config `yaml:"net"`
@@ -94,15 +91,17 @@ type Config struct {
Nps nps.Config `yaml:"nps"` Nps nps.Config `yaml:"nps"`
Os os.Config `yaml:"os"` Os os.Config `yaml:"os"`
PhysicalDisk physical_disk.Config `yaml:"physical_disk"` PhysicalDisk physical_disk.Config `yaml:"physical_disk"`
Printer printer.Config `yaml:"printer"`
Process process.Config `yaml:"process"` Process process.Config `yaml:"process"`
RemoteFx remote_fx.Config `yaml:"remote_fx"` RemoteFx remote_fx.Config `yaml:"remote_fx"`
ScheduledTask scheduled_task.Config `yaml:"scheduled_task"` ScheduledTask scheduled_task.Config `yaml:"scheduled_task"`
Service service.Config `yaml:"service"` Service service.Config `yaml:"service"`
Smb smb.Config `yaml:"smb"` SMB smb.Config `yaml:"smb"`
Smtp smtp.Config `yaml:"smtp"` SMBClient smbclient.Config `yaml:"smbclient"` //nolint:tagliatelle
SMTP smtp.Config `yaml:"smtp"`
System system.Config `yaml:"system"` System system.Config `yaml:"system"`
TeradiciPcoip teradici_pcoip.Config `yaml:"teradici_pcoip"` TeradiciPcoip teradici_pcoip.Config `yaml:"teradici_pcoip"`
Tcp tcp.Config `yaml:"tcp"` TCP tcp.Config `yaml:"tcp"`
TerminalServices terminal_services.Config `yaml:"terminal_services"` TerminalServices terminal_services.Config `yaml:"terminal_services"`
Textfile textfile.Config `yaml:"textfile"` Textfile textfile.Config `yaml:"textfile"`
Thermalzone thermalzone.Config `yaml:"thermalzone"` Thermalzone thermalzone.Config `yaml:"thermalzone"`
@@ -112,31 +111,30 @@ type Config struct {
} }
// ConfigDefaults Is an interface to be used by the external libraries. It holds all ConfigDefaults form all collectors // ConfigDefaults Is an interface to be used by the external libraries. It holds all ConfigDefaults form all collectors
//
//goland:noinspection GoUnusedGlobalVariable
var ConfigDefaults = Config{ var ConfigDefaults = Config{
Ad: ad.ConfigDefaults, AD: ad.ConfigDefaults,
Adcs: adcs.ConfigDefaults, ADCS: adcs.ConfigDefaults,
Adfs: adfs.ConfigDefaults, ADFS: adfs.ConfigDefaults,
Cache: cache.ConfigDefaults, Cache: cache.ConfigDefaults,
Container: container.ConfigDefaults, Container: container.ConfigDefaults,
Cpu: cpu.ConfigDefaults, CPU: cpu.ConfigDefaults,
CpuInfo: cpu_info.ConfigDefaults, CPUInfo: cpu_info.ConfigDefaults,
Cs: cs.ConfigDefaults, Cs: cs.ConfigDefaults,
Dfsr: dfsr.ConfigDefaults, DFSR: dfsr.ConfigDefaults,
Dhcp: dhcp.ConfigDefaults, Dhcp: dhcp.ConfigDefaults,
Diskdrive: diskdrive.ConfigDefaults, DiskDrive: diskdrive.ConfigDefaults,
Dns: dns.ConfigDefaults, DNS: dns.ConfigDefaults,
Exchange: exchange.ConfigDefaults, Exchange: exchange.ConfigDefaults,
Fsrmquota: exchange.ConfigDefaults, Fsrmquota: fsrmquota.ConfigDefaults,
Hyperv: hyperv.ConfigDefaults, Hyperv: hyperv.ConfigDefaults,
Iis: iis.ConfigDefaults, IIS: iis.ConfigDefaults,
License: license.ConfigDefaults,
LogicalDisk: logical_disk.ConfigDefaults, LogicalDisk: logical_disk.ConfigDefaults,
Logon: logon.ConfigDefaults, Logon: logon.ConfigDefaults,
Memory: memory.ConfigDefaults, Memory: memory.ConfigDefaults,
MsclusterCluster: mscluster_cluster.ConfigDefaults, Mscluster: mscluster.ConfigDefaults,
MsclusterNetwork: mscluster_network.ConfigDefaults,
MsclusterNode: mscluster_node.ConfigDefaults,
MsclusterResource: mscluster_resource.ConfigDefaults,
MsclusterResourceGroup: mscluster_resourcegroup.ConfigDefaults,
Msmq: msmq.ConfigDefaults, Msmq: msmq.ConfigDefaults,
Mssql: mssql.ConfigDefaults, Mssql: mssql.ConfigDefaults,
Net: net.ConfigDefaults, Net: net.ConfigDefaults,
@@ -151,15 +149,17 @@ var ConfigDefaults = Config{
Nps: nps.ConfigDefaults, Nps: nps.ConfigDefaults,
Os: os.ConfigDefaults, Os: os.ConfigDefaults,
PhysicalDisk: physical_disk.ConfigDefaults, PhysicalDisk: physical_disk.ConfigDefaults,
Printer: printer.ConfigDefaults,
Process: process.ConfigDefaults, Process: process.ConfigDefaults,
RemoteFx: remote_fx.ConfigDefaults, RemoteFx: remote_fx.ConfigDefaults,
ScheduledTask: scheduled_task.ConfigDefaults, ScheduledTask: scheduled_task.ConfigDefaults,
Service: service.ConfigDefaults, Service: service.ConfigDefaults,
Smb: smb.ConfigDefaults, SMB: smb.ConfigDefaults,
Smtp: smtp.ConfigDefaults, SMBClient: smbclient.ConfigDefaults,
SMTP: smtp.ConfigDefaults,
System: system.ConfigDefaults, System: system.ConfigDefaults,
TeradiciPcoip: teradici_pcoip.ConfigDefaults, TeradiciPcoip: teradici_pcoip.ConfigDefaults,
Tcp: tcp.ConfigDefaults, TCP: tcp.ConfigDefaults,
TerminalServices: terminal_services.ConfigDefaults, TerminalServices: terminal_services.ConfigDefaults,
Textfile: textfile.ConfigDefaults, Textfile: textfile.ConfigDefaults,
Thermalzone: thermalzone.ConfigDefaults, Thermalzone: thermalzone.ConfigDefaults,

View File

@@ -3,7 +3,6 @@
package container package container
import ( import (
"fmt"
"strings" "strings"
"github.com/Microsoft/hcsshim" "github.com/Microsoft/hcsshim"
@@ -13,6 +12,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "container" const Name = "container"
@@ -21,167 +21,174 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for containers metrics // A Collector is a Prometheus Collector for containers metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
// Presence // Presence
ContainerAvailable *prometheus.Desc containerAvailable *prometheus.Desc
// Number of containers // Number of containers
ContainersCount *prometheus.Desc containersCount *prometheus.Desc
// memory
UsageCommitBytes *prometheus.Desc // Memory
UsageCommitPeakBytes *prometheus.Desc usageCommitBytes *prometheus.Desc
UsagePrivateWorkingSetBytes *prometheus.Desc usageCommitPeakBytes *prometheus.Desc
usagePrivateWorkingSetBytes *prometheus.Desc
// CPU // CPU
RuntimeTotal *prometheus.Desc runtimeTotal *prometheus.Desc
RuntimeUser *prometheus.Desc runtimeUser *prometheus.Desc
RuntimeKernel *prometheus.Desc runtimeKernel *prometheus.Desc
// Network // Network
BytesReceived *prometheus.Desc bytesReceived *prometheus.Desc
BytesSent *prometheus.Desc bytesSent *prometheus.Desc
PacketsReceived *prometheus.Desc packetsReceived *prometheus.Desc
PacketsSent *prometheus.Desc packetsSent *prometheus.Desc
DroppedPacketsIncoming *prometheus.Desc droppedPacketsIncoming *prometheus.Desc
DroppedPacketsOutgoing *prometheus.Desc droppedPacketsOutgoing *prometheus.Desc
// Storage // Storage
ReadCountNormalized *prometheus.Desc readCountNormalized *prometheus.Desc
ReadSizeBytes *prometheus.Desc readSizeBytes *prometheus.Desc
WriteCountNormalized *prometheus.Desc writeCountNormalized *prometheus.Desc
WriteSizeBytes *prometheus.Desc writeSizeBytes *prometheus.Desc
} }
// New constructs a new collector // New constructs a new Collector.
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.ContainerAvailable = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.containerAvailable = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "available"), prometheus.BuildFQName(types.Namespace, Name, "available"),
"Available", "Available",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.ContainersCount = prometheus.NewDesc( c.containersCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "count"), prometheus.BuildFQName(types.Namespace, Name, "count"),
"Number of containers", "Number of containers",
nil, nil,
nil, nil,
) )
c.UsageCommitBytes = prometheus.NewDesc( c.usageCommitBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_bytes"), prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_bytes"),
"Memory Usage Commit Bytes", "Memory Usage Commit Bytes",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.UsageCommitPeakBytes = prometheus.NewDesc( c.usageCommitPeakBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_peak_bytes"), prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_peak_bytes"),
"Memory Usage Commit Peak Bytes", "Memory Usage Commit Peak Bytes",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.UsagePrivateWorkingSetBytes = prometheus.NewDesc( c.usagePrivateWorkingSetBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "memory_usage_private_working_set_bytes"), prometheus.BuildFQName(types.Namespace, Name, "memory_usage_private_working_set_bytes"),
"Memory Usage Private Working Set Bytes", "Memory Usage Private Working Set Bytes",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.RuntimeTotal = prometheus.NewDesc( c.runtimeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_total"),
"Total Run time in Seconds", "Total Run time in Seconds",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.RuntimeUser = prometheus.NewDesc( c.runtimeUser = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_usermode"), prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_usermode"),
"Run Time in User mode in Seconds", "Run Time in User mode in Seconds",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.RuntimeKernel = prometheus.NewDesc( c.runtimeKernel = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_kernelmode"), prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_kernelmode"),
"Run time in Kernel mode in Seconds", "Run time in Kernel mode in Seconds",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.BytesReceived = prometheus.NewDesc( c.bytesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_receive_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "network_receive_bytes_total"),
"Bytes Received on Interface", "Bytes Received on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "interface"},
nil, nil,
) )
c.BytesSent = prometheus.NewDesc( c.bytesSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_transmit_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "network_transmit_bytes_total"),
"Bytes Sent on Interface", "Bytes Sent on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "interface"},
nil, nil,
) )
c.PacketsReceived = prometheus.NewDesc( c.packetsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_total"), prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_total"),
"Packets Received on Interface", "Packets Received on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "interface"},
nil, nil,
) )
c.PacketsSent = prometheus.NewDesc( c.packetsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_total"), prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_total"),
"Packets Sent on Interface", "Packets Sent on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "interface"},
nil, nil,
) )
c.DroppedPacketsIncoming = prometheus.NewDesc( c.droppedPacketsIncoming = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_dropped_total"), prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_dropped_total"),
"Dropped Incoming Packets on Interface", "Dropped Incoming Packets on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "interface"},
nil, nil,
) )
c.DroppedPacketsOutgoing = prometheus.NewDesc( c.droppedPacketsOutgoing = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_dropped_total"), prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_dropped_total"),
"Dropped Outgoing Packets on Interface", "Dropped Outgoing Packets on Interface",
[]string{"container_id", "interface"}, []string{"container_id", "interface"},
nil, nil,
) )
c.ReadCountNormalized = prometheus.NewDesc( c.readCountNormalized = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_read_count_normalized_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_read_count_normalized_total"),
"Read Count Normalized", "Read Count Normalized",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.ReadSizeBytes = prometheus.NewDesc( c.readSizeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_read_size_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_read_size_bytes_total"),
"Read Size Bytes", "Read Size Bytes",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.WriteCountNormalized = prometheus.NewDesc( c.writeCountNormalized = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_write_count_normalized_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_write_count_normalized_total"),
"Write Count Normalized", "Write Count Normalized",
[]string{"container_id"}, []string{"container_id"},
nil, nil,
) )
c.WriteSizeBytes = prometheus.NewDesc( c.writeSizeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "storage_write_size_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "storage_write_size_bytes_total"),
"Write Size Bytes", "Write Size Bytes",
[]string{"container_id"}, []string{"container_id"},
@@ -192,39 +199,40 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting collector metrics", "desc", desc, "err", err) if err := c.collect(logger, ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting collector metrics", "err", err)
return err return err
} }
return nil return nil
} }
// containerClose closes the container resource // containerClose closes the container resource.
func (c *collector) containerClose(container hcsshim.Container) { func (c *Collector) containerClose(logger log.Logger, container hcsshim.Container) {
err := container.Close() err := container.Close()
if err != nil { if err != nil {
_ = level.Error(c.logger).Log("err", err) _ = level.Error(logger).Log("err", err)
} }
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(logger log.Logger, ch chan<- prometheus.Metric) error {
// Types Container is passed to get the containers compute systems only // Types Container is passed to get the containers compute systems only
containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}}) containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}})
if err != nil { if err != nil {
_ = level.Error(c.logger).Log("msg", "Err in Getting containers", "err", err) _ = level.Error(logger).Log("msg", "Err in Getting containers", "err", err)
return nil, err return err
} }
count := len(containers) count := len(containers)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ContainersCount, c.containersCount,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(count), float64(count),
) )
if count == 0 { if count == 0 {
return nil, nil return nil
} }
containerPrefixes := make(map[string]string) containerPrefixes := make(map[string]string)
@@ -234,16 +242,16 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
func() { func() {
container, err := hcsshim.OpenContainer(containerDetails.ID) container, err := hcsshim.OpenContainer(containerDetails.ID)
if container != nil { if container != nil {
defer c.containerClose(container) defer c.containerClose(logger, container)
} }
if err != nil { if err != nil {
_ = level.Error(c.logger).Log("msg", "err in opening container", "containerId", containerDetails.ID, "err", err) _ = level.Error(logger).Log("msg", "err in opening container", "containerId", containerDetails.ID, "err", err)
return return
} }
cstats, err := container.Statistics() cstats, err := container.Statistics()
if err != nil { if err != nil {
_ = level.Error(c.logger).Log("msg", "err in fetching container Statistics", "containerId", containerDetails.ID, "err", err) _ = level.Error(logger).Log("msg", "err in fetching container Statistics", "containerId", containerDetails.ID, "err", err)
return return
} }
@@ -251,67 +259,67 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
containerPrefixes[containerDetails.ID] = containerIdWithPrefix containerPrefixes[containerDetails.ID] = containerIdWithPrefix
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ContainerAvailable, c.containerAvailable,
prometheus.CounterValue, prometheus.CounterValue,
1, 1,
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.UsageCommitBytes, c.usageCommitBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(cstats.Memory.UsageCommitBytes), float64(cstats.Memory.UsageCommitBytes),
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.UsageCommitPeakBytes, c.usageCommitPeakBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(cstats.Memory.UsageCommitPeakBytes), float64(cstats.Memory.UsageCommitPeakBytes),
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.UsagePrivateWorkingSetBytes, c.usagePrivateWorkingSetBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(cstats.Memory.UsagePrivateWorkingSetBytes), float64(cstats.Memory.UsagePrivateWorkingSetBytes),
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RuntimeTotal, c.runtimeTotal,
prometheus.CounterValue, prometheus.CounterValue,
float64(cstats.Processor.TotalRuntime100ns)*perflib.TicksToSecondScaleFactor, float64(cstats.Processor.TotalRuntime100ns)*perflib.TicksToSecondScaleFactor,
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RuntimeUser, c.runtimeUser,
prometheus.CounterValue, prometheus.CounterValue,
float64(cstats.Processor.RuntimeUser100ns)*perflib.TicksToSecondScaleFactor, float64(cstats.Processor.RuntimeUser100ns)*perflib.TicksToSecondScaleFactor,
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RuntimeKernel, c.runtimeKernel,
prometheus.CounterValue, prometheus.CounterValue,
float64(cstats.Processor.RuntimeKernel100ns)*perflib.TicksToSecondScaleFactor, float64(cstats.Processor.RuntimeKernel100ns)*perflib.TicksToSecondScaleFactor,
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadCountNormalized, c.readCountNormalized,
prometheus.CounterValue, prometheus.CounterValue,
float64(cstats.Storage.ReadCountNormalized), float64(cstats.Storage.ReadCountNormalized),
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadSizeBytes, c.readSizeBytes,
prometheus.CounterValue, prometheus.CounterValue,
float64(cstats.Storage.ReadSizeBytes), float64(cstats.Storage.ReadSizeBytes),
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WriteCountNormalized, c.writeCountNormalized,
prometheus.CounterValue, prometheus.CounterValue,
float64(cstats.Storage.WriteCountNormalized), float64(cstats.Storage.WriteCountNormalized),
containerIdWithPrefix, containerIdWithPrefix,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WriteSizeBytes, c.writeSizeBytes,
prometheus.CounterValue, prometheus.CounterValue,
float64(cstats.Storage.WriteSizeBytes), float64(cstats.Storage.WriteSizeBytes),
containerIdWithPrefix, containerIdWithPrefix,
@@ -321,19 +329,19 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
hnsEndpoints, err := hcsshim.HNSListEndpointRequest() hnsEndpoints, err := hcsshim.HNSListEndpointRequest()
if err != nil { if err != nil {
_ = level.Warn(c.logger).Log("msg", "Failed to collect network stats for containers") _ = level.Warn(logger).Log("msg", "Failed to collect network stats for containers")
return nil, nil return err
} }
if len(hnsEndpoints) == 0 { if len(hnsEndpoints) == 0 {
_ = level.Info(c.logger).Log("msg", fmt.Sprintf("No network stats for containers to collect")) _ = level.Info(logger).Log("msg", "No network stats for containers to collect")
return nil, nil return nil
} }
for _, endpoint := range hnsEndpoints { for _, endpoint := range hnsEndpoints {
endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id) endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id)
if err != nil { if err != nil {
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for interface %s", endpoint.Id), "err", err) _ = level.Warn(logger).Log("msg", "Failed to collect network stats for interface "+endpoint.Id, "err", err)
continue continue
} }
@@ -342,43 +350,43 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
endpointId := strings.ToUpper(endpoint.Id) endpointId := strings.ToUpper(endpoint.Id)
if !ok { if !ok {
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for container %s", containerId)) _ = level.Warn(logger).Log("msg", "Failed to collect network stats for container "+containerId)
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesReceived, c.bytesReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.BytesReceived), float64(endpointStats.BytesReceived),
containerIdWithPrefix, endpointId, containerIdWithPrefix, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesSent, c.bytesSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.BytesSent), float64(endpointStats.BytesSent),
containerIdWithPrefix, endpointId, containerIdWithPrefix, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsReceived, c.packetsReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.PacketsReceived), float64(endpointStats.PacketsReceived),
containerIdWithPrefix, endpointId, containerIdWithPrefix, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsSent, c.packetsSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.PacketsSent), float64(endpointStats.PacketsSent),
containerIdWithPrefix, endpointId, containerIdWithPrefix, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DroppedPacketsIncoming, c.droppedPacketsIncoming,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.DroppedPacketsIncoming), float64(endpointStats.DroppedPacketsIncoming),
containerIdWithPrefix, endpointId, containerIdWithPrefix, endpointId,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DroppedPacketsOutgoing, c.droppedPacketsOutgoing,
prometheus.CounterValue, prometheus.CounterValue,
float64(endpointStats.DroppedPacketsOutgoing), float64(endpointStats.DroppedPacketsOutgoing),
containerIdWithPrefix, endpointId, containerIdWithPrefix, endpointId,
@@ -386,7 +394,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
} }
} }
return nil, nil return nil
} }
func getContainerIdWithPrefix(containerDetails hcsshim.ContainerProperties) string { func getContainerIdWithPrefix(containerDetails hcsshim.ContainerProperties) string {

View File

@@ -11,6 +11,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/winversion" "github.com/prometheus-community/windows_exporter/pkg/winversion"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "cpu" const Name = "cpu"
@@ -19,71 +20,75 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type collector struct { type Collector struct {
logger log.Logger config Config
CStateSecondsTotal *prometheus.Desc cStateSecondsTotal *prometheus.Desc
TimeTotal *prometheus.Desc timeTotal *prometheus.Desc
InterruptsTotal *prometheus.Desc interruptsTotal *prometheus.Desc
DPCsTotal *prometheus.Desc dpcsTotal *prometheus.Desc
clockInterruptsTotal *prometheus.Desc
ClockInterruptsTotal *prometheus.Desc idleBreakEventsTotal *prometheus.Desc
IdleBreakEventsTotal *prometheus.Desc parkingStatus *prometheus.Desc
ParkingStatus *prometheus.Desc processorFrequencyMHz *prometheus.Desc
ProcessorFrequencyMHz *prometheus.Desc processorPerformance *prometheus.Desc
ProcessorMaxFrequencyMHz *prometheus.Desc processorMPerf *prometheus.Desc
ProcessorPerformance *prometheus.Desc processorRTC *prometheus.Desc
ProcessorMPerf *prometheus.Desc processorUtility *prometheus.Desc
ProcessorRTC *prometheus.Desc processorPrivilegedUtility *prometheus.Desc
ProcessorUtility *prometheus.Desc
ProcessorPrivUtility *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name) if winversion.WindowsVersionFloat() > 6.05 {
}
func (c *collector) GetPerfCounter() ([]string, error) {
if winversion.WindowsVersionFloat > 6.05 {
return []string{"Processor Information"}, nil return []string{"Processor Information"}, nil
} }
return []string{"Processor"}, nil return []string{"Processor"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.CStateSecondsTotal = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.cStateSecondsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"),
"Time spent in low-power idle state", "Time spent in low-power idle state",
[]string{"core", "state"}, []string{"core", "state"},
nil, nil,
) )
c.TimeTotal = prometheus.NewDesc( c.timeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "time_total"), prometheus.BuildFQName(types.Namespace, Name, "time_total"),
"Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)", "Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)",
[]string{"core", "mode"}, []string{"core", "mode"},
nil, nil,
) )
c.InterruptsTotal = prometheus.NewDesc( c.interruptsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"), prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"),
"Total number of received and serviced hardware interrupts", "Total number of received and serviced hardware interrupts",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.DPCsTotal = prometheus.NewDesc( c.dpcsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"), prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"),
"Total number of received and serviced deferred procedure calls (DPCs)", "Total number of received and serviced deferred procedure calls (DPCs)",
[]string{"core"}, []string{"core"},
@@ -96,85 +101,85 @@ func (c *collector) Build() error {
// are added in later versions, so we aren't guaranteed to get all of // are added in later versions, so we aren't guaranteed to get all of
// them). // them).
// Value 6.05 was selected to split between Windows versions. // Value 6.05 was selected to split between Windows versions.
if winversion.WindowsVersionFloat < 6.05 { if winversion.WindowsVersionFloat() < 6.05 {
return nil return nil
} }
c.CStateSecondsTotal = prometheus.NewDesc( c.cStateSecondsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"),
"Time spent in low-power idle state", "Time spent in low-power idle state",
[]string{"core", "state"}, []string{"core", "state"},
nil, nil,
) )
c.TimeTotal = prometheus.NewDesc( c.timeTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "time_total"), prometheus.BuildFQName(types.Namespace, Name, "time_total"),
"Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)", "Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)",
[]string{"core", "mode"}, []string{"core", "mode"},
nil, nil,
) )
c.InterruptsTotal = prometheus.NewDesc( c.interruptsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"), prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"),
"Total number of received and serviced hardware interrupts", "Total number of received and serviced hardware interrupts",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.DPCsTotal = prometheus.NewDesc( c.dpcsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"), prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"),
"Total number of received and serviced deferred procedure calls (DPCs)", "Total number of received and serviced deferred procedure calls (DPCs)",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ClockInterruptsTotal = prometheus.NewDesc( c.clockInterruptsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "clock_interrupts_total"), prometheus.BuildFQName(types.Namespace, Name, "clock_interrupts_total"),
"Total number of received and serviced clock tick interrupts", "Total number of received and serviced clock tick interrupts",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.IdleBreakEventsTotal = prometheus.NewDesc( c.idleBreakEventsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "idle_break_events_total"), prometheus.BuildFQName(types.Namespace, Name, "idle_break_events_total"),
"Total number of time processor was woken from idle", "Total number of time processor was woken from idle",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ParkingStatus = prometheus.NewDesc( c.parkingStatus = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "parking_status"), prometheus.BuildFQName(types.Namespace, Name, "parking_status"),
"Parking Status represents whether a processor is parked or not", "Parking Status represents whether a processor is parked or not",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ProcessorFrequencyMHz = prometheus.NewDesc( c.processorFrequencyMHz = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "core_frequency_mhz"), prometheus.BuildFQName(types.Namespace, Name, "core_frequency_mhz"),
"Core frequency in megahertz", "Core frequency in megahertz",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ProcessorPerformance = prometheus.NewDesc( c.processorPerformance = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "processor_performance_total"), prometheus.BuildFQName(types.Namespace, Name, "processor_performance_total"),
"Processor Performance is the average performance of the processor while it is executing instructions, as a percentage of the nominal performance of the processor. On some processors, Processor Performance may exceed 100%", "Processor Performance is the average performance of the processor while it is executing instructions, as a percentage of the nominal performance of the processor. On some processors, Processor Performance may exceed 100%",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ProcessorMPerf = prometheus.NewDesc( c.processorMPerf = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "processor_mperf_total"), prometheus.BuildFQName(types.Namespace, Name, "processor_mperf_total"),
"Processor MPerf is the number of TSC ticks incremented while executing instructions", "Processor MPerf is the number of TSC ticks incremented while executing instructions",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ProcessorRTC = prometheus.NewDesc( c.processorRTC = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "processor_rtc_total"), prometheus.BuildFQName(types.Namespace, Name, "processor_rtc_total"),
"Processor RTC represents the number of RTC ticks made since the system booted. It should consistently be 64e6, and can be used to properly derive Processor Utility Rate", "Processor RTC represents the number of RTC ticks made since the system booted. It should consistently be 64e6, and can be used to properly derive Processor Utility Rate",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ProcessorUtility = prometheus.NewDesc( c.processorUtility = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "processor_utility_total"), prometheus.BuildFQName(types.Namespace, Name, "processor_utility_total"),
"Processor Utility represents is the amount of time the core spends executing instructions", "Processor Utility represents is the amount of time the core spends executing instructions",
[]string{"core"}, []string{"core"},
nil, nil,
) )
c.ProcessorPrivUtility = prometheus.NewDesc( c.processorPrivilegedUtility = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "processor_privileged_utility_total"), prometheus.BuildFQName(types.Namespace, Name, "processor_privileged_utility_total"),
"Processor Privilieged Utility represents is the amount of time the core has spent executing instructions inside the kernel", "Processor Privileged Utility represents is the amount of time the core has spent executing instructions inside the kernel",
[]string{"core"}, []string{"core"},
nil, nil,
) )
@@ -182,12 +187,13 @@ func (c *collector) Build() error {
return nil return nil
} }
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if winversion.WindowsVersionFloat > 6.05 { logger = log.With(logger, "collector", Name)
return c.CollectFull(ctx, ch) if winversion.WindowsVersionFloat() > 6.05 {
return c.CollectFull(ctx, logger, ch)
} }
return c.CollectBasic(ctx, ch) return c.CollectBasic(ctx, logger, ch)
} }
type perflibProcessor struct { type perflibProcessor struct {
@@ -198,9 +204,9 @@ type perflibProcessor struct {
DPCRate float64 `perflib:"DPC Rate"` DPCRate float64 `perflib:"DPC Rate"`
DPCsQueued float64 `perflib:"DPCs Queued/sec"` DPCsQueued float64 `perflib:"DPCs Queued/sec"`
Interrupts float64 `perflib:"Interrupts/sec"` Interrupts float64 `perflib:"Interrupts/sec"`
PercentC2Time float64 `perflib:"% C1 Time"` PercentC1Time float64 `perflib:"% C1 Time"`
PercentC3Time float64 `perflib:"% C2 Time"` PercentC2Time float64 `perflib:"% C2 Time"`
PercentC1Time float64 `perflib:"% C3 Time"` PercentC3Time float64 `perflib:"% C3 Time"`
PercentDPCTime float64 `perflib:"% DPC Time"` PercentDPCTime float64 `perflib:"% DPC Time"`
PercentIdleTime float64 `perflib:"% Idle Time"` PercentIdleTime float64 `perflib:"% Idle Time"`
PercentInterruptTime float64 `perflib:"% Interrupt Time"` PercentInterruptTime float64 `perflib:"% Interrupt Time"`
@@ -209,9 +215,10 @@ type perflibProcessor struct {
PercentUserTime float64 `perflib:"% User Time"` PercentUserTime float64 `perflib:"% User Time"`
} }
func (c *collector) CollectBasic(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) CollectBasic(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
data := make([]perflibProcessor, 0) data := make([]perflibProcessor, 0)
err := perflib.UnmarshalObject(ctx.PerfObjects["Processor"], &data, c.logger) err := perflib.UnmarshalObject(ctx.PerfObjects["Processor"], &data, logger)
if err != nil { if err != nil {
return err return err
} }
@@ -223,63 +230,63 @@ func (c *collector) CollectBasic(ctx *types.ScrapeContext, ch chan<- prometheus.
core := cpu.Name core := cpu.Name
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentC1Time, cpu.PercentC1Time,
core, "c1", core, "c1",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentC2Time, cpu.PercentC2Time,
core, "c2", core, "c2",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentC3Time, cpu.PercentC3Time,
core, "c3", core, "c3",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentIdleTime, cpu.PercentIdleTime,
core, "idle", core, "idle",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentInterruptTime, cpu.PercentInterruptTime,
core, "interrupt", core, "interrupt",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentDPCTime, cpu.PercentDPCTime,
core, "dpc", core, "dpc",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentPrivilegedTime, cpu.PercentPrivilegedTime,
core, "privileged", core, "privileged",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PercentUserTime, cpu.PercentUserTime,
core, "user", core, "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.InterruptsTotal, c.interruptsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.Interrupts, cpu.Interrupts,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DPCsTotal, c.dpcsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.DPCsQueued, cpu.DPCsQueued,
core, core,
@@ -318,9 +325,10 @@ type perflibProcessorInformation struct {
UserTimeSeconds float64 `perflib:"% User Time"` UserTimeSeconds float64 `perflib:"% User Time"`
} }
func (c *collector) CollectFull(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) CollectFull(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
data := make([]perflibProcessorInformation, 0) data := make([]perflibProcessorInformation, 0)
err := perflib.UnmarshalObject(ctx.PerfObjects["Processor Information"], &data, c.logger) err := perflib.UnmarshalObject(ctx.PerfObjects["Processor Information"], &data, logger)
if err != nil { if err != nil {
return err return err
} }
@@ -332,119 +340,119 @@ func (c *collector) CollectFull(ctx *types.ScrapeContext, ch chan<- prometheus.M
core := cpu.Name core := cpu.Name
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.C1TimeSeconds, cpu.C1TimeSeconds,
core, "c1", core, "c1",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.C2TimeSeconds, cpu.C2TimeSeconds,
core, "c2", core, "c2",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal, c.cStateSecondsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.C3TimeSeconds, cpu.C3TimeSeconds,
core, "c3", core, "c3",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.IdleTimeSeconds, cpu.IdleTimeSeconds,
core, "idle", core, "idle",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.InterruptTimeSeconds, cpu.InterruptTimeSeconds,
core, "interrupt", core, "interrupt",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.DPCTimeSeconds, cpu.DPCTimeSeconds,
core, "dpc", core, "dpc",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PrivilegedTimeSeconds, cpu.PrivilegedTimeSeconds,
core, "privileged", core, "privileged",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeTotal, c.timeTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.UserTimeSeconds, cpu.UserTimeSeconds,
core, "user", core, "user",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.InterruptsTotal, c.interruptsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.InterruptsTotal, cpu.InterruptsTotal,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DPCsTotal, c.dpcsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.DPCsQueuedTotal, cpu.DPCsQueuedTotal,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ClockInterruptsTotal, c.clockInterruptsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.ClockInterruptsTotal, cpu.ClockInterruptsTotal,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.IdleBreakEventsTotal, c.idleBreakEventsTotal,
prometheus.CounterValue, prometheus.CounterValue,
cpu.IdleBreakEventsTotal, cpu.IdleBreakEventsTotal,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ParkingStatus, c.parkingStatus,
prometheus.GaugeValue, prometheus.GaugeValue,
cpu.ParkingStatus, cpu.ParkingStatus,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ProcessorFrequencyMHz, c.processorFrequencyMHz,
prometheus.GaugeValue, prometheus.GaugeValue,
cpu.ProcessorFrequencyMHz, cpu.ProcessorFrequencyMHz,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ProcessorPerformance, c.processorPerformance,
prometheus.CounterValue, prometheus.CounterValue,
cpu.ProcessorPerformance, cpu.ProcessorPerformance,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ProcessorMPerf, c.processorMPerf,
prometheus.CounterValue, prometheus.CounterValue,
cpu.ProcessorMPerf, cpu.ProcessorMPerf,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ProcessorRTC, c.processorRTC,
prometheus.CounterValue, prometheus.CounterValue,
cpu.ProcessorRTC, cpu.ProcessorRTC,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ProcessorUtility, c.processorUtility,
prometheus.CounterValue, prometheus.CounterValue,
cpu.ProcessorUtilityRate, cpu.ProcessorUtilityRate,
core, core,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ProcessorPrivUtility, c.processorPrivilegedUtility,
prometheus.CounterValue, prometheus.CounterValue,
cpu.PrivilegedUtilitySeconds, cpu.PrivilegedUtilitySeconds,
core, core,

View File

@@ -11,115 +11,217 @@ import (
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const ( const (
Name = "cpu_info" Name = "cpu_info"
// If you are adding additional labels to the metric, make sure that they get added in here as well. See below for explanation.
win32ProcessorQuery = "SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name FROM Win32_Processor"
) )
type Config struct{} type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for a few WMI metrics in Win32_Processor // A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor.
type collector struct { type Collector struct {
logger log.Logger config Config
CpuInfo *prometheus.Desc wmiClient *wmi.Client
cpuInfo *prometheus.Desc
cpuCoreCount *prometheus.Desc
cpuEnabledCoreCount *prometheus.Desc
cpuLogicalProcessorsCount *prometheus.Desc
cpuThreadCount *prometheus.Desc
cpuL2CacheSize *prometheus.Desc
cpuL3CacheSize *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.CpuInfo = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.cpuInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, "", Name), prometheus.BuildFQName(types.Namespace, "", Name),
"Labeled CPU information as provided provided by Win32_Processor", "Labelled CPU information as provided by Win32_Processor",
[]string{ []string{
"architecture", "architecture",
"device_id", "device_id",
"description", "description",
"family", "family",
"l2_cache_size",
"l3_cache_size",
"name", "name",
}, },
nil, nil,
) )
c.cpuThreadCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "thread"),
"Number of threads per CPU",
[]string{
"device_id",
},
nil,
)
c.cpuCoreCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "core"),
"Number of cores per CPU",
[]string{
"device_id",
},
nil,
)
c.cpuEnabledCoreCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "enabled_core"),
"Number of enabled cores per CPU",
[]string{
"device_id",
},
nil,
)
c.cpuLogicalProcessorsCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "logical_processor"),
"Number of logical processors per CPU",
[]string{
"device_id",
},
nil,
)
c.cpuL2CacheSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "l2_cache_size"),
"Size of L2 cache per CPU",
[]string{
"device_id",
},
nil,
)
c.cpuL3CacheSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "l3_cache_size"),
"Size of L3 cache per CPU",
[]string{
"device_id",
},
nil,
)
return nil return nil
} }
type win32_Processor struct { type win32Processor struct {
Architecture uint32 Architecture uint32
DeviceID string DeviceID string
Description string Description string
Family uint16 Family uint16
L2CacheSize uint32 L2CacheSize uint32
L3CacheSize uint32 L3CacheSize uint32
Name string Name string
ThreadCount uint32
NumberOfCores uint32
NumberOfEnabledCore uint32
NumberOfLogicalProcessors uint32
} }
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting cpu_info metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting cpu_info metrics", "err", err)
return err return err
} }
return nil return nil
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []win32_Processor var dst []win32Processor
// We use a static query here because the provided methods in wmi.go all issue a SELECT *; // We use a static query here because the provided methods in wmi.go all issue a SELECT *;
// This results in the time-consuming LoadPercentage field being read which seems to measure each CPU // This results in the time-consuming LoadPercentage field being read which seems to measure each CPU
// serially over a 1 second interval, so the scrape time is at least 1s * num_sockets // serially over a 1 second interval, so the scrape time is at least 1s * num_sockets
if err := wmi.Query(win32ProcessorQuery, &dst); err != nil { if err := c.wmiClient.Query("SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name, ThreadCount, NumberOfCores, NumberOfEnabledCore, NumberOfLogicalProcessors FROM Win32_Processor", &dst); err != nil {
return nil, err return err
} }
if len(dst) == 0 { if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set") return errors.New("WMI query returned empty result set")
} }
// Some CPUs end up exposing trailing spaces for certain strings, so clean them up // Some CPUs end up exposing trailing spaces for certain strings, so clean them up
for _, processor := range dst { for _, processor := range dst {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CpuInfo, c.cpuInfo,
prometheus.GaugeValue, prometheus.GaugeValue,
1.0, 1.0,
strconv.Itoa(int(processor.Architecture)), strconv.Itoa(int(processor.Architecture)),
strings.TrimRight(processor.DeviceID, " "), strings.TrimRight(processor.DeviceID, " "),
strings.TrimRight(processor.Description, " "), strings.TrimRight(processor.Description, " "),
strconv.Itoa(int(processor.Family)), strconv.Itoa(int(processor.Family)),
strconv.Itoa(int(processor.L2CacheSize)),
strconv.Itoa(int(processor.L3CacheSize)),
strings.TrimRight(processor.Name, " "), strings.TrimRight(processor.Name, " "),
) )
ch <- prometheus.MustNewConstMetric(
c.cpuCoreCount,
prometheus.GaugeValue,
float64(processor.NumberOfCores),
strings.TrimRight(processor.DeviceID, " "),
)
ch <- prometheus.MustNewConstMetric(
c.cpuEnabledCoreCount,
prometheus.GaugeValue,
float64(processor.NumberOfEnabledCore),
strings.TrimRight(processor.DeviceID, " "),
)
ch <- prometheus.MustNewConstMetric(
c.cpuLogicalProcessorsCount,
prometheus.GaugeValue,
float64(processor.NumberOfLogicalProcessors),
strings.TrimRight(processor.DeviceID, " "),
)
ch <- prometheus.MustNewConstMetric(
c.cpuThreadCount,
prometheus.GaugeValue,
float64(processor.ThreadCount),
strings.TrimRight(processor.DeviceID, " "),
)
ch <- prometheus.MustNewConstMetric(
c.cpuL2CacheSize,
prometheus.GaugeValue,
float64(processor.L2CacheSize),
strings.TrimRight(processor.DeviceID, " "),
)
ch <- prometheus.MustNewConstMetric(
c.cpuL3CacheSize,
prometheus.GaugeValue,
float64(processor.L3CacheSize),
strings.TrimRight(processor.DeviceID, " "),
)
} }
return nil, nil return nil
} }

View File

@@ -0,0 +1,12 @@
package cpu_info_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/pkg/collector/cpu_info"
"github.com/prometheus-community/windows_exporter/pkg/testutils"
)
func BenchmarkCollector(b *testing.B) {
testutils.FuncBenchmarkCollector(b, cpu_info.Name, cpu_info.NewWithFlags)
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/headers/sysinfoapi" "github.com/prometheus-community/windows_exporter/pkg/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "cs" const Name = "cs"
@@ -17,53 +18,59 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI metrics // A Collector is a Prometheus Collector for WMI metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
PhysicalMemoryBytes *prometheus.Desc physicalMemoryBytes *prometheus.Desc
LogicalProcessors *prometheus.Desc logicalProcessors *prometheus.Desc
Hostname *prometheus.Desc hostname *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.LogicalProcessors = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.logicalProcessors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "logical_processors"), prometheus.BuildFQName(types.Namespace, Name, "logical_processors"),
"ComputerSystem.NumberOfLogicalProcessors", "ComputerSystem.NumberOfLogicalProcessors",
nil, nil,
nil, nil,
) )
c.PhysicalMemoryBytes = prometheus.NewDesc( c.physicalMemoryBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "physical_memory_bytes"), prometheus.BuildFQName(types.Namespace, Name, "physical_memory_bytes"),
"ComputerSystem.TotalPhysicalMemory", "ComputerSystem.TotalPhysicalMemory",
nil, nil,
nil, nil,
) )
c.Hostname = prometheus.NewDesc( c.hostname = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "hostname"), prometheus.BuildFQName(types.Namespace, Name, "hostname"),
"Labeled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain", "Labelled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain",
[]string{ []string{
"hostname", "hostname",
"domain", "domain",
@@ -76,51 +83,52 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting cs metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting cs metrics", "err", err)
return err return err
} }
return nil return nil
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
// Get systeminfo for number of processors // Get systeminfo for number of processors
systemInfo := sysinfoapi.GetSystemInfo() systemInfo := sysinfoapi.GetSystemInfo()
// Get memory status for physical memory // Get memory status for physical memory
mem, err := sysinfoapi.GlobalMemoryStatusEx() mem, err := sysinfoapi.GlobalMemoryStatusEx()
if err != nil { if err != nil {
return nil, err return err
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogicalProcessors, c.logicalProcessors,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(systemInfo.NumberOfProcessors), float64(systemInfo.NumberOfProcessors),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PhysicalMemoryBytes, c.physicalMemoryBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(mem.TotalPhys), float64(mem.TotalPhys),
) )
hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname) hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname)
if err != nil { if err != nil {
return nil, err return err
} }
domain, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSDomain) domain, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSDomain)
if err != nil { if err != nil {
return nil, err return err
} }
fqdn, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSFullyQualified) fqdn, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSFullyQualified)
if err != nil { if err != nil {
return nil, err return err
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Hostname, c.hostname,
prometheus.GaugeValue, prometheus.GaugeValue,
1.0, 1.0,
hostname, hostname,
@@ -128,5 +136,5 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
fqdn, fqdn,
) )
return nil, nil return nil
} }

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "dhcp" const Name = "dhcp"
@@ -16,205 +17,211 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector perflib DHCP metrics // A Collector is a Prometheus Collector perflib DHCP metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
PacketsReceivedTotal *prometheus.Desc acksTotal *prometheus.Desc
DuplicatesDroppedTotal *prometheus.Desc activeQueueLength *prometheus.Desc
PacketsExpiredTotal *prometheus.Desc conflictCheckQueueLength *prometheus.Desc
ActiveQueueLength *prometheus.Desc declinesTotal *prometheus.Desc
ConflictCheckQueueLength *prometheus.Desc deniedDueToMatch *prometheus.Desc
DiscoversTotal *prometheus.Desc deniedDueToNonMatch *prometheus.Desc
OffersTotal *prometheus.Desc discoversTotal *prometheus.Desc
RequestsTotal *prometheus.Desc duplicatesDroppedTotal *prometheus.Desc
InformsTotal *prometheus.Desc failoverBndackReceivedTotal *prometheus.Desc
AcksTotal *prometheus.Desc failoverBndackSentTotal *prometheus.Desc
NacksTotal *prometheus.Desc failoverBndupdDropped *prometheus.Desc
DeclinesTotal *prometheus.Desc failoverBndupdPendingOutboundQueue *prometheus.Desc
ReleasesTotal *prometheus.Desc failoverBndupdReceivedTotal *prometheus.Desc
OfferQueueLength *prometheus.Desc failoverBndupdSentTotal *prometheus.Desc
DeniedDueToMatch *prometheus.Desc failoverTransitionsCommunicationInterruptedState *prometheus.Desc
DeniedDueToNonMatch *prometheus.Desc failoverTransitionsPartnerDownState *prometheus.Desc
FailoverBndupdSentTotal *prometheus.Desc failoverTransitionsRecoverState *prometheus.Desc
FailoverBndupdReceivedTotal *prometheus.Desc informsTotal *prometheus.Desc
FailoverBndackSentTotal *prometheus.Desc nACKsTotal *prometheus.Desc
FailoverBndackReceivedTotal *prometheus.Desc offerQueueLength *prometheus.Desc
FailoverBndupdPendingOutboundQueue *prometheus.Desc offersTotal *prometheus.Desc
FailoverTransitionsCommunicationinterruptedState *prometheus.Desc packetsExpiredTotal *prometheus.Desc
FailoverTransitionsPartnerdownState *prometheus.Desc packetsReceivedTotal *prometheus.Desc
FailoverTransitionsRecoverState *prometheus.Desc releasesTotal *prometheus.Desc
FailoverBndupdDropped *prometheus.Desc requestsTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"DHCP Server"}, nil return []string{"DHCP Server"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.PacketsReceivedTotal = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.packetsReceivedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_received_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_received_total"),
"Total number of packets received by the DHCP server (PacketsReceivedTotal)", "Total number of packets received by the DHCP server (PacketsReceivedTotal)",
nil, nil,
nil, nil,
) )
c.DuplicatesDroppedTotal = prometheus.NewDesc( c.duplicatesDroppedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "duplicates_dropped_total"), prometheus.BuildFQName(types.Namespace, Name, "duplicates_dropped_total"),
"Total number of duplicate packets received by the DHCP server (DuplicatesDroppedTotal)", "Total number of duplicate packets received by the DHCP server (DuplicatesDroppedTotal)",
nil, nil,
nil, nil,
) )
c.PacketsExpiredTotal = prometheus.NewDesc( c.packetsExpiredTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_expired_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_expired_total"),
"Total number of packets expired in the DHCP server message queue (PacketsExpiredTotal)", "Total number of packets expired in the DHCP server message queue (PacketsExpiredTotal)",
nil, nil,
nil, nil,
) )
c.ActiveQueueLength = prometheus.NewDesc( c.activeQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "active_queue_length"), prometheus.BuildFQName(types.Namespace, Name, "active_queue_length"),
"Number of packets in the processing queue of the DHCP server (ActiveQueueLength)", "Number of packets in the processing queue of the DHCP server (ActiveQueueLength)",
nil, nil,
nil, nil,
) )
c.ConflictCheckQueueLength = prometheus.NewDesc( c.conflictCheckQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "conflict_check_queue_length"), prometheus.BuildFQName(types.Namespace, Name, "conflict_check_queue_length"),
"Number of packets in the DHCP server queue waiting on conflict detection (ping). (ConflictCheckQueueLength)", "Number of packets in the DHCP server queue waiting on conflict detection (ping). (ConflictCheckQueueLength)",
nil, nil,
nil, nil,
) )
c.DiscoversTotal = prometheus.NewDesc( c.discoversTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "discovers_total"), prometheus.BuildFQName(types.Namespace, Name, "discovers_total"),
"Total DHCP Discovers received by the DHCP server (DiscoversTotal)", "Total DHCP Discovers received by the DHCP server (DiscoversTotal)",
nil, nil,
nil, nil,
) )
c.OffersTotal = prometheus.NewDesc( c.offersTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "offers_total"), prometheus.BuildFQName(types.Namespace, Name, "offers_total"),
"Total DHCP Offers sent by the DHCP server (OffersTotal)", "Total DHCP Offers sent by the DHCP server (OffersTotal)",
nil, nil,
nil, nil,
) )
c.RequestsTotal = prometheus.NewDesc( c.requestsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "requests_total"), prometheus.BuildFQName(types.Namespace, Name, "requests_total"),
"Total DHCP Requests received by the DHCP server (RequestsTotal)", "Total DHCP Requests received by the DHCP server (RequestsTotal)",
nil, nil,
nil, nil,
) )
c.InformsTotal = prometheus.NewDesc( c.informsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "informs_total"), prometheus.BuildFQName(types.Namespace, Name, "informs_total"),
"Total DHCP Informs received by the DHCP server (InformsTotal)", "Total DHCP Informs received by the DHCP server (InformsTotal)",
nil, nil,
nil, nil,
) )
c.AcksTotal = prometheus.NewDesc( c.acksTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "acks_total"), prometheus.BuildFQName(types.Namespace, Name, "acks_total"),
"Total DHCP Acks sent by the DHCP server (AcksTotal)", "Total DHCP Acks sent by the DHCP server (AcksTotal)",
nil, nil,
nil, nil,
) )
c.NacksTotal = prometheus.NewDesc( c.nACKsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "nacks_total"), prometheus.BuildFQName(types.Namespace, Name, "nacks_total"),
"Total DHCP Nacks sent by the DHCP server (NacksTotal)", "Total DHCP Nacks sent by the DHCP server (NacksTotal)",
nil, nil,
nil, nil,
) )
c.DeclinesTotal = prometheus.NewDesc( c.declinesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "declines_total"), prometheus.BuildFQName(types.Namespace, Name, "declines_total"),
"Total DHCP Declines received by the DHCP server (DeclinesTotal)", "Total DHCP Declines received by the DHCP server (DeclinesTotal)",
nil, nil,
nil, nil,
) )
c.ReleasesTotal = prometheus.NewDesc( c.releasesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "releases_total"), prometheus.BuildFQName(types.Namespace, Name, "releases_total"),
"Total DHCP Releases received by the DHCP server (ReleasesTotal)", "Total DHCP Releases received by the DHCP server (ReleasesTotal)",
nil, nil,
nil, nil,
) )
c.OfferQueueLength = prometheus.NewDesc( c.offerQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "offer_queue_length"), prometheus.BuildFQName(types.Namespace, Name, "offer_queue_length"),
"Number of packets in the offer queue of the DHCP server (OfferQueueLength)", "Number of packets in the offer queue of the DHCP server (OfferQueueLength)",
nil, nil,
nil, nil,
) )
c.DeniedDueToMatch = prometheus.NewDesc( c.deniedDueToMatch = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "denied_due_to_match_total"), prometheus.BuildFQName(types.Namespace, Name, "denied_due_to_match_total"),
"Total number of DHCP requests denied, based on matches from the Deny list (DeniedDueToMatch)", "Total number of DHCP requests denied, based on matches from the Deny list (DeniedDueToMatch)",
nil, nil,
nil, nil,
) )
c.DeniedDueToNonMatch = prometheus.NewDesc( c.deniedDueToNonMatch = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "denied_due_to_nonmatch_total"), prometheus.BuildFQName(types.Namespace, Name, "denied_due_to_nonmatch_total"),
"Total number of DHCP requests denied, based on non-matches from the Allow list (DeniedDueToNonMatch)", "Total number of DHCP requests denied, based on non-matches from the Allow list (DeniedDueToNonMatch)",
nil, nil,
nil, nil,
) )
c.FailoverBndupdSentTotal = prometheus.NewDesc( c.failoverBndupdSentTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_sent_total"),
"Number of DHCP fail over Binding Update messages sent (FailoverBndupdSentTotal)", "Number of DHCP fail over Binding Update messages sent (FailoverBndupdSentTotal)",
nil, nil,
nil, nil,
) )
c.FailoverBndupdReceivedTotal = prometheus.NewDesc( c.failoverBndupdReceivedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_received_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_received_total"),
"Number of DHCP fail over Binding Update messages received (FailoverBndupdReceivedTotal)", "Number of DHCP fail over Binding Update messages received (FailoverBndupdReceivedTotal)",
nil, nil,
nil, nil,
) )
c.FailoverBndackSentTotal = prometheus.NewDesc( c.failoverBndackSentTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_bndack_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_bndack_sent_total"),
"Number of DHCP fail over Binding Ack messages sent (FailoverBndackSentTotal)", "Number of DHCP fail over Binding Ack messages sent (FailoverBndackSentTotal)",
nil, nil,
nil, nil,
) )
c.FailoverBndackReceivedTotal = prometheus.NewDesc( c.failoverBndackReceivedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_bndack_received_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_bndack_received_total"),
"Number of DHCP fail over Binding Ack messages received (FailoverBndackReceivedTotal)", "Number of DHCP fail over Binding Ack messages received (FailoverBndackReceivedTotal)",
nil, nil,
nil, nil,
) )
c.FailoverBndupdPendingOutboundQueue = prometheus.NewDesc( c.failoverBndupdPendingOutboundQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_pending_in_outbound_queue"), prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_pending_in_outbound_queue"),
"Number of pending outbound DHCP fail over Binding Update messages (FailoverBndupdPendingOutboundQueue)", "Number of pending outbound DHCP fail over Binding Update messages (FailoverBndupdPendingOutboundQueue)",
nil, nil,
nil, nil,
) )
c.FailoverTransitionsCommunicationinterruptedState = prometheus.NewDesc( c.failoverTransitionsCommunicationInterruptedState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_communicationinterrupted_state_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_communicationinterrupted_state_total"),
"Total number of transitions into COMMUNICATION INTERRUPTED state (FailoverTransitionsCommunicationinterruptedState)", "Total number of transitions into COMMUNICATION INTERRUPTED state (FailoverTransitionsCommunicationinterruptedState)",
nil, nil,
nil, nil,
) )
c.FailoverTransitionsPartnerdownState = prometheus.NewDesc( c.failoverTransitionsPartnerDownState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_partnerdown_state_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_partnerdown_state_total"),
"Total number of transitions into PARTNER DOWN state (FailoverTransitionsPartnerdownState)", "Total number of transitions into PARTNER DOWN state (FailoverTransitionsPartnerdownState)",
nil, nil,
nil, nil,
) )
c.FailoverTransitionsRecoverState = prometheus.NewDesc( c.failoverTransitionsRecoverState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_recover_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_recover_total"),
"Total number of transitions into RECOVER state (FailoverTransitionsRecoverState)", "Total number of transitions into RECOVER state (FailoverTransitionsRecoverState)",
nil, nil,
nil, nil,
) )
c.FailoverBndupdDropped = prometheus.NewDesc( c.failoverBndupdDropped = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_dropped_total"), prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_dropped_total"),
"Total number of DHCP fail over Binding Updates dropped (FailoverBndupdDropped)", "Total number of DHCP fail over Binding Updates dropped (FailoverBndupdDropped)",
nil, nil,
@@ -254,158 +261,159 @@ type dhcpPerf struct {
FailoverBndupdDropped float64 `perflib:"Failover: BndUpd Dropped."` FailoverBndupdDropped float64 `perflib:"Failover: BndUpd Dropped."`
} }
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var dhcpPerfs []dhcpPerf var dhcpPerfs []dhcpPerf
if err := perflib.UnmarshalObject(ctx.PerfObjects["DHCP Server"], &dhcpPerfs, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["DHCP Server"], &dhcpPerfs, logger); err != nil {
return err return err
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedTotal, c.packetsReceivedTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].PacketsReceivedTotal, dhcpPerfs[0].PacketsReceivedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DuplicatesDroppedTotal, c.duplicatesDroppedTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].DuplicatesDroppedTotal, dhcpPerfs[0].DuplicatesDroppedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsExpiredTotal, c.packetsExpiredTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].PacketsExpiredTotal, dhcpPerfs[0].PacketsExpiredTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ActiveQueueLength, c.activeQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
dhcpPerfs[0].ActiveQueueLength, dhcpPerfs[0].ActiveQueueLength,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ConflictCheckQueueLength, c.conflictCheckQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
dhcpPerfs[0].ConflictCheckQueueLength, dhcpPerfs[0].ConflictCheckQueueLength,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DiscoversTotal, c.discoversTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].DiscoversTotal, dhcpPerfs[0].DiscoversTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.OffersTotal, c.offersTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].OffersTotal, dhcpPerfs[0].OffersTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RequestsTotal, c.requestsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].RequestsTotal, dhcpPerfs[0].RequestsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.InformsTotal, c.informsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].InformsTotal, dhcpPerfs[0].InformsTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AcksTotal, c.acksTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].AcksTotal, dhcpPerfs[0].AcksTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NacksTotal, c.nACKsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].NacksTotal, dhcpPerfs[0].NacksTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DeclinesTotal, c.declinesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].DeclinesTotal, dhcpPerfs[0].DeclinesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReleasesTotal, c.releasesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].ReleasesTotal, dhcpPerfs[0].ReleasesTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.OfferQueueLength, c.offerQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
dhcpPerfs[0].OfferQueueLength, dhcpPerfs[0].OfferQueueLength,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DeniedDueToMatch, c.deniedDueToMatch,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].DeniedDueToMatch, dhcpPerfs[0].DeniedDueToMatch,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DeniedDueToNonMatch, c.deniedDueToNonMatch,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].DeniedDueToNonMatch, dhcpPerfs[0].DeniedDueToNonMatch,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverBndupdSentTotal, c.failoverBndupdSentTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverBndupdSentTotal, dhcpPerfs[0].FailoverBndupdSentTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverBndupdReceivedTotal, c.failoverBndupdReceivedTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverBndupdReceivedTotal, dhcpPerfs[0].FailoverBndupdReceivedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverBndackSentTotal, c.failoverBndackSentTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverBndackSentTotal, dhcpPerfs[0].FailoverBndackSentTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverBndackReceivedTotal, c.failoverBndackReceivedTotal,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverBndackReceivedTotal, dhcpPerfs[0].FailoverBndackReceivedTotal,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverBndupdPendingOutboundQueue, c.failoverBndupdPendingOutboundQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
dhcpPerfs[0].FailoverBndupdPendingOutboundQueue, dhcpPerfs[0].FailoverBndupdPendingOutboundQueue,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverTransitionsCommunicationinterruptedState, c.failoverTransitionsCommunicationInterruptedState,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverTransitionsCommunicationinterruptedState, dhcpPerfs[0].FailoverTransitionsCommunicationinterruptedState,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverTransitionsPartnerdownState, c.failoverTransitionsPartnerDownState,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverTransitionsPartnerdownState, dhcpPerfs[0].FailoverTransitionsPartnerdownState,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverTransitionsRecoverState, c.failoverTransitionsRecoverState,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverTransitionsRecoverState, dhcpPerfs[0].FailoverTransitionsRecoverState,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverBndupdDropped, c.failoverBndupdDropped,
prometheus.CounterValue, prometheus.CounterValue,
dhcpPerfs[0].FailoverBndupdDropped, dhcpPerfs[0].FailoverBndupdDropped,
) )

View File

@@ -10,8 +10,8 @@ import (
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const ( const (
@@ -23,41 +23,53 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive // A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
DiskInfo *prometheus.Desc availability *prometheus.Desc
Status *prometheus.Desc diskInfo *prometheus.Desc
Size *prometheus.Desc partitions *prometheus.Desc
Partitions *prometheus.Desc size *prometheus.Desc
Availability *prometheus.Desc status *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.DiskInfo = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.diskInfo = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"), prometheus.BuildFQName(types.Namespace, Name, "info"),
"General drive information", "General drive information",
[]string{ []string{
@@ -68,25 +80,25 @@ func (c *collector) Build() error {
}, },
nil, nil,
) )
c.Status = prometheus.NewDesc( c.status = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "status"), prometheus.BuildFQName(types.Namespace, Name, "status"),
"Status of the drive", "Status of the drive",
[]string{"name", "status"}, []string{"name", "status"},
nil, nil,
) )
c.Size = prometheus.NewDesc( c.size = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "size"), prometheus.BuildFQName(types.Namespace, Name, "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.", "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"}, []string{"name"},
nil, nil,
) )
c.Partitions = prometheus.NewDesc( c.partitions = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "partitions"), prometheus.BuildFQName(types.Namespace, Name, "partitions"),
"Number of partitions", "Number of partitions",
[]string{"name"}, []string{"name"},
nil, nil,
) )
c.Availability = prometheus.NewDesc( c.availability = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "availability"), prometheus.BuildFQName(types.Namespace, Name, "availability"),
"Availability Status", "Availability Status",
[]string{"name", "availability"}, []string{"name", "availability"},
@@ -96,7 +108,7 @@ func (c *collector) Build() error {
return nil return nil
} }
type Win32_DiskDrive struct { type win32_DiskDrive struct {
DeviceID string DeviceID string
Model string Model string
Size uint64 Size uint64
@@ -149,33 +161,34 @@ var (
) )
// Collect sends the metric values for each metric to the provided prometheus Metric channel. // Collect sends the metric values for each metric to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting disk_drive_info metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting disk_drive_info metrics", "err", err)
return err return err
} }
return nil return nil
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_DiskDrive var dst []win32_DiskDrive
if err := wmi.Query(win32DiskQuery, &dst); err != nil { if err := c.wmiClient.Query(win32DiskQuery, &dst); err != nil {
return nil, err return err
} }
if len(dst) == 0 { if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set") return errors.New("WMI query returned empty result set")
} }
for _, disk := range dst { for _, disk := range dst {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DiskInfo, c.diskInfo,
prometheus.GaugeValue, prometheus.GaugeValue,
1.0, 1.0,
strings.Trim(disk.DeviceID, "\\.\\"), strings.Trim(disk.DeviceID, "\\.\\"), //nolint:staticcheck
strings.TrimRight(disk.Model, " "), strings.TrimRight(disk.Model, " "),
strings.TrimRight(disk.Caption, " "), strings.TrimRight(disk.Caption, " "),
strings.TrimRight(disk.Name, "\\.\\"), strings.TrimRight(disk.Name, "\\.\\"), //nolint:staticcheck
) )
for _, status := range allDiskStatus { for _, status := range allDiskStatus {
@@ -185,26 +198,26 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Status, c.status,
prometheus.GaugeValue, prometheus.GaugeValue,
isCurrentState, isCurrentState,
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
status, status,
) )
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Size, c.size,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(disk.Size), float64(disk.Size),
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Partitions, c.partitions,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(disk.Partitions), float64(disk.Partitions),
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
) )
for availNum, val := range availMap { for availNum, val := range availMap {
@@ -213,14 +226,14 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
isCurrentState = 1.0 isCurrentState = 1.0
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Availability, c.availability,
prometheus.GaugeValue, prometheus.GaugeValue,
isCurrentState, isCurrentState,
strings.Trim(disk.Name, "\\.\\"), strings.Trim(disk.Name, "\\.\\"), //nolint:staticcheck
val, val,
) )
} }
} }
return nil, nil return nil
} }

View File

@@ -9,8 +9,8 @@ import (
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "dns" const Name = "dns"
@@ -19,184 +19,197 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
ZoneTransferRequestsReceived *prometheus.Desc dynamicUpdatesFailures *prometheus.Desc
ZoneTransferRequestsSent *prometheus.Desc dynamicUpdatesQueued *prometheus.Desc
ZoneTransferResponsesReceived *prometheus.Desc dynamicUpdatesReceived *prometheus.Desc
ZoneTransferSuccessReceived *prometheus.Desc memoryUsedBytes *prometheus.Desc
ZoneTransferSuccessSent *prometheus.Desc notifyReceived *prometheus.Desc
ZoneTransferFailures *prometheus.Desc notifySent *prometheus.Desc
MemoryUsedBytes *prometheus.Desc queries *prometheus.Desc
DynamicUpdatesQueued *prometheus.Desc recursiveQueries *prometheus.Desc
DynamicUpdatesReceived *prometheus.Desc recursiveQueryFailures *prometheus.Desc
DynamicUpdatesFailures *prometheus.Desc recursiveQuerySendTimeouts *prometheus.Desc
NotifyReceived *prometheus.Desc responses *prometheus.Desc
NotifySent *prometheus.Desc secureUpdateFailures *prometheus.Desc
SecureUpdateFailures *prometheus.Desc secureUpdateReceived *prometheus.Desc
SecureUpdateReceived *prometheus.Desc unmatchedResponsesReceived *prometheus.Desc
Queries *prometheus.Desc winsQueries *prometheus.Desc
Responses *prometheus.Desc winsResponses *prometheus.Desc
RecursiveQueries *prometheus.Desc zoneTransferFailures *prometheus.Desc
RecursiveQueryFailures *prometheus.Desc zoneTransferRequestsReceived *prometheus.Desc
RecursiveQuerySendTimeouts *prometheus.Desc zoneTransferRequestsSent *prometheus.Desc
WinsQueries *prometheus.Desc zoneTransferResponsesReceived *prometheus.Desc
WinsResponses *prometheus.Desc zoneTransferSuccessReceived *prometheus.Desc
UnmatchedResponsesReceived *prometheus.Desc zoneTransferSuccessSent *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.ZoneTransferRequestsReceived = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.zoneTransferRequestsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_requests_received_total"), prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_requests_received_total"),
"Number of zone transfer requests (AXFR/IXFR) received by the master DNS server", "Number of zone transfer requests (AXFR/IXFR) received by the master DNS server",
[]string{"qtype"}, []string{"qtype"},
nil, nil,
) )
c.ZoneTransferRequestsSent = prometheus.NewDesc( c.zoneTransferRequestsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_requests_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_requests_sent_total"),
"Number of zone transfer requests (AXFR/IXFR) sent by the secondary DNS server", "Number of zone transfer requests (AXFR/IXFR) sent by the secondary DNS server",
[]string{"qtype"}, []string{"qtype"},
nil, nil,
) )
c.ZoneTransferResponsesReceived = prometheus.NewDesc( c.zoneTransferResponsesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_response_received_total"), prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_response_received_total"),
"Number of zone transfer responses (AXFR/IXFR) received by the secondary DNS server", "Number of zone transfer responses (AXFR/IXFR) received by the secondary DNS server",
[]string{"qtype"}, []string{"qtype"},
nil, nil,
) )
c.ZoneTransferSuccessReceived = prometheus.NewDesc( c.zoneTransferSuccessReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_success_received_total"), prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_success_received_total"),
"Number of successful zone transfers (AXFR/IXFR) received by the secondary DNS server", "Number of successful zone transfers (AXFR/IXFR) received by the secondary DNS server",
[]string{"qtype", "protocol"}, []string{"qtype", "protocol"},
nil, nil,
) )
c.ZoneTransferSuccessSent = prometheus.NewDesc( c.zoneTransferSuccessSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_success_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_success_sent_total"),
"Number of successful zone transfers (AXFR/IXFR) of the master DNS server", "Number of successful zone transfers (AXFR/IXFR) of the master DNS server",
[]string{"qtype"}, []string{"qtype"},
nil, nil,
) )
c.ZoneTransferFailures = prometheus.NewDesc( c.zoneTransferFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_failures_total"), prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_failures_total"),
"Number of failed zone transfers of the master DNS server", "Number of failed zone transfers of the master DNS server",
nil, nil,
nil, nil,
) )
c.MemoryUsedBytes = prometheus.NewDesc( c.memoryUsedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "memory_used_bytes"), prometheus.BuildFQName(types.Namespace, Name, "memory_used_bytes"),
"Current memory used by DNS server", "Current memory used by DNS server",
[]string{"area"}, []string{"area"},
nil, nil,
) )
c.DynamicUpdatesQueued = prometheus.NewDesc( c.dynamicUpdatesQueued = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_queued"), prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_queued"),
"Number of dynamic updates queued by the DNS server", "Number of dynamic updates queued by the DNS server",
nil, nil,
nil, nil,
) )
c.DynamicUpdatesReceived = prometheus.NewDesc( c.dynamicUpdatesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_received_total"), prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_received_total"),
"Number of secure update requests received by the DNS server", "Number of secure update requests received by the DNS server",
[]string{"operation"}, []string{"operation"},
nil, nil,
) )
c.DynamicUpdatesFailures = prometheus.NewDesc( c.dynamicUpdatesFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_failures_total"), prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_failures_total"),
"Number of dynamic updates which timed out or were rejected by the DNS server", "Number of dynamic updates which timed out or were rejected by the DNS server",
[]string{"reason"}, []string{"reason"},
nil, nil,
) )
c.NotifyReceived = prometheus.NewDesc( c.notifyReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "notify_received_total"), prometheus.BuildFQName(types.Namespace, Name, "notify_received_total"),
"Number of notifies received by the secondary DNS server", "Number of notifies received by the secondary DNS server",
nil, nil,
nil, nil,
) )
c.NotifySent = prometheus.NewDesc( c.notifySent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "notify_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "notify_sent_total"),
"Number of notifies sent by the master DNS server", "Number of notifies sent by the master DNS server",
nil, nil,
nil, nil,
) )
c.SecureUpdateFailures = prometheus.NewDesc( c.secureUpdateFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "secure_update_failures_total"), prometheus.BuildFQName(types.Namespace, Name, "secure_update_failures_total"),
"Number of secure updates that failed on the DNS server", "Number of secure updates that failed on the DNS server",
nil, nil,
nil, nil,
) )
c.SecureUpdateReceived = prometheus.NewDesc( c.secureUpdateReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "secure_update_received_total"), prometheus.BuildFQName(types.Namespace, Name, "secure_update_received_total"),
"Number of secure update requests received by the DNS server", "Number of secure update requests received by the DNS server",
nil, nil,
nil, nil,
) )
c.Queries = prometheus.NewDesc( c.queries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "queries_total"), prometheus.BuildFQName(types.Namespace, Name, "queries_total"),
"Number of queries received by DNS server", "Number of queries received by DNS server",
[]string{"protocol"}, []string{"protocol"},
nil, nil,
) )
c.Responses = prometheus.NewDesc( c.responses = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "responses_total"), prometheus.BuildFQName(types.Namespace, Name, "responses_total"),
"Number of responses sent by DNS server", "Number of responses sent by DNS server",
[]string{"protocol"}, []string{"protocol"},
nil, nil,
) )
c.RecursiveQueries = prometheus.NewDesc( c.recursiveQueries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "recursive_queries_total"), prometheus.BuildFQName(types.Namespace, Name, "recursive_queries_total"),
"Number of recursive queries received by DNS server", "Number of recursive queries received by DNS server",
nil, nil,
nil, nil,
) )
c.RecursiveQueryFailures = prometheus.NewDesc( c.recursiveQueryFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "recursive_query_failures_total"), prometheus.BuildFQName(types.Namespace, Name, "recursive_query_failures_total"),
"Number of recursive query failures", "Number of recursive query failures",
nil, nil,
nil, nil,
) )
c.RecursiveQuerySendTimeouts = prometheus.NewDesc( c.recursiveQuerySendTimeouts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "recursive_query_send_timeouts_total"), prometheus.BuildFQName(types.Namespace, Name, "recursive_query_send_timeouts_total"),
"Number of recursive query sending timeouts", "Number of recursive query sending timeouts",
nil, nil,
nil, nil,
) )
c.WinsQueries = prometheus.NewDesc( c.winsQueries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "wins_queries_total"), prometheus.BuildFQName(types.Namespace, Name, "wins_queries_total"),
"Number of WINS lookup requests received by the server", "Number of WINS lookup requests received by the server",
[]string{"direction"}, []string{"direction"},
nil, nil,
) )
c.WinsResponses = prometheus.NewDesc( c.winsResponses = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "wins_responses_total"), prometheus.BuildFQName(types.Namespace, Name, "wins_responses_total"),
"Number of WINS lookup responses sent by the server", "Number of WINS lookup responses sent by the server",
[]string{"direction"}, []string{"direction"},
nil, nil,
) )
c.UnmatchedResponsesReceived = prometheus.NewDesc( c.unmatchedResponsesReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "unmatched_responses_total"), prometheus.BuildFQName(types.Namespace, Name, "unmatched_responses_total"),
"Number of response packets received by the DNS server that do not match any outstanding remote query", "Number of response packets received by the DNS server that do not match any outstanding remote query",
nil, nil,
@@ -207,9 +220,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting dns metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting dns metrics", "err", err)
return err return err
} }
return nil return nil
@@ -261,77 +275,76 @@ type Win32_PerfRawData_DNS_DNS struct {
ZoneTransferSOARequestSent uint32 ZoneTransferSOARequestSent uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_DNS_DNS var dst []Win32_PerfRawData_DNS_DNS
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_DNS_DNS", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
if len(dst) == 0 { if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set") return errors.New("WMI query returned empty result set")
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsReceived, c.zoneTransferRequestsReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AXFRRequestReceived), float64(dst[0].AXFRRequestReceived),
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsReceived, c.zoneTransferRequestsReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].IXFRRequestReceived), float64(dst[0].IXFRRequestReceived),
"incremental", "incremental",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsSent, c.zoneTransferRequestsSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AXFRRequestSent), float64(dst[0].AXFRRequestSent),
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsSent, c.zoneTransferRequestsSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].IXFRRequestSent), float64(dst[0].IXFRRequestSent),
"incremental", "incremental",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsSent, c.zoneTransferRequestsSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].ZoneTransferSOARequestSent), float64(dst[0].ZoneTransferSOARequestSent),
"soa", "soa",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferResponsesReceived, c.zoneTransferResponsesReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AXFRResponseReceived), float64(dst[0].AXFRResponseReceived),
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferResponsesReceived, c.zoneTransferResponsesReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].IXFRResponseReceived), float64(dst[0].IXFRResponseReceived),
"incremental", "incremental",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessReceived, c.zoneTransferSuccessReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AXFRSuccessReceived), float64(dst[0].AXFRSuccessReceived),
"full", "full",
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessReceived, c.zoneTransferSuccessReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].IXFRTCPSuccessReceived), float64(dst[0].IXFRTCPSuccessReceived),
"incremental", "incremental",
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessReceived, c.zoneTransferSuccessReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].IXFRTCPSuccessReceived), float64(dst[0].IXFRTCPSuccessReceived),
"incremental", "incremental",
@@ -339,186 +352,186 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessSent, c.zoneTransferSuccessSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AXFRSuccessSent), float64(dst[0].AXFRSuccessSent),
"full", "full",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessSent, c.zoneTransferSuccessSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].IXFRSuccessSent), float64(dst[0].IXFRSuccessSent),
"incremental", "incremental",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferFailures, c.zoneTransferFailures,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].ZoneTransferFailure), float64(dst[0].ZoneTransferFailure),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(dst[0].CachingMemory), float64(dst[0].CachingMemory),
"caching", "caching",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(dst[0].DatabaseNodeMemory), float64(dst[0].DatabaseNodeMemory),
"database_node", "database_node",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(dst[0].NbstatMemory), float64(dst[0].NbstatMemory),
"nbstat", "nbstat",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(dst[0].RecordFlowMemory), float64(dst[0].RecordFlowMemory),
"record_flow", "record_flow",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(dst[0].TCPMessageMemory), float64(dst[0].TCPMessageMemory),
"tcp_message", "tcp_message",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes, c.memoryUsedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(dst[0].UDPMessageMemory), float64(dst[0].UDPMessageMemory),
"udp_message", "udp_message",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesReceived, c.dynamicUpdatesReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].DynamicUpdateNoOperation), float64(dst[0].DynamicUpdateNoOperation),
"noop", "noop",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesReceived, c.dynamicUpdatesReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].DynamicUpdateWrittentoDatabase), float64(dst[0].DynamicUpdateWrittentoDatabase),
"written", "written",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesQueued, c.dynamicUpdatesQueued,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(dst[0].DynamicUpdateQueued), float64(dst[0].DynamicUpdateQueued),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesFailures, c.dynamicUpdatesFailures,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].DynamicUpdateRejected), float64(dst[0].DynamicUpdateRejected),
"rejected", "rejected",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesFailures, c.dynamicUpdatesFailures,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].DynamicUpdateTimeOuts), float64(dst[0].DynamicUpdateTimeOuts),
"timeout", "timeout",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NotifyReceived, c.notifyReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].NotifyReceived), float64(dst[0].NotifyReceived),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NotifySent, c.notifySent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].NotifySent), float64(dst[0].NotifySent),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RecursiveQueries, c.recursiveQueries,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].RecursiveQueries), float64(dst[0].RecursiveQueries),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RecursiveQueryFailures, c.recursiveQueryFailures,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].RecursiveQueryFailure), float64(dst[0].RecursiveQueryFailure),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RecursiveQuerySendTimeouts, c.recursiveQuerySendTimeouts,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].RecursiveSendTimeOuts), float64(dst[0].RecursiveSendTimeOuts),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Queries, c.queries,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].TCPQueryReceived), float64(dst[0].TCPQueryReceived),
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Queries, c.queries,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].UDPQueryReceived), float64(dst[0].UDPQueryReceived),
"udp", "udp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Responses, c.responses,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].TCPResponseSent), float64(dst[0].TCPResponseSent),
"tcp", "tcp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Responses, c.responses,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].UDPResponseSent), float64(dst[0].UDPResponseSent),
"udp", "udp",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.UnmatchedResponsesReceived, c.unmatchedResponsesReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].UnmatchedResponsesReceived), float64(dst[0].UnmatchedResponsesReceived),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WinsQueries, c.winsQueries,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].WINSLookupReceived), float64(dst[0].WINSLookupReceived),
"forward", "forward",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WinsQueries, c.winsQueries,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].WINSReverseLookupReceived), float64(dst[0].WINSReverseLookupReceived),
"reverse", "reverse",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WinsResponses, c.winsResponses,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].WINSResponseSent), float64(dst[0].WINSResponseSent),
"forward", "forward",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WinsResponses, c.winsResponses,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].WINSReverseResponseSent), float64(dst[0].WINSReverseResponseSent),
"reverse", "reverse",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SecureUpdateFailures, c.secureUpdateFailures,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].SecureUpdateFailure), float64(dst[0].SecureUpdateFailure),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SecureUpdateReceived, c.secureUpdateReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].SecureUpdateReceived), float64(dst[0].SecureUpdateReceived),
) )
return nil, nil return nil
} }

View File

@@ -5,7 +5,6 @@ package exchange
import ( import (
"fmt" "fmt"
"os" "os"
"slices"
"strings" "strings"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
@@ -13,123 +12,153 @@ import (
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const ( const Name = "exchange"
Name = "exchange"
FlagExchangeListAllCollectors = "collectors.exchange.list"
FlagExchangeCollectorsEnabled = "collectors.exchange.enabled"
)
type Config struct { type Config struct {
CollectorsEnabled string `yaml:"collectors_enabled"` CollectorsEnabled []string `yaml:"collectors_enabled"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
CollectorsEnabled: "", CollectorsEnabled: []string{
"ADAccessProcesses",
"TransportQueues",
"HttpProxy",
"ActiveSync",
"AvailabilityService",
"OutlookWebAccess",
"Autodiscover",
"WorkloadManagement",
"RpcClientAccess",
"MapiHttpEmsmdb",
},
} }
type collector struct { type Collector struct {
logger log.Logger config Config
exchangeListAllCollectors *bool activeMailboxDeliveryQueueLength *prometheus.Desc
exchangeCollectorsEnabled *string activeSyncRequestsPerSec *prometheus.Desc
activeTasks *prometheus.Desc
LDAPReadTime *prometheus.Desc activeUserCount *prometheus.Desc
LDAPSearchTime *prometheus.Desc activeUserCountMapiHttpEmsMDB *prometheus.Desc
LDAPWriteTime *prometheus.Desc autoDiscoverRequestsPerSec *prometheus.Desc
LDAPTimeoutErrorsPerSec *prometheus.Desc availabilityRequestsSec *prometheus.Desc
LongRunningLDAPOperationsPerMin *prometheus.Desc averageAuthenticationLatency *prometheus.Desc
ExternalActiveRemoteDeliveryQueueLength *prometheus.Desc averageCASProcessingLatency *prometheus.Desc
InternalActiveRemoteDeliveryQueueLength *prometheus.Desc completedTasks *prometheus.Desc
ActiveMailboxDeliveryQueueLength *prometheus.Desc connectionCount *prometheus.Desc
RetryMailboxDeliveryQueueLength *prometheus.Desc currentUniqueUsers *prometheus.Desc
UnreachableQueueLength *prometheus.Desc externalActiveRemoteDeliveryQueueLength *prometheus.Desc
ExternalLargestDeliveryQueueLength *prometheus.Desc externalLargestDeliveryQueueLength *prometheus.Desc
InternalLargestDeliveryQueueLength *prometheus.Desc internalActiveRemoteDeliveryQueueLength *prometheus.Desc
PoisonQueueLength *prometheus.Desc internalLargestDeliveryQueueLength *prometheus.Desc
MailboxServerLocatorAverageLatency *prometheus.Desc isActive *prometheus.Desc
AverageAuthenticationLatency *prometheus.Desc ldapReadTime *prometheus.Desc
AverageCASProcessingLatency *prometheus.Desc ldapSearchTime *prometheus.Desc
MailboxServerProxyFailureRate *prometheus.Desc ldapTimeoutErrorsPerSec *prometheus.Desc
OutstandingProxyRequests *prometheus.Desc ldapWriteTime *prometheus.Desc
ProxyRequestsPerSec *prometheus.Desc longRunningLDAPOperationsPerMin *prometheus.Desc
ActiveSyncRequestsPerSec *prometheus.Desc mailboxServerLocatorAverageLatency *prometheus.Desc
PingCommandsPending *prometheus.Desc mailboxServerProxyFailureRate *prometheus.Desc
SyncCommandsPerSec *prometheus.Desc outstandingProxyRequests *prometheus.Desc
AvailabilityRequestsSec *prometheus.Desc owaRequestsPerSec *prometheus.Desc
CurrentUniqueUsers *prometheus.Desc pingCommandsPending *prometheus.Desc
OWARequestsPerSec *prometheus.Desc poisonQueueLength *prometheus.Desc
AutodiscoverRequestsPerSec *prometheus.Desc proxyRequestsPerSec *prometheus.Desc
ActiveTasks *prometheus.Desc queuedTasks *prometheus.Desc
CompletedTasks *prometheus.Desc retryMailboxDeliveryQueueLength *prometheus.Desc
QueuedTasks *prometheus.Desc rpcAveragedLatency *prometheus.Desc
YieldedTasks *prometheus.Desc rpcOperationsPerSec *prometheus.Desc
IsActive *prometheus.Desc rpcRequests *prometheus.Desc
RPCAveragedLatency *prometheus.Desc syncCommandsPerSec *prometheus.Desc
RPCRequests *prometheus.Desc unreachableQueueLength *prometheus.Desc
ActiveUserCount *prometheus.Desc userCount *prometheus.Desc
ConnectionCount *prometheus.Desc yieldedTasks *prometheus.Desc
RPCOperationsPerSec *prometheus.Desc
UserCount *prometheus.Desc
ActiveUserCountMapiHttpEmsmdb *prometheus.Desc
enabledCollectors []string
} }
// All available collector functions func New(config *Config) *Collector {
var exchangeAllCollectorNames = []string{
"ADAccessProcesses",
"TransportQueues",
"HttpProxy",
"ActiveSync",
"AvailabilityService",
"OutlookWebAccess",
"Autodiscover",
"WorkloadManagement",
"RpcClientAccess",
"MapiHttpEmsmdb",
}
func New(logger log.Logger, config *Config) types.Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
} }
exchangeListAllCollectors := false if config.CollectorsEnabled == nil {
c := &collector{ config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
exchangeCollectorsEnabled: &config.CollectorsEnabled,
exchangeListAllCollectors: &exchangeListAllCollectors,
} }
c.SetLogger(logger)
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(app *kingpin.Application) types.Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &collector{ c := &Collector{
exchangeListAllCollectors: app.Flag( config: ConfigDefaults,
FlagExchangeListAllCollectors,
"List the collectors along with their perflib object name/ids",
).Bool(),
exchangeCollectorsEnabled: app.Flag(
FlagExchangeCollectorsEnabled,
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default(ConfigDefaults.CollectorsEnabled).String(),
} }
c.config.CollectorsEnabled = make([]string, 0)
var listAllCollectors bool
var collectorsEnabled string
app.Flag(
"collectors.exchange.list",
"List the collectors along with their perflib object name/ids",
).BoolVar(&listAllCollectors)
app.Flag(
"collectors.exchange.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringVar(&collectorsEnabled)
app.PreAction(func(*kingpin.ParseContext) error {
if listAllCollectors {
collectorDesc := map[string]string{
"ADAccessProcesses": "[19108] MSExchange ADAccess Processes",
"TransportQueues": "[20524] MSExchangeTransport Queues",
"HttpProxy": "[36934] MSExchange HttpProxy",
"ActiveSync": "[25138] MSExchange ActiveSync",
"AvailabilityService": "[24914] MSExchange Availability Service",
"OutlookWebAccess": "[24618] MSExchange OWA",
"Autodiscover": "[29240] MSExchange Autodiscover",
"WorkloadManagement": "[19430] MSExchange WorkloadManagement Workloads",
"RpcClientAccess": "[29336] MSExchange RpcClientAccess",
"MapiHttpEmsmdb": "[26463] MSExchange MapiHttp Emsmdb",
}
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object"))
for _, cname := range ConfigDefaults.CollectorsEnabled {
sb.WriteString(fmt.Sprintf("%-32s %-32s\n", cname, collectorDesc[cname]))
}
app.UsageTemplate(sb.String()).Usage(nil)
os.Exit(0)
}
return nil
})
app.Action(func(*kingpin.ParseContext) error {
c.config.CollectorsEnabled = strings.Split(collectorsEnabled, ",")
return nil
})
return c
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{ return []string{
"MSExchange ADAccess Processes", "MSExchange ADAccess Processes",
"MSExchangeTransport Queues", "MSExchangeTransport Queues",
@@ -144,7 +173,11 @@ func (c *collector) GetPerfCounter() ([]string, error) {
}, nil }, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
// desc creates a new prometheus description // desc creates a new prometheus description
desc := func(metricName string, description string, labels ...string) *prometheus.Desc { desc := func(metricName string, description string, labels ...string) *prometheus.Desc {
return prometheus.NewDesc( return prometheus.NewDesc(
@@ -155,88 +188,52 @@ func (c *collector) Build() error {
) )
} }
c.RPCAveragedLatency = desc("rpc_avg_latency_sec", "The latency (sec) averaged for the past 1024 packets") c.rpcAveragedLatency = desc("rpc_avg_latency_sec", "The latency (sec) averaged for the past 1024 packets")
c.RPCRequests = desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service") c.rpcRequests = desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service")
c.ActiveUserCount = desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes") c.activeUserCount = desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes")
c.ConnectionCount = desc("rpc_connection_count", "Total number of client connections maintained") c.connectionCount = desc("rpc_connection_count", "Total number of client connections maintained")
c.RPCOperationsPerSec = desc("rpc_operations_total", "The rate at which RPC operations occur") c.rpcOperationsPerSec = desc("rpc_operations_total", "The rate at which RPC operations occur")
c.UserCount = desc("rpc_user_count", "Number of users") c.userCount = desc("rpc_user_count", "Number of users")
c.LDAPReadTime = desc("ldap_read_time_sec", "Time (sec) to send an LDAP read request and receive a response", "name") c.ldapReadTime = desc("ldap_read_time_sec", "Time (sec) to send an LDAP read request and receive a response", "name")
c.LDAPSearchTime = desc("ldap_search_time_sec", "Time (sec) to send an LDAP search request and receive a response", "name") c.ldapSearchTime = desc("ldap_search_time_sec", "Time (sec) to send an LDAP search request and receive a response", "name")
c.LDAPWriteTime = desc("ldap_write_time_sec", "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", "name") c.ldapWriteTime = desc("ldap_write_time_sec", "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", "name")
c.LDAPTimeoutErrorsPerSec = desc("ldap_timeout_errors_total", "Total number of LDAP timeout errors", "name") c.ldapTimeoutErrorsPerSec = desc("ldap_timeout_errors_total", "Total number of LDAP timeout errors", "name")
c.LongRunningLDAPOperationsPerMin = desc("ldap_long_running_ops_per_sec", "Long Running LDAP operations per second", "name") c.longRunningLDAPOperationsPerMin = desc("ldap_long_running_ops_per_sec", "Long Running LDAP operations per second", "name")
c.ExternalActiveRemoteDeliveryQueueLength = desc("transport_queues_external_active_remote_delivery", "External Active Remote Delivery Queue length", "name") c.externalActiveRemoteDeliveryQueueLength = desc("transport_queues_external_active_remote_delivery", "External Active Remote Delivery Queue length", "name")
c.InternalActiveRemoteDeliveryQueueLength = desc("transport_queues_internal_active_remote_delivery", "Internal Active Remote Delivery Queue length", "name") c.internalActiveRemoteDeliveryQueueLength = desc("transport_queues_internal_active_remote_delivery", "Internal Active Remote Delivery Queue length", "name")
c.ActiveMailboxDeliveryQueueLength = desc("transport_queues_active_mailbox_delivery", "Active Mailbox Delivery Queue length", "name") c.activeMailboxDeliveryQueueLength = desc("transport_queues_active_mailbox_delivery", "Active Mailbox Delivery Queue length", "name")
c.RetryMailboxDeliveryQueueLength = desc("transport_queues_retry_mailbox_delivery", "Retry Mailbox Delivery Queue length", "name") c.retryMailboxDeliveryQueueLength = desc("transport_queues_retry_mailbox_delivery", "Retry Mailbox Delivery Queue length", "name")
c.UnreachableQueueLength = desc("transport_queues_unreachable", "Unreachable Queue length", "name") c.unreachableQueueLength = desc("transport_queues_unreachable", "Unreachable Queue length", "name")
c.ExternalLargestDeliveryQueueLength = desc("transport_queues_external_largest_delivery", "External Largest Delivery Queue length", "name") c.externalLargestDeliveryQueueLength = desc("transport_queues_external_largest_delivery", "External Largest Delivery Queue length", "name")
c.InternalLargestDeliveryQueueLength = desc("transport_queues_internal_largest_delivery", "Internal Largest Delivery Queue length", "name") c.internalLargestDeliveryQueueLength = desc("transport_queues_internal_largest_delivery", "Internal Largest Delivery Queue length", "name")
c.PoisonQueueLength = desc("transport_queues_poison", "Poison Queue length", "name") c.poisonQueueLength = desc("transport_queues_poison", "Poison Queue length", "name")
c.MailboxServerLocatorAverageLatency = desc("http_proxy_mailbox_server_locator_avg_latency_sec", "Average latency (sec) of MailboxServerLocator web service calls", "name") c.mailboxServerLocatorAverageLatency = desc("http_proxy_mailbox_server_locator_avg_latency_sec", "Average latency (sec) of MailboxServerLocator web service calls", "name")
c.AverageAuthenticationLatency = desc("http_proxy_avg_auth_latency", "Average time spent authenticating CAS requests over the last 200 samples", "name") c.averageAuthenticationLatency = desc("http_proxy_avg_auth_latency", "Average time spent authenticating CAS requests over the last 200 samples", "name")
c.OutstandingProxyRequests = desc("http_proxy_outstanding_proxy_requests", "Number of concurrent outstanding proxy requests", "name") c.outstandingProxyRequests = desc("http_proxy_outstanding_proxy_requests", "Number of concurrent outstanding proxy requests", "name")
c.ProxyRequestsPerSec = desc("http_proxy_requests_total", "Number of proxy requests processed each second", "name") c.proxyRequestsPerSec = desc("http_proxy_requests_total", "Number of proxy requests processed each second", "name")
c.AvailabilityRequestsSec = desc("avail_service_requests_per_sec", "Number of requests serviced per second") c.availabilityRequestsSec = desc("avail_service_requests_per_sec", "Number of requests serviced per second")
c.CurrentUniqueUsers = desc("owa_current_unique_users", "Number of unique users currently logged on to Outlook Web App") c.currentUniqueUsers = desc("owa_current_unique_users", "Number of unique users currently logged on to Outlook Web App")
c.OWARequestsPerSec = desc("owa_requests_total", "Number of requests handled by Outlook Web App per second") c.owaRequestsPerSec = desc("owa_requests_total", "Number of requests handled by Outlook Web App per second")
c.AutodiscoverRequestsPerSec = desc("autodiscover_requests_total", "Number of autodiscover service requests processed each second") c.autoDiscoverRequestsPerSec = desc("autodiscover_requests_total", "Number of autodiscover service requests processed each second")
c.ActiveTasks = desc("workload_active_tasks", "Number of active tasks currently running in the background for workload management", "name") c.activeTasks = desc("workload_active_tasks", "Number of active tasks currently running in the background for workload management", "name")
c.CompletedTasks = desc("workload_completed_tasks", "Number of workload management tasks that have been completed", "name") c.completedTasks = desc("workload_completed_tasks", "Number of workload management tasks that have been completed", "name")
c.QueuedTasks = desc("workload_queued_tasks", "Number of workload management tasks that are currently queued up waiting to be processed", "name") c.queuedTasks = desc("workload_queued_tasks", "Number of workload management tasks that are currently queued up waiting to be processed", "name")
c.YieldedTasks = desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name") c.yieldedTasks = desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name")
c.IsActive = desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name") c.isActive = desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name")
c.ActiveSyncRequestsPerSec = desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load") c.activeSyncRequestsPerSec = desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load")
c.AverageCASProcessingLatency = desc("http_proxy_avg_cas_proccessing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name") c.averageCASProcessingLatency = desc("http_proxy_avg_cas_processing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name")
c.MailboxServerProxyFailureRate = desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name") c.mailboxServerProxyFailureRate = desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name")
c.PingCommandsPending = desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue") c.pingCommandsPending = desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue")
c.SyncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder") c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder")
c.ActiveUserCountMapiHttpEmsmdb = desc("mapihttp_emsmdb_active_user_count", "Number of unique outlook users that have shown some kind of activity in the last 2 minutes") c.activeUserCountMapiHttpEmsMDB = desc("mapihttp_emsmdb_active_user_count", "Number of unique outlook users that have shown some kind of activity in the last 2 minutes")
c.enabledCollectors = make([]string, 0, len(exchangeAllCollectorNames))
collectorDesc := map[string]string{
"ADAccessProcesses": "[19108] MSExchange ADAccess Processes",
"TransportQueues": "[20524] MSExchangeTransport Queues",
"HttpProxy": "[36934] MSExchange HttpProxy",
"ActiveSync": "[25138] MSExchange ActiveSync",
"AvailabilityService": "[24914] MSExchange Availability Service",
"OutlookWebAccess": "[24618] MSExchange OWA",
"Autodiscover": "[29240] MSExchange Autodiscover",
"WorkloadManagement": "[19430] MSExchange WorkloadManagement Workloads",
"RpcClientAccess": "[29336] MSExchange RpcClientAccess",
"MapiHttpEmsmdb": "[26463] MSExchange MapiHttp Emsmdb",
}
if *c.exchangeListAllCollectors {
fmt.Printf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object")
for _, cname := range exchangeAllCollectorNames {
fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname])
}
os.Exit(0)
}
if utils.IsEmpty(c.exchangeCollectorsEnabled) {
for _, collectorName := range exchangeAllCollectorNames {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
}
} else {
for _, collectorName := range strings.Split(*c.exchangeCollectorsEnabled, ",") {
if slices.Contains(exchangeAllCollectorNames, collectorName) {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
} else {
return fmt.Errorf("unknown exchange collector: %s", collectorName)
}
}
}
return nil return nil
} }
// Collect collects exchange metrics and sends them to prometheus // Collect collects exchange metrics and sends them to prometheus.
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ logger = log.With(logger, "collector", Name)
collectorFuncs := map[string]func(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error{
"ADAccessProcesses": c.collectADAccessProcesses, "ADAccessProcesses": c.collectADAccessProcesses,
"TransportQueues": c.collectTransportQueues, "TransportQueues": c.collectTransportQueues,
"HttpProxy": c.collectHTTPProxy, "HttpProxy": c.collectHTTPProxy,
@@ -249,16 +246,16 @@ func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
"MapiHttpEmsmdb": c.collectMapiHttpEmsmdb, "MapiHttpEmsmdb": c.collectMapiHttpEmsmdb,
} }
for _, collectorName := range c.enabledCollectors { for _, collectorName := range c.config.CollectorsEnabled {
if err := collectorFuncs[collectorName](ctx, ch); err != nil { if err := collectorFuncs[collectorName](ctx, logger, ch); err != nil {
_ = level.Error(c.logger).Log("msg", "Error in "+collectorName, "err", err) _ = level.Error(logger).Log("msg", "Error in "+collectorName, "err", err)
return err return err
} }
} }
return nil return nil
} }
// Perflib: [19108] MSExchange ADAccess Processes // Perflib: [19108] MSExchange ADAccess Processes.
type perflibADAccessProcesses struct { type perflibADAccessProcesses struct {
Name string Name string
@@ -269,9 +266,10 @@ type perflibADAccessProcesses struct {
LongRunningLDAPOperationsPerMin float64 `perflib:"Long Running LDAP Operations/min"` LongRunningLDAPOperationsPerMin float64 `perflib:"Long Running LDAP Operations/min"`
} }
func (c *collector) collectADAccessProcesses(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectADAccessProcesses(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibADAccessProcesses var data []perflibADAccessProcesses
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange ADAccess Processes"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange ADAccess Processes"], &data, logger); err != nil {
return err return err
} }
@@ -289,31 +287,31 @@ func (c *collector) collectADAccessProcesses(ctx *types.ScrapeContext, ch chan<-
labelName = fmt.Sprintf("%s_%d", labelName, labelUseCount[labelName]) labelName = fmt.Sprintf("%s_%d", labelName, labelUseCount[labelName])
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LDAPReadTime, c.ldapReadTime,
prometheus.CounterValue, prometheus.CounterValue,
c.msToSec(proc.LDAPReadTime), c.msToSec(proc.LDAPReadTime),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LDAPSearchTime, c.ldapSearchTime,
prometheus.CounterValue, prometheus.CounterValue,
c.msToSec(proc.LDAPSearchTime), c.msToSec(proc.LDAPSearchTime),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LDAPWriteTime, c.ldapWriteTime,
prometheus.CounterValue, prometheus.CounterValue,
c.msToSec(proc.LDAPWriteTime), c.msToSec(proc.LDAPWriteTime),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LDAPTimeoutErrorsPerSec, c.ldapTimeoutErrorsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
proc.LDAPTimeoutErrorsPerSec, proc.LDAPTimeoutErrorsPerSec,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LongRunningLDAPOperationsPerMin, c.longRunningLDAPOperationsPerMin,
prometheus.CounterValue, prometheus.CounterValue,
proc.LongRunningLDAPOperationsPerMin*60, proc.LongRunningLDAPOperationsPerMin*60,
labelName, labelName,
@@ -322,20 +320,21 @@ func (c *collector) collectADAccessProcesses(ctx *types.ScrapeContext, ch chan<-
return nil return nil
} }
// Perflib: [24914] MSExchange Availability Service // Perflib: [24914] MSExchange Availability Service.
type perflibAvailabilityService struct { type perflibAvailabilityService struct {
RequestsSec float64 `perflib:"Availability Requests (sec)"` RequestsSec float64 `perflib:"Availability Requests (sec)"`
} }
func (c *collector) collectAvailabilityService(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectAvailabilityService(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibAvailabilityService var data []perflibAvailabilityService
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange Availability Service"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange Availability Service"], &data, logger); err != nil {
return err return err
} }
for _, availservice := range data { for _, availservice := range data {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AvailabilityRequestsSec, c.availabilityRequestsSec,
prometheus.CounterValue, prometheus.CounterValue,
availservice.RequestsSec, availservice.RequestsSec,
) )
@@ -343,7 +342,7 @@ func (c *collector) collectAvailabilityService(ctx *types.ScrapeContext, ch chan
return nil return nil
} }
// Perflib: [36934] MSExchange HttpProxy // Perflib: [36934] MSExchange HttpProxy.
type perflibHTTPProxy struct { type perflibHTTPProxy struct {
Name string Name string
@@ -355,46 +354,47 @@ type perflibHTTPProxy struct {
ProxyRequestsPerSec float64 `perflib:"Proxy Requests/Sec"` ProxyRequestsPerSec float64 `perflib:"Proxy Requests/Sec"`
} }
func (c *collector) collectHTTPProxy(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectHTTPProxy(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibHTTPProxy var data []perflibHTTPProxy
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange HttpProxy"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange HttpProxy"], &data, logger); err != nil {
return err return err
} }
for _, instance := range data { for _, instance := range data {
labelName := c.toLabelName(instance.Name) labelName := c.toLabelName(instance.Name)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MailboxServerLocatorAverageLatency, c.mailboxServerLocatorAverageLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
c.msToSec(instance.MailboxServerLocatorAverageLatency), c.msToSec(instance.MailboxServerLocatorAverageLatency),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AverageAuthenticationLatency, c.averageAuthenticationLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
instance.AverageAuthenticationLatency, instance.AverageAuthenticationLatency,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AverageCASProcessingLatency, c.averageCASProcessingLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
c.msToSec(instance.AverageCASProcessingLatency), c.msToSec(instance.AverageCASProcessingLatency),
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MailboxServerProxyFailureRate, c.mailboxServerProxyFailureRate,
prometheus.GaugeValue, prometheus.GaugeValue,
instance.MailboxServerProxyFailureRate, instance.MailboxServerProxyFailureRate,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.OutstandingProxyRequests, c.outstandingProxyRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
instance.OutstandingProxyRequests, instance.OutstandingProxyRequests,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ProxyRequestsPerSec, c.proxyRequestsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
instance.ProxyRequestsPerSec, instance.ProxyRequestsPerSec,
labelName, labelName,
@@ -403,26 +403,27 @@ func (c *collector) collectHTTPProxy(ctx *types.ScrapeContext, ch chan<- prometh
return nil return nil
} }
// Perflib: [24618] MSExchange OWA // Perflib: [24618] MSExchange OWA.
type perflibOWA struct { type perflibOWA struct {
CurrentUniqueUsers float64 `perflib:"Current Unique Users"` CurrentUniqueUsers float64 `perflib:"Current Unique Users"`
RequestsPerSec float64 `perflib:"Requests/sec"` RequestsPerSec float64 `perflib:"Requests/sec"`
} }
func (c *collector) collectOWA(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectOWA(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibOWA var data []perflibOWA
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange OWA"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange OWA"], &data, logger); err != nil {
return err return err
} }
for _, owa := range data { for _, owa := range data {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CurrentUniqueUsers, c.currentUniqueUsers,
prometheus.GaugeValue, prometheus.GaugeValue,
owa.CurrentUniqueUsers, owa.CurrentUniqueUsers,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.OWARequestsPerSec, c.owaRequestsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
owa.RequestsPerSec, owa.RequestsPerSec,
) )
@@ -430,32 +431,33 @@ func (c *collector) collectOWA(ctx *types.ScrapeContext, ch chan<- prometheus.Me
return nil return nil
} }
// Perflib: [25138] MSExchange ActiveSync // Perflib: [25138] MSExchange ActiveSync.
type perflibActiveSync struct { type perflibActiveSync struct {
RequestsPerSec float64 `perflib:"Requests/sec"` RequestsPerSec float64 `perflib:"Requests/sec"`
PingCommandsPending float64 `perflib:"Ping Commands Pending"` PingCommandsPending float64 `perflib:"Ping Commands Pending"`
SyncCommandsPerSec float64 `perflib:"Sync Commands/sec"` SyncCommandsPerSec float64 `perflib:"Sync Commands/sec"`
} }
func (c *collector) collectActiveSync(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectActiveSync(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibActiveSync var data []perflibActiveSync
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange ActiveSync"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange ActiveSync"], &data, logger); err != nil {
return err return err
} }
for _, instance := range data { for _, instance := range data {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ActiveSyncRequestsPerSec, c.activeSyncRequestsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
instance.RequestsPerSec, instance.RequestsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PingCommandsPending, c.pingCommandsPending,
prometheus.GaugeValue, prometheus.GaugeValue,
instance.PingCommandsPending, instance.PingCommandsPending,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SyncCommandsPerSec, c.syncCommandsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
instance.SyncCommandsPerSec, instance.SyncCommandsPerSec,
) )
@@ -463,7 +465,7 @@ func (c *collector) collectActiveSync(ctx *types.ScrapeContext, ch chan<- promet
return nil return nil
} }
// Perflib: [29366] MSExchange RpcClientAccess // Perflib: [29366] MSExchange RpcClientAccess.
type perflibRPCClientAccess struct { type perflibRPCClientAccess struct {
RPCAveragedLatency float64 `perflib:"RPC Averaged Latency"` RPCAveragedLatency float64 `perflib:"RPC Averaged Latency"`
RPCRequests float64 `perflib:"RPC Requests"` RPCRequests float64 `perflib:"RPC Requests"`
@@ -473,40 +475,41 @@ type perflibRPCClientAccess struct {
UserCount float64 `perflib:"User Count"` UserCount float64 `perflib:"User Count"`
} }
func (c *collector) collectRPC(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectRPC(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibRPCClientAccess var data []perflibRPCClientAccess
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange RpcClientAccess"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange RpcClientAccess"], &data, logger); err != nil {
return err return err
} }
for _, rpc := range data { for _, rpc := range data {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RPCAveragedLatency, c.rpcAveragedLatency,
prometheus.GaugeValue, prometheus.GaugeValue,
c.msToSec(rpc.RPCAveragedLatency), c.msToSec(rpc.RPCAveragedLatency),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RPCRequests, c.rpcRequests,
prometheus.GaugeValue, prometheus.GaugeValue,
rpc.RPCRequests, rpc.RPCRequests,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ActiveUserCount, c.activeUserCount,
prometheus.GaugeValue, prometheus.GaugeValue,
rpc.ActiveUserCount, rpc.ActiveUserCount,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ConnectionCount, c.connectionCount,
prometheus.GaugeValue, prometheus.GaugeValue,
rpc.ConnectionCount, rpc.ConnectionCount,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RPCOperationsPerSec, c.rpcOperationsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
rpc.RPCOperationsPerSec, rpc.RPCOperationsPerSec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.UserCount, c.userCount,
prometheus.GaugeValue, prometheus.GaugeValue,
rpc.UserCount, rpc.UserCount,
) )
@@ -515,7 +518,7 @@ func (c *collector) collectRPC(ctx *types.ScrapeContext, ch chan<- prometheus.Me
return nil return nil
} }
// Perflib: [20524] MSExchangeTransport Queues // Perflib: [20524] MSExchangeTransport Queues.
type perflibTransportQueues struct { type perflibTransportQueues struct {
Name string Name string
@@ -529,9 +532,10 @@ type perflibTransportQueues struct {
PoisonQueueLength float64 `perflib:"Poison Queue Length"` PoisonQueueLength float64 `perflib:"Poison Queue Length"`
} }
func (c *collector) collectTransportQueues(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectTransportQueues(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibTransportQueues var data []perflibTransportQueues
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchangeTransport Queues"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchangeTransport Queues"], &data, logger); err != nil {
return err return err
} }
@@ -541,49 +545,49 @@ func (c *collector) collectTransportQueues(ctx *types.ScrapeContext, ch chan<- p
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ExternalActiveRemoteDeliveryQueueLength, c.externalActiveRemoteDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.ExternalActiveRemoteDeliveryQueueLength, queue.ExternalActiveRemoteDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.InternalActiveRemoteDeliveryQueueLength, c.internalActiveRemoteDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.InternalActiveRemoteDeliveryQueueLength, queue.InternalActiveRemoteDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ActiveMailboxDeliveryQueueLength, c.activeMailboxDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.ActiveMailboxDeliveryQueueLength, queue.ActiveMailboxDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RetryMailboxDeliveryQueueLength, c.retryMailboxDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.RetryMailboxDeliveryQueueLength, queue.RetryMailboxDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.UnreachableQueueLength, c.unreachableQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.UnreachableQueueLength, queue.UnreachableQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ExternalLargestDeliveryQueueLength, c.externalLargestDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.ExternalLargestDeliveryQueueLength, queue.ExternalLargestDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.InternalLargestDeliveryQueueLength, c.internalLargestDeliveryQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.InternalLargestDeliveryQueueLength, queue.InternalLargestDeliveryQueueLength,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PoisonQueueLength, c.poisonQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
queue.PoisonQueueLength, queue.PoisonQueueLength,
labelName, labelName,
@@ -592,7 +596,7 @@ func (c *collector) collectTransportQueues(ctx *types.ScrapeContext, ch chan<- p
return nil return nil
} }
// Perflib: [19430] MSExchange WorkloadManagement Workloads // Perflib: [19430] MSExchange WorkloadManagement Workloads.
type perflibWorkloadManagementWorkloads struct { type perflibWorkloadManagementWorkloads struct {
Name string Name string
@@ -603,9 +607,10 @@ type perflibWorkloadManagementWorkloads struct {
IsActive float64 `perflib:"Active"` IsActive float64 `perflib:"Active"`
} }
func (c *collector) collectWorkloadManagementWorkloads(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectWorkloadManagementWorkloads(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibWorkloadManagementWorkloads var data []perflibWorkloadManagementWorkloads
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange WorkloadManagement Workloads"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange WorkloadManagement Workloads"], &data, logger); err != nil {
return err return err
} }
@@ -615,31 +620,31 @@ func (c *collector) collectWorkloadManagementWorkloads(ctx *types.ScrapeContext,
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ActiveTasks, c.activeTasks,
prometheus.GaugeValue, prometheus.GaugeValue,
instance.ActiveTasks, instance.ActiveTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CompletedTasks, c.completedTasks,
prometheus.CounterValue, prometheus.CounterValue,
instance.CompletedTasks, instance.CompletedTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.QueuedTasks, c.queuedTasks,
prometheus.CounterValue, prometheus.CounterValue,
instance.QueuedTasks, instance.QueuedTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.YieldedTasks, c.yieldedTasks,
prometheus.CounterValue, prometheus.CounterValue,
instance.YieldedTasks, instance.YieldedTasks,
labelName, labelName,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.IsActive, c.isActive,
prometheus.GaugeValue, prometheus.GaugeValue,
instance.IsActive, instance.IsActive,
labelName, labelName,
@@ -649,19 +654,20 @@ func (c *collector) collectWorkloadManagementWorkloads(ctx *types.ScrapeContext,
return nil return nil
} }
// [29240] MSExchangeAutodiscover // [29240] MSExchangeAutodiscover.
type perflibAutodiscover struct { type perflibAutodiscover struct {
RequestsPerSec float64 `perflib:"Requests/sec"` RequestsPerSec float64 `perflib:"Requests/sec"`
} }
func (c *collector) collectAutoDiscover(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectAutoDiscover(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibAutodiscover var data []perflibAutodiscover
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchangeAutodiscover"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchangeAutodiscover"], &data, logger); err != nil {
return err return err
} }
for _, autodisc := range data { for _, autodisc := range data {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AutodiscoverRequestsPerSec, c.autoDiscoverRequestsPerSec,
prometheus.CounterValue, prometheus.CounterValue,
autodisc.RequestsPerSec, autodisc.RequestsPerSec,
) )
@@ -669,20 +675,21 @@ func (c *collector) collectAutoDiscover(ctx *types.ScrapeContext, ch chan<- prom
return nil return nil
} }
// perflib [26463] MSExchange MapiHttp Emsmdb // perflib [26463] MSExchange MapiHttp Emsmdb.
type perflibMapiHttpEmsmdb struct { type perflibMapiHttpEmsmdb struct {
ActiveUserCount float64 `perflib:"Active User Count"` ActiveUserCount float64 `perflib:"Active User Count"`
} }
func (c *collector) collectMapiHttpEmsmdb(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectMapiHttpEmsmdb(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var data []perflibMapiHttpEmsmdb var data []perflibMapiHttpEmsmdb
if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange MapiHttp Emsmdb"], &data, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange MapiHttp Emsmdb"], &data, logger); err != nil {
return err return err
} }
for _, mapihttp := range data { for _, mapihttp := range data {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ActiveUserCountMapiHttpEmsmdb, c.activeUserCountMapiHttpEmsMDB,
prometheus.GaugeValue, prometheus.GaugeValue,
mapihttp.ActiveUserCount, mapihttp.ActiveUserCount,
) )
@@ -691,14 +698,14 @@ func (c *collector) collectMapiHttpEmsmdb(ctx *types.ScrapeContext, ch chan<- pr
return nil return nil
} }
// toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores // toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores.
func (c *collector) toLabelName(name string) string { func (c *Collector) toLabelName(name string) string {
s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_") s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_")
s = strings.ReplaceAll(s, "__", "_") s = strings.ReplaceAll(s, "__", "_")
return s return s
} }
// msToSec converts from ms to seconds // msToSec converts from ms to seconds.
func (c *collector) msToSec(t float64) float64 { func (c *Collector) msToSec(t float64) float64 {
return t / 1000 return t / 1000
} }

View File

@@ -3,14 +3,15 @@
package fsrmquota package fsrmquota
import ( import (
"github.com/prometheus-community/windows_exporter/pkg/types" "errors"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "fsrmquota" const Name = "fsrmquota"
@@ -19,94 +20,106 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
QuotasCount *prometheus.Desc quotasCount *prometheus.Desc
Path *prometheus.Desc peakUsage *prometheus.Desc
PeakUsage *prometheus.Desc size *prometheus.Desc
Size *prometheus.Desc usage *prometheus.Desc
Usage *prometheus.Desc
Description *prometheus.Desc description *prometheus.Desc
Disabled *prometheus.Desc disabled *prometheus.Desc
MatchesTemplate *prometheus.Desc matchesTemplate *prometheus.Desc
SoftLimit *prometheus.Desc softLimit *prometheus.Desc
Template *prometheus.Desc template *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.QuotasCount = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.quotasCount = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "count"), prometheus.BuildFQName(types.Namespace, Name, "count"),
"Number of Quotas", "Number of Quotas",
nil, nil,
nil, nil,
) )
c.PeakUsage = prometheus.NewDesc( c.peakUsage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "peak_usage_bytes"), prometheus.BuildFQName(types.Namespace, Name, "peak_usage_bytes"),
"The highest amount of disk space usage charged to this quota. (PeakUsage)", "The highest amount of disk space usage charged to this quota. (PeakUsage)",
[]string{"path", "template"}, []string{"path", "template"},
nil, nil,
) )
c.Size = prometheus.NewDesc( c.size = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "size_bytes"), prometheus.BuildFQName(types.Namespace, Name, "size_bytes"),
"The size of the quota. (Size)", "The size of the quota. (Size)",
[]string{"path", "template"}, []string{"path", "template"},
nil, nil,
) )
c.Usage = prometheus.NewDesc( c.usage = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "usage_bytes"), prometheus.BuildFQName(types.Namespace, Name, "usage_bytes"),
"The current amount of disk space usage charged to this quota. (Usage)", "The current amount of disk space usage charged to this quota. (Usage)",
[]string{"path", "template"}, []string{"path", "template"},
nil, nil,
) )
c.Description = prometheus.NewDesc( c.description = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "description"), prometheus.BuildFQName(types.Namespace, Name, "description"),
"Description of the quota (Description)", "Description of the quota (Description)",
[]string{"path", "template", "description"}, []string{"path", "template", "description"},
nil, nil,
) )
c.Disabled = prometheus.NewDesc( c.disabled = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "disabled"), prometheus.BuildFQName(types.Namespace, Name, "disabled"),
"If 1, the quota is disabled. The default value is 0. (Disabled)", "If 1, the quota is disabled. The default value is 0. (Disabled)",
[]string{"path", "template"}, []string{"path", "template"},
nil, nil,
) )
c.SoftLimit = prometheus.NewDesc( c.softLimit = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "softlimit"), prometheus.BuildFQName(types.Namespace, Name, "softlimit"),
"If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)", "If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)",
[]string{"path", "template"}, []string{"path", "template"},
nil, nil,
) )
c.Template = prometheus.NewDesc( c.template = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "template"), prometheus.BuildFQName(types.Namespace, Name, "template"),
"Quota template name. (Template)", "Quota template name. (Template)",
[]string{"path", "template"}, []string{"path", "template"},
nil, nil,
) )
c.MatchesTemplate = prometheus.NewDesc( c.matchesTemplate = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "matchestemplate"), prometheus.BuildFQName(types.Namespace, Name, "matchestemplate"),
"If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)", "If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)",
[]string{"path", "template"}, []string{"path", "template"},
@@ -117,9 +130,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", "failed collecting fsrmquota metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting fsrmquota metrics", "err", err)
return err return err
} }
return nil return nil
@@ -142,66 +156,63 @@ type MSFT_FSRMQuota struct {
SoftLimit bool SoftLimit bool
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []MSFT_FSRMQuota var dst []MSFT_FSRMQuota
q := wmi.QueryAll(&dst, c.logger)
var count int var count int
if err := wmi.QueryNamespace(q, &dst, "root/microsoft/windows/fsrm"); err != nil { if err := c.wmiClient.Query("SELECT * FROM MSFT_FSRMQuota", &dst, nil, "root/microsoft/windows/fsrm"); err != nil {
return nil, err return err
} }
for _, quota := range dst { for _, quota := range dst {
count++ count++
path := quota.Path path := quota.Path
template := quota.Template template := quota.Template
Description := quota.Description Description := quota.Description
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PeakUsage, c.peakUsage,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(quota.PeakUsage), float64(quota.PeakUsage),
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Size, c.size,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(quota.Size), float64(quota.Size),
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Usage, c.usage,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(quota.Usage), float64(quota.Usage),
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Description, c.description,
prometheus.GaugeValue, prometheus.GaugeValue,
1.0, 1.0,
path, template, Description, path, template, Description,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Disabled, c.disabled,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.BoolToFloat(quota.Disabled), utils.BoolToFloat(quota.Disabled),
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MatchesTemplate, c.matchesTemplate,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.BoolToFloat(quota.MatchesTemplate), utils.BoolToFloat(quota.MatchesTemplate),
path, path,
template, template,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SoftLimit, c.softLimit,
prometheus.GaugeValue, prometheus.GaugeValue,
utils.BoolToFloat(quota.SoftLimit), utils.BoolToFloat(quota.SoftLimit),
path, path,
@@ -210,9 +221,9 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.QuotasCount, c.quotasCount,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(count), float64(count),
) )
return nil, nil return nil
} }

View File

@@ -11,16 +11,16 @@ import (
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/google/uuid"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/collectors/version"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/version"
) )
func (c *Collectors) BuildServeHTTP(disableExporterMetrics bool, timeoutMargin float64) http.HandlerFunc { func (c *Collectors) BuildServeHTTP(logger log.Logger, disableExporterMetrics bool, timeoutMargin float64) http.HandlerFunc {
collectorFactory := func(timeout time.Duration, requestedCollectors []string) (error, *Prometheus) { collectorFactory := func(timeout time.Duration, requestedCollectors []string) (error, *Prometheus) {
filteredCollectors := make(map[string]types.Collector) filteredCollectors := make(map[string]Collector)
// scrape all enabled collectors if no collector is requested // scrape all enabled collectors if no collector is requested
if len(requestedCollectors) == 0 { if len(requestedCollectors) == 0 {
filteredCollectors = c.collectors filteredCollectors = c.collectors
@@ -32,10 +32,18 @@ func (c *Collectors) BuildServeHTTP(disableExporterMetrics bool, timeoutMargin f
} }
filteredCollectors[name] = col filteredCollectors[name] = col
} }
return nil, NewPrometheus(timeout, c, c.logger)
filtered := Collectors{
collectors: filteredCollectors,
perfCounterQuery: c.perfCounterQuery,
}
return nil, NewPrometheus(timeout, &filtered, logger)
} }
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
logger := log.With(logger, "remote", r.RemoteAddr, "correlation_id", uuid.New().String())
const defaultTimeout = 10.0 const defaultTimeout = 10.0
var timeoutSeconds float64 var timeoutSeconds float64
@@ -43,20 +51,20 @@ func (c *Collectors) BuildServeHTTP(disableExporterMetrics bool, timeoutMargin f
var err error var err error
timeoutSeconds, err = strconv.ParseFloat(v, 64) timeoutSeconds, err = strconv.ParseFloat(v, 64)
if err != nil { if err != nil {
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Couldn't parse X-Prometheus-Scrape-Timeout-Seconds: %q. Defaulting timeout to %f", v, defaultTimeout)) _ = level.Warn(logger).Log("msg", fmt.Sprintf("Couldn't parse X-Prometheus-Scrape-Timeout-Seconds: %q. Defaulting timeout to %f", v, defaultTimeout))
} }
} }
if timeoutSeconds == 0 { if timeoutSeconds == 0 {
timeoutSeconds = defaultTimeout timeoutSeconds = defaultTimeout
} }
timeoutSeconds = timeoutSeconds - timeoutMargin timeoutSeconds -= timeoutMargin
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
err, wc := collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"]) err, wc := collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"])
if err != nil { if err != nil {
_ = level.Warn(c.logger).Log("msg", "Couldn't create filtered metrics handler", "err", err) _ = level.Warn(logger).Log("msg", "Couldn't create filtered metrics handler", "err", err)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err))) //nolint:errcheck _, _ = w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err)))
return return
} }
@@ -70,7 +78,7 @@ func (c *Collectors) BuildServeHTTP(disableExporterMetrics bool, timeoutMargin f
} }
h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{ h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{
ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(c.logger)), "", stdlog.Lshortfile), ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(logger)), "", stdlog.Lshortfile),
}) })
h.ServeHTTP(w, r) h.ServeHTTP(w, r)
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,8 @@ import (
) )
func TestIISDeduplication(t *testing.T) { func TestIISDeduplication(t *testing.T) {
t.Parallel()
start := []perflibAPP_POOL_WAS{ start := []perflibAPP_POOL_WAS{
{ {
Name: "foo", Name: "foo",

View File

@@ -0,0 +1,102 @@
//go:build windows
package license
import (
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/headers/slc"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
const Name = "license"
var labelMap = map[slc.SL_GENUINE_STATE]string{
slc.SL_GEN_STATE_IS_GENUINE: "genuine",
slc.SL_GEN_STATE_INVALID_LICENSE: "invalid_license",
slc.SL_GEN_STATE_TAMPERED: "tampered",
slc.SL_GEN_STATE_OFFLINE: "offline",
slc.SL_GEN_STATE_LAST: "last",
}
type Config struct{}
var ConfigDefaults = Config{}
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_DNS_DNS metrics.
type Collector struct {
config Config
licenseStatus *prometheus.Desc
}
func New(config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c
}
func NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{}
}
func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
return []string{}, nil
}
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.licenseStatus = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "status"),
"Status of windows license",
[]string{"state"},
nil,
)
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting license metrics", "err", err)
return err
}
return nil
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
status, err := slc.SLIsWindowsGenuineLocal()
if err != nil {
return err
}
for k, v := range labelMap {
val := 0.0
if status == k {
val = 1.0
}
ch <- prometheus.MustNewConstMetric(c.licenseStatus, prometheus.GaugeValue, val, v)
}
return nil
}

View File

@@ -0,0 +1,12 @@
package license_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/pkg/collector/license"
"github.com/prometheus-community/windows_exporter/pkg/testutils"
)
func BenchmarkCollector(b *testing.B) {
testutils.FuncBenchmarkCollector(b, license.Name, license.NewWithFlags)
}

View File

@@ -3,8 +3,12 @@
package logical_disk package logical_disk
import ( import (
"encoding/binary"
"fmt" "fmt"
"regexp" "regexp"
"slices"
"strconv"
"strings"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
@@ -12,225 +16,256 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows"
) )
const ( const Name = "logical_disk"
Name = "logical_disk"
FlagLogicalDiskVolumeExclude = "collector.logical_disk.volume-exclude"
FlagLogicalDiskVolumeInclude = "collector.logical_disk.volume-include"
)
type Config struct { type Config struct {
VolumeInclude string `yaml:"volume_include"` VolumeInclude *regexp.Regexp `yaml:"volume_include"`
VolumeExclude string `yaml:"volume_exclude"` VolumeExclude *regexp.Regexp `yaml:"volume_exclude"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
VolumeInclude: ".+", VolumeInclude: types.RegExpAny,
VolumeExclude: "", VolumeExclude: types.RegExpEmpty,
} }
// A collector is a Prometheus collector for perflib logicalDisk metrics // A Collector is a Prometheus Collector for perflib logicalDisk metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
volumeInclude *string avgReadQueue *prometheus.Desc
volumeExclude *string avgWriteQueue *prometheus.Desc
freeSpace *prometheus.Desc
RequestsQueued *prometheus.Desc idleTime *prometheus.Desc
AvgReadQueue *prometheus.Desc information *prometheus.Desc
AvgWriteQueue *prometheus.Desc readBytesTotal *prometheus.Desc
ReadBytesTotal *prometheus.Desc readLatency *prometheus.Desc
ReadsTotal *prometheus.Desc readOnly *prometheus.Desc
WriteBytesTotal *prometheus.Desc readsTotal *prometheus.Desc
WritesTotal *prometheus.Desc readTime *prometheus.Desc
ReadTime *prometheus.Desc readWriteLatency *prometheus.Desc
WriteTime *prometheus.Desc requestsQueued *prometheus.Desc
TotalSpace *prometheus.Desc splitIOs *prometheus.Desc
FreeSpace *prometheus.Desc totalSpace *prometheus.Desc
IdleTime *prometheus.Desc writeBytesTotal *prometheus.Desc
SplitIOs *prometheus.Desc writeLatency *prometheus.Desc
ReadLatency *prometheus.Desc writesTotal *prometheus.Desc
WriteLatency *prometheus.Desc writeTime *prometheus.Desc
ReadWriteLatency *prometheus.Desc
volumeIncludePattern *regexp.Regexp
volumeExcludePattern *regexp.Regexp
} }
func New(logger log.Logger, config *Config) types.Collector { type volumeInfo struct {
filesystem string
serialNumber string
label string
volumeType string
readonly float64
}
func New(config *Config) *Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &collector{ if config.VolumeExclude == nil {
volumeExclude: &config.VolumeExclude, config.VolumeExclude = ConfigDefaults.VolumeExclude
volumeInclude: &config.VolumeInclude,
} }
c.SetLogger(logger)
return c
}
func NewWithFlags(app *kingpin.Application) types.Collector { if config.VolumeInclude == nil {
c := &collector{ config.VolumeInclude = ConfigDefaults.VolumeInclude
volumeInclude: app.Flag( }
FlagLogicalDiskVolumeInclude,
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.", c := &Collector{
).Default(ConfigDefaults.VolumeInclude).String(), config: *config,
volumeExclude: app.Flag(
FlagLogicalDiskVolumeExclude,
"Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.VolumeExclude).String(),
} }
return c return c
} }
func (c *collector) GetName() string { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
config: ConfigDefaults,
}
var volumeExclude, volumeInclude string
app.Flag(
"collector.logical_disk.volume-exclude",
"Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.",
).Default(c.config.VolumeExclude.String()).StringVar(&volumeExclude)
app.Flag(
"collector.logical_disk.volume-include",
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.",
).Default(c.config.VolumeInclude.String()).StringVar(&volumeInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.VolumeExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeExclude))
if err != nil {
return fmt.Errorf("collector.logical_disk.volume-exclude: %w", err)
}
c.config.VolumeInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", volumeInclude))
if err != nil {
return fmt.Errorf("collector.logical_disk.volume-include: %w", err)
}
return nil
})
return c
}
func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"LogicalDisk"}, nil return []string{"LogicalDisk"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.RequestsQueued = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.information = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"),
"A metric with a constant '1' value labeled with logical disk information",
[]string{"disk", "type", "volume", "volume_name", "filesystem", "serial_number"},
nil,
)
c.readOnly = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "readonly"),
"Whether the logical disk is read-only",
[]string{"volume"},
nil,
)
c.requestsQueued = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "requests_queued"), prometheus.BuildFQName(types.Namespace, Name, "requests_queued"),
"The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)", "The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.AvgReadQueue = prometheus.NewDesc( c.avgReadQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "avg_read_requests_queued"), prometheus.BuildFQName(types.Namespace, Name, "avg_read_requests_queued"),
"Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)", "Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.AvgWriteQueue = prometheus.NewDesc( c.avgWriteQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "avg_write_requests_queued"), prometheus.BuildFQName(types.Namespace, Name, "avg_write_requests_queued"),
"Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)", "Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.ReadBytesTotal = prometheus.NewDesc( c.readBytesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "read_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "read_bytes_total"),
"The number of bytes transferred from the disk during read operations (LogicalDisk.DiskReadBytesPerSec)", "The number of bytes transferred from the disk during read operations (LogicalDisk.DiskReadBytesPerSec)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.ReadsTotal = prometheus.NewDesc( c.readsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "reads_total"), prometheus.BuildFQName(types.Namespace, Name, "reads_total"),
"The number of read operations on the disk (LogicalDisk.DiskReadsPerSec)", "The number of read operations on the disk (LogicalDisk.DiskReadsPerSec)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.WriteBytesTotal = prometheus.NewDesc( c.writeBytesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "write_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "write_bytes_total"),
"The number of bytes transferred to the disk during write operations (LogicalDisk.DiskWriteBytesPerSec)", "The number of bytes transferred to the disk during write operations (LogicalDisk.DiskWriteBytesPerSec)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.WritesTotal = prometheus.NewDesc( c.writesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "writes_total"), prometheus.BuildFQName(types.Namespace, Name, "writes_total"),
"The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)", "The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.ReadTime = prometheus.NewDesc( c.readTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "read_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "read_seconds_total"),
"Seconds that the disk was busy servicing read requests (LogicalDisk.PercentDiskReadTime)", "Seconds that the disk was busy servicing read requests (LogicalDisk.PercentDiskReadTime)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.WriteTime = prometheus.NewDesc( c.writeTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "write_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "write_seconds_total"),
"Seconds that the disk was busy servicing write requests (LogicalDisk.PercentDiskWriteTime)", "Seconds that the disk was busy servicing write requests (LogicalDisk.PercentDiskWriteTime)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.FreeSpace = prometheus.NewDesc( c.freeSpace = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "free_bytes"), prometheus.BuildFQName(types.Namespace, Name, "free_bytes"),
"Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)", "Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.TotalSpace = prometheus.NewDesc( c.totalSpace = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "size_bytes"), prometheus.BuildFQName(types.Namespace, Name, "size_bytes"),
"Total space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)", "Total space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.IdleTime = prometheus.NewDesc( c.idleTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "idle_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "idle_seconds_total"),
"Seconds that the disk was idle (LogicalDisk.PercentIdleTime)", "Seconds that the disk was idle (LogicalDisk.PercentIdleTime)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.SplitIOs = prometheus.NewDesc( c.splitIOs = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "split_ios_total"), prometheus.BuildFQName(types.Namespace, Name, "split_ios_total"),
"The number of I/Os to the disk were split into multiple I/Os (LogicalDisk.SplitIOPerSec)", "The number of I/Os to the disk were split into multiple I/Os (LogicalDisk.SplitIOPerSec)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.ReadLatency = prometheus.NewDesc( c.readLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "read_latency_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "read_latency_seconds_total"),
"Shows the average time, in seconds, of a read operation from the disk (LogicalDisk.AvgDiskSecPerRead)", "Shows the average time, in seconds, of a read operation from the disk (LogicalDisk.AvgDiskSecPerRead)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.WriteLatency = prometheus.NewDesc( c.writeLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "write_latency_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "write_latency_seconds_total"),
"Shows the average time, in seconds, of a write operation to the disk (LogicalDisk.AvgDiskSecPerWrite)", "Shows the average time, in seconds, of a write operation to the disk (LogicalDisk.AvgDiskSecPerWrite)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
c.ReadWriteLatency = prometheus.NewDesc( c.readWriteLatency = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "read_write_latency_seconds_total"), prometheus.BuildFQName(types.Namespace, Name, "read_write_latency_seconds_total"),
"Shows the time, in seconds, of the average disk transfer (LogicalDisk.AvgDiskSecPerTransfer)", "Shows the time, in seconds, of the average disk transfer (LogicalDisk.AvgDiskSecPerTransfer)",
[]string{"volume"}, []string{"volume"},
nil, nil,
) )
var err error
c.volumeIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeInclude))
if err != nil {
return err
}
c.volumeExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeExclude))
if err != nil {
return err
}
return nil return nil
} }
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting logical_disk metrics", "desc", desc, "err", err) if err := c.collect(ctx, logger, ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting logical_disk metrics", "err", err)
return err return err
} }
return nil return nil
@@ -238,7 +273,7 @@ func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
// Win32_PerfRawData_PerfDisk_LogicalDisk docs: // Win32_PerfRawData_PerfDisk_LogicalDisk docs:
// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class // - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class
// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference // - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference.
type logicalDisk struct { type logicalDisk struct {
Name string Name string
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`
@@ -259,131 +294,261 @@ type logicalDisk struct {
AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"` AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"`
} }
func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
var dst []logicalDisk logger = log.With(logger, "collector", Name)
if err := perflib.UnmarshalObject(ctx.PerfObjects["LogicalDisk"], &dst, c.logger); err != nil { var (
return nil, err err error
diskID string
info volumeInfo
dst []logicalDisk
)
if err = perflib.UnmarshalObject(ctx.PerfObjects["LogicalDisk"], &dst, logger); err != nil {
return err
} }
for _, volume := range dst { for _, volume := range dst {
if volume.Name == "_Total" || if volume.Name == "_Total" ||
c.volumeExcludePattern.MatchString(volume.Name) || c.config.VolumeExclude.MatchString(volume.Name) ||
!c.volumeIncludePattern.MatchString(volume.Name) { !c.config.VolumeInclude.MatchString(volume.Name) {
continue continue
} }
diskID, err = getDiskIDByVolume(volume.Name)
if err != nil {
_ = level.Warn(logger).Log("msg", "failed to get disk ID for "+volume.Name, "err", err)
}
info, err = getVolumeInfo(volume.Name)
if err != nil {
_ = level.Warn(logger).Log("msg", "failed to get volume information for %s"+volume.Name, "err", err)
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RequestsQueued, c.information,
prometheus.GaugeValue,
1,
diskID,
info.volumeType,
volume.Name,
info.label,
info.filesystem,
info.serialNumber,
)
ch <- prometheus.MustNewConstMetric(
c.requestsQueued,
prometheus.GaugeValue, prometheus.GaugeValue,
volume.CurrentDiskQueueLength, volume.CurrentDiskQueueLength,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AvgReadQueue, c.avgReadQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
volume.AvgDiskReadQueueLength*perflib.TicksToSecondScaleFactor, volume.AvgDiskReadQueueLength*perflib.TicksToSecondScaleFactor,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AvgWriteQueue, c.avgWriteQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
volume.AvgDiskWriteQueueLength*perflib.TicksToSecondScaleFactor, volume.AvgDiskWriteQueueLength*perflib.TicksToSecondScaleFactor,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadBytesTotal, c.readBytesTotal,
prometheus.CounterValue, prometheus.CounterValue,
volume.DiskReadBytesPerSec, volume.DiskReadBytesPerSec,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadsTotal, c.readsTotal,
prometheus.CounterValue, prometheus.CounterValue,
volume.DiskReadsPerSec, volume.DiskReadsPerSec,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WriteBytesTotal, c.writeBytesTotal,
prometheus.CounterValue, prometheus.CounterValue,
volume.DiskWriteBytesPerSec, volume.DiskWriteBytesPerSec,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WritesTotal, c.writesTotal,
prometheus.CounterValue, prometheus.CounterValue,
volume.DiskWritesPerSec, volume.DiskWritesPerSec,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadTime, c.readTime,
prometheus.CounterValue, prometheus.CounterValue,
volume.PercentDiskReadTime, volume.PercentDiskReadTime,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WriteTime, c.writeTime,
prometheus.CounterValue, prometheus.CounterValue,
volume.PercentDiskWriteTime, volume.PercentDiskWriteTime,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FreeSpace, c.freeSpace,
prometheus.GaugeValue, prometheus.GaugeValue,
volume.PercentFreeSpace_Base*1024*1024, volume.PercentFreeSpace_Base*1024*1024,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalSpace, c.totalSpace,
prometheus.GaugeValue, prometheus.GaugeValue,
volume.PercentFreeSpace*1024*1024, volume.PercentFreeSpace*1024*1024,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.IdleTime, c.idleTime,
prometheus.CounterValue, prometheus.CounterValue,
volume.PercentIdleTime, volume.PercentIdleTime,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SplitIOs, c.splitIOs,
prometheus.CounterValue, prometheus.CounterValue,
volume.SplitIOPerSec, volume.SplitIOPerSec,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadLatency, c.readLatency,
prometheus.CounterValue, prometheus.CounterValue,
volume.AvgDiskSecPerRead*perflib.TicksToSecondScaleFactor, volume.AvgDiskSecPerRead*perflib.TicksToSecondScaleFactor,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WriteLatency, c.writeLatency,
prometheus.CounterValue, prometheus.CounterValue,
volume.AvgDiskSecPerWrite*perflib.TicksToSecondScaleFactor, volume.AvgDiskSecPerWrite*perflib.TicksToSecondScaleFactor,
volume.Name, volume.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ReadWriteLatency, c.readWriteLatency,
prometheus.CounterValue, prometheus.CounterValue,
volume.AvgDiskSecPerTransfer*perflib.TicksToSecondScaleFactor, volume.AvgDiskSecPerTransfer*perflib.TicksToSecondScaleFactor,
volume.Name, volume.Name,
) )
} }
return nil, nil return nil
}
func getDriveType(driveType uint32) string {
switch driveType {
case windows.DRIVE_UNKNOWN:
return "unknown"
case windows.DRIVE_NO_ROOT_DIR:
return "norootdir"
case windows.DRIVE_REMOVABLE:
return "removable"
case windows.DRIVE_FIXED:
return "fixed"
case windows.DRIVE_REMOTE:
return "remote"
case windows.DRIVE_CDROM:
return "cdrom"
case windows.DRIVE_RAMDISK:
return "ramdisk"
default:
return "unknown"
}
}
// diskExtentSize Size of the DiskExtent structure in bytes.
const diskExtentSize = 24
// getDiskIDByVolume returns the disk ID for a given volume.
func getDiskIDByVolume(rootDrive string) (string, error) {
// Open a volume handle to the Disk Root.
var err error
var f windows.Handle
// mode has to include FILE_SHARE permission to allow concurrent access to the disk.
// use 0 as access mode to avoid admin permission.
mode := uint32(windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE)
f, err = windows.CreateFile(
windows.StringToUTF16Ptr(`\\.\`+rootDrive),
0, mode, nil, windows.OPEN_EXISTING, uint32(windows.FILE_ATTRIBUTE_READONLY), 0)
if err != nil {
return "", err
}
defer windows.Close(f)
controlCode := uint32(5636096) // IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
volumeDiskExtents := make([]byte, 16*1024)
var bytesReturned uint32
err = windows.DeviceIoControl(f, controlCode, nil, 0, &volumeDiskExtents[0], uint32(len(volumeDiskExtents)), &bytesReturned, nil)
if err != nil {
return "", fmt.Errorf("could not identify physical drive for %s: %w", rootDrive, err)
}
numDiskIDs := uint(binary.LittleEndian.Uint32(volumeDiskExtents))
if numDiskIDs < 1 {
return "", fmt.Errorf("could not identify physical drive for %s: no disk IDs returned", rootDrive)
}
diskIDs := make([]string, numDiskIDs)
for i := range numDiskIDs {
diskIDs[i] = strconv.FormatUint(uint64(binary.LittleEndian.Uint32(volumeDiskExtents[8+i*diskExtentSize:])), 10)
}
slices.Sort(diskIDs)
diskIDs = slices.Compact(diskIDs)
return strings.Join(diskIDs, ";"), nil
}
func getVolumeInfo(rootDrive string) (volumeInfo, error) {
if !strings.HasSuffix(rootDrive, ":") {
return volumeInfo{}, nil
}
volPath := windows.StringToUTF16Ptr(rootDrive + `\`)
volBufLabel := make([]uint16, windows.MAX_PATH+1)
volSerialNum := uint32(0)
fsFlags := uint32(0)
volBufType := make([]uint16, windows.MAX_PATH+1)
driveType := windows.GetDriveType(volPath)
err := windows.GetVolumeInformation(volPath, &volBufLabel[0], uint32(len(volBufLabel)),
&volSerialNum, nil, &fsFlags, &volBufType[0], uint32(len(volBufType)))
if err != nil {
if driveType != windows.DRIVE_CDROM && driveType != windows.DRIVE_REMOVABLE {
return volumeInfo{}, err
}
return volumeInfo{}, nil
}
return volumeInfo{
volumeType: getDriveType(driveType),
label: windows.UTF16PtrToString(&volBufLabel[0]),
filesystem: windows.UTF16PtrToString(&volBufType[0]),
serialNumber: fmt.Sprintf("%X", volSerialNum),
readonly: float64(fsFlags & windows.FILE_READ_ONLY_VOLUME),
}, nil
} }

View File

@@ -9,8 +9,8 @@ import (
) )
func BenchmarkCollector(b *testing.B) { func BenchmarkCollector(b *testing.B) {
// Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all disks. // Whitelist is not set in testing context (kingpin flags not parsed), causing the Collector to skip all disks.
localVolumeInclude := ".+" localVolumeInclude := ".+"
kingpin.CommandLine.GetArg(logical_disk.FlagLogicalDiskVolumeInclude).StringVar(&localVolumeInclude) kingpin.CommandLine.GetArg("collector.logical_disk.volume-include").StringVar(&localVolumeInclude)
testutils.FuncBenchmarkCollector(b, "logical_disk", logical_disk.NewWithFlags) testutils.FuncBenchmarkCollector(b, "logical_disk", logical_disk.NewWithFlags)
} }

View File

@@ -5,13 +5,12 @@ package logon
import ( import (
"errors" "errors"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "logon" const Name = "logon"
@@ -20,37 +19,49 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI metrics // A Collector is a Prometheus Collector for WMI metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
LogonType *prometheus.Desc logonType *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.LogonType = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.logonType = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "logon_type"), prometheus.BuildFQName(types.Namespace, Name, "logon_type"),
"Number of active logon sessions (LogonSession.LogonType)", "Number of active logon sessions (LogonSession.LogonType)",
[]string{"status"}, []string{"status"},
@@ -61,9 +72,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting user metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting user metrics", "err", err)
return err return err
} }
return nil return nil
@@ -75,14 +87,13 @@ type Win32_LogonSession struct {
LogonType uint32 LogonType uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_LogonSession var dst []Win32_LogonSession
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_LogonSession", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
if len(dst) == 0 { if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set") return errors.New("WMI query returned empty result set")
} }
// Init counters // Init counters
@@ -132,94 +143,94 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(system), float64(system),
"system", "system",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(interactive), float64(interactive),
"interactive", "interactive",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(network), float64(network),
"network", "network",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(batch), float64(batch),
"batch", "batch",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(service), float64(service),
"service", "service",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(proxy), float64(proxy),
"proxy", "proxy",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(unlock), float64(unlock),
"unlock", "unlock",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(networkcleartext), float64(networkcleartext),
"network_clear_text", "network_clear_text",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(newcredentials), float64(newcredentials),
"new_credentials", "new_credentials",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(remoteinteractive), float64(remoteinteractive),
"remote_interactive", "remote_interactive",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(cachedinteractive), float64(cachedinteractive),
"cached_interactive", "cached_interactive",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(remoteinteractive), float64(remoteinteractive),
"cached_remote_interactive", "cached_remote_interactive",
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogonType, c.logonType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(cachedunlock), float64(cachedunlock),
"cached_unlock", "cached_unlock",
) )
return nil, nil return nil
} }

View File

@@ -8,6 +8,6 @@ import (
) )
func BenchmarkCollector(b *testing.B) { func BenchmarkCollector(b *testing.B) {
// No context name required as collector source is WMI // No context name required as Collector source is WMI
testutils.FuncBenchmarkCollector(b, logon.Name, logon.NewWithFlags) testutils.FuncBenchmarkCollector(b, logon.Name, logon.NewWithFlags)
} }

View File

@@ -1,6 +1,7 @@
package collector package collector
import ( import (
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/pkg/collector/ad" "github.com/prometheus-community/windows_exporter/pkg/collector/ad"
"github.com/prometheus-community/windows_exporter/pkg/collector/adcs" "github.com/prometheus-community/windows_exporter/pkg/collector/adcs"
"github.com/prometheus-community/windows_exporter/pkg/collector/adfs" "github.com/prometheus-community/windows_exporter/pkg/collector/adfs"
@@ -17,14 +18,11 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/fsrmquota" "github.com/prometheus-community/windows_exporter/pkg/collector/fsrmquota"
"github.com/prometheus-community/windows_exporter/pkg/collector/hyperv" "github.com/prometheus-community/windows_exporter/pkg/collector/hyperv"
"github.com/prometheus-community/windows_exporter/pkg/collector/iis" "github.com/prometheus-community/windows_exporter/pkg/collector/iis"
"github.com/prometheus-community/windows_exporter/pkg/collector/license"
"github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk" "github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk"
"github.com/prometheus-community/windows_exporter/pkg/collector/logon" "github.com/prometheus-community/windows_exporter/pkg/collector/logon"
"github.com/prometheus-community/windows_exporter/pkg/collector/memory" "github.com/prometheus-community/windows_exporter/pkg/collector/memory"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_cluster" "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_network"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_node"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resource"
"github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resourcegroup"
"github.com/prometheus-community/windows_exporter/pkg/collector/msmq" "github.com/prometheus-community/windows_exporter/pkg/collector/msmq"
"github.com/prometheus-community/windows_exporter/pkg/collector/mssql" "github.com/prometheus-community/windows_exporter/pkg/collector/mssql"
"github.com/prometheus-community/windows_exporter/pkg/collector/net" "github.com/prometheus-community/windows_exporter/pkg/collector/net"
@@ -39,11 +37,13 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/nps" "github.com/prometheus-community/windows_exporter/pkg/collector/nps"
"github.com/prometheus-community/windows_exporter/pkg/collector/os" "github.com/prometheus-community/windows_exporter/pkg/collector/os"
"github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk" "github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk"
"github.com/prometheus-community/windows_exporter/pkg/collector/printer"
"github.com/prometheus-community/windows_exporter/pkg/collector/process" "github.com/prometheus-community/windows_exporter/pkg/collector/process"
"github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx" "github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx"
"github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task" "github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task"
"github.com/prometheus-community/windows_exporter/pkg/collector/service" "github.com/prometheus-community/windows_exporter/pkg/collector/service"
"github.com/prometheus-community/windows_exporter/pkg/collector/smb" "github.com/prometheus-community/windows_exporter/pkg/collector/smb"
"github.com/prometheus-community/windows_exporter/pkg/collector/smbclient"
"github.com/prometheus-community/windows_exporter/pkg/collector/smtp" "github.com/prometheus-community/windows_exporter/pkg/collector/smtp"
"github.com/prometheus-community/windows_exporter/pkg/collector/system" "github.com/prometheus-community/windows_exporter/pkg/collector/system"
"github.com/prometheus-community/windows_exporter/pkg/collector/tcp" "github.com/prometheus-community/windows_exporter/pkg/collector/tcp"
@@ -54,67 +54,70 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/collector/time" "github.com/prometheus-community/windows_exporter/pkg/collector/time"
"github.com/prometheus-community/windows_exporter/pkg/collector/vmware" "github.com/prometheus-community/windows_exporter/pkg/collector/vmware"
"github.com/prometheus-community/windows_exporter/pkg/collector/vmware_blast" "github.com/prometheus-community/windows_exporter/pkg/collector/vmware_blast"
"github.com/prometheus-community/windows_exporter/pkg/types"
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
) )
var Map = map[string]types.CollectorBuilderWithFlags{ func NewBuilderWithFlags[C Collector](fn BuilderWithFlags[C]) BuilderWithFlags[Collector] {
ad.Name: ad.NewWithFlags, return func(app *kingpin.Application) Collector {
adcs.Name: adcs.NewWithFlags, return fn(app)
adfs.Name: adfs.NewWithFlags, }
cache.Name: cache.NewWithFlags, }
container.Name: container.NewWithFlags,
cpu.Name: cpu.NewWithFlags, var BuildersWithFlags = map[string]BuilderWithFlags[Collector]{
cpu_info.Name: cpu_info.NewWithFlags, ad.Name: NewBuilderWithFlags(ad.NewWithFlags),
cs.Name: cs.NewWithFlags, adcs.Name: NewBuilderWithFlags(adcs.NewWithFlags),
dfsr.Name: dfsr.NewWithFlags, adfs.Name: NewBuilderWithFlags(adfs.NewWithFlags),
dhcp.Name: dhcp.NewWithFlags, cache.Name: NewBuilderWithFlags(cache.NewWithFlags),
diskdrive.Name: diskdrive.NewWithFlags, container.Name: NewBuilderWithFlags(container.NewWithFlags),
dns.Name: dns.NewWithFlags, cpu.Name: NewBuilderWithFlags(cpu.NewWithFlags),
exchange.Name: exchange.NewWithFlags, cpu_info.Name: NewBuilderWithFlags(cpu_info.NewWithFlags),
fsrmquota.Name: fsrmquota.NewWithFlags, cs.Name: NewBuilderWithFlags(cs.NewWithFlags),
hyperv.Name: hyperv.NewWithFlags, dfsr.Name: NewBuilderWithFlags(dfsr.NewWithFlags),
iis.Name: iis.NewWithFlags, dhcp.Name: NewBuilderWithFlags(dhcp.NewWithFlags),
logical_disk.Name: logical_disk.NewWithFlags, diskdrive.Name: NewBuilderWithFlags(diskdrive.NewWithFlags),
logon.Name: logon.NewWithFlags, dns.Name: NewBuilderWithFlags(dns.NewWithFlags),
memory.Name: memory.NewWithFlags, exchange.Name: NewBuilderWithFlags(exchange.NewWithFlags),
mscluster_cluster.Name: mscluster_cluster.NewWithFlags, fsrmquota.Name: NewBuilderWithFlags(fsrmquota.NewWithFlags),
mscluster_network.Name: mscluster_network.NewWithFlags, hyperv.Name: NewBuilderWithFlags(hyperv.NewWithFlags),
mscluster_node.Name: mscluster_node.NewWithFlags, iis.Name: NewBuilderWithFlags(iis.NewWithFlags),
mscluster_resource.Name: mscluster_resource.NewWithFlags, license.Name: NewBuilderWithFlags(license.NewWithFlags),
mscluster_resourcegroup.Name: mscluster_resourcegroup.NewWithFlags, logical_disk.Name: NewBuilderWithFlags(logical_disk.NewWithFlags),
msmq.Name: msmq.NewWithFlags, logon.Name: NewBuilderWithFlags(logon.NewWithFlags),
mssql.Name: mssql.NewWithFlags, memory.Name: NewBuilderWithFlags(memory.NewWithFlags),
net.Name: net.NewWithFlags, mscluster.Name: NewBuilderWithFlags(mscluster.NewWithFlags),
netframework_clrexceptions.Name: netframework_clrexceptions.NewWithFlags, msmq.Name: NewBuilderWithFlags(msmq.NewWithFlags),
netframework_clrinterop.Name: netframework_clrinterop.NewWithFlags, mssql.Name: NewBuilderWithFlags(mssql.NewWithFlags),
netframework_clrjit.Name: netframework_clrjit.NewWithFlags, net.Name: NewBuilderWithFlags(net.NewWithFlags),
netframework_clrloading.Name: netframework_clrloading.NewWithFlags, netframework_clrexceptions.Name: NewBuilderWithFlags(netframework_clrexceptions.NewWithFlags),
netframework_clrlocksandthreads.Name: netframework_clrlocksandthreads.NewWithFlags, netframework_clrinterop.Name: NewBuilderWithFlags(netframework_clrinterop.NewWithFlags),
netframework_clrmemory.Name: netframework_clrmemory.NewWithFlags, netframework_clrjit.Name: NewBuilderWithFlags(netframework_clrjit.NewWithFlags),
netframework_clrremoting.Name: netframework_clrremoting.NewWithFlags, netframework_clrloading.Name: NewBuilderWithFlags(netframework_clrloading.NewWithFlags),
netframework_clrsecurity.Name: netframework_clrsecurity.NewWithFlags, netframework_clrlocksandthreads.Name: NewBuilderWithFlags(netframework_clrlocksandthreads.NewWithFlags),
nps.Name: nps.NewWithFlags, netframework_clrmemory.Name: NewBuilderWithFlags(netframework_clrmemory.NewWithFlags),
os.Name: os.NewWithFlags, netframework_clrremoting.Name: NewBuilderWithFlags(netframework_clrremoting.NewWithFlags),
physical_disk.Name: physical_disk.NewWithFlags, netframework_clrsecurity.Name: NewBuilderWithFlags(netframework_clrsecurity.NewWithFlags),
process.Name: process.NewWithFlags, nps.Name: NewBuilderWithFlags(nps.NewWithFlags),
remote_fx.Name: remote_fx.NewWithFlags, os.Name: NewBuilderWithFlags(os.NewWithFlags),
scheduled_task.Name: scheduled_task.NewWithFlags, physical_disk.Name: NewBuilderWithFlags(physical_disk.NewWithFlags),
service.Name: service.NewWithFlags, printer.Name: NewBuilderWithFlags(printer.NewWithFlags),
smb.Name: smb.NewWithFlags, process.Name: NewBuilderWithFlags(process.NewWithFlags),
smtp.Name: smtp.NewWithFlags, remote_fx.Name: NewBuilderWithFlags(remote_fx.NewWithFlags),
system.Name: system.NewWithFlags, scheduled_task.Name: NewBuilderWithFlags(scheduled_task.NewWithFlags),
teradici_pcoip.Name: teradici_pcoip.NewWithFlags, service.Name: NewBuilderWithFlags(service.NewWithFlags),
tcp.Name: tcp.NewWithFlags, smb.Name: NewBuilderWithFlags(smb.NewWithFlags),
terminal_services.Name: terminal_services.NewWithFlags, smbclient.Name: NewBuilderWithFlags(smbclient.NewWithFlags),
textfile.Name: textfile.NewWithFlags, smtp.Name: NewBuilderWithFlags(smtp.NewWithFlags),
thermalzone.Name: thermalzone.NewWithFlags, system.Name: NewBuilderWithFlags(system.NewWithFlags),
time.Name: time.NewWithFlags, teradici_pcoip.Name: NewBuilderWithFlags(teradici_pcoip.NewWithFlags),
vmware.Name: vmware.NewWithFlags, tcp.Name: NewBuilderWithFlags(tcp.NewWithFlags),
vmware_blast.Name: vmware_blast.NewWithFlags, terminal_services.Name: NewBuilderWithFlags(terminal_services.NewWithFlags),
textfile.Name: NewBuilderWithFlags(textfile.NewWithFlags),
thermalzone.Name: NewBuilderWithFlags(thermalzone.NewWithFlags),
time.Name: NewBuilderWithFlags(time.NewWithFlags),
vmware.Name: NewBuilderWithFlags(vmware.NewWithFlags),
vmware_blast.Name: NewBuilderWithFlags(vmware_blast.NewWithFlags),
} }
func Available() []string { func Available() []string {
return maps.Keys(Map) return maps.Keys(BuildersWithFlags)
} }

View File

@@ -12,6 +12,7 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "memory" const Name = "memory"
@@ -20,266 +21,272 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for perflib Memory metrics // A Collector is a Prometheus Collector for perflib Memory metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
AvailableBytes *prometheus.Desc availableBytes *prometheus.Desc
CacheBytes *prometheus.Desc cacheBytes *prometheus.Desc
CacheBytesPeak *prometheus.Desc cacheBytesPeak *prometheus.Desc
CacheFaultsTotal *prometheus.Desc cacheFaultsTotal *prometheus.Desc
CommitLimit *prometheus.Desc commitLimit *prometheus.Desc
CommittedBytes *prometheus.Desc committedBytes *prometheus.Desc
DemandZeroFaultsTotal *prometheus.Desc demandZeroFaultsTotal *prometheus.Desc
FreeAndZeroPageListBytes *prometheus.Desc freeAndZeroPageListBytes *prometheus.Desc
FreeSystemPageTableEntries *prometheus.Desc freeSystemPageTableEntries *prometheus.Desc
ModifiedPageListBytes *prometheus.Desc modifiedPageListBytes *prometheus.Desc
PageFaultsTotal *prometheus.Desc pageFaultsTotal *prometheus.Desc
SwapPageReadsTotal *prometheus.Desc swapPageReadsTotal *prometheus.Desc
SwapPagesReadTotal *prometheus.Desc swapPagesReadTotal *prometheus.Desc
SwapPagesWrittenTotal *prometheus.Desc swapPagesWrittenTotal *prometheus.Desc
SwapPageOperationsTotal *prometheus.Desc swapPageOperationsTotal *prometheus.Desc
SwapPageWritesTotal *prometheus.Desc swapPageWritesTotal *prometheus.Desc
PoolNonpagedAllocsTotal *prometheus.Desc poolNonPagedAllocationsTotal *prometheus.Desc
PoolNonpagedBytes *prometheus.Desc poolNonPagedBytes *prometheus.Desc
PoolPagedAllocsTotal *prometheus.Desc poolPagedAllocationsTotal *prometheus.Desc
PoolPagedBytes *prometheus.Desc poolPagedBytes *prometheus.Desc
PoolPagedResidentBytes *prometheus.Desc poolPagedResidentBytes *prometheus.Desc
StandbyCacheCoreBytes *prometheus.Desc standbyCacheCoreBytes *prometheus.Desc
StandbyCacheNormalPriorityBytes *prometheus.Desc standbyCacheNormalPriorityBytes *prometheus.Desc
StandbyCacheReserveBytes *prometheus.Desc standbyCacheReserveBytes *prometheus.Desc
SystemCacheResidentBytes *prometheus.Desc systemCacheResidentBytes *prometheus.Desc
SystemCodeResidentBytes *prometheus.Desc systemCodeResidentBytes *prometheus.Desc
SystemCodeTotalBytes *prometheus.Desc systemCodeTotalBytes *prometheus.Desc
SystemDriverResidentBytes *prometheus.Desc systemDriverResidentBytes *prometheus.Desc
SystemDriverTotalBytes *prometheus.Desc systemDriverTotalBytes *prometheus.Desc
TransitionFaultsTotal *prometheus.Desc transitionFaultsTotal *prometheus.Desc
TransitionPagesRepurposedTotal *prometheus.Desc transitionPagesRepurposedTotal *prometheus.Desc
WriteCopiesTotal *prometheus.Desc writeCopiesTotal *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Memory"}, nil return []string{"Memory"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.AvailableBytes = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.availableBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "available_bytes"), prometheus.BuildFQName(types.Namespace, Name, "available_bytes"),
"The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+ "The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+
" the standby (cached), free and zero page lists (AvailableBytes)", " the standby (cached), free and zero page lists (AvailableBytes)",
nil, nil,
nil, nil,
) )
c.CacheBytes = prometheus.NewDesc( c.cacheBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cache_bytes"), prometheus.BuildFQName(types.Namespace, Name, "cache_bytes"),
"(CacheBytes)", "(CacheBytes)",
nil, nil,
nil, nil,
) )
c.CacheBytesPeak = prometheus.NewDesc( c.cacheBytesPeak = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cache_bytes_peak"), prometheus.BuildFQName(types.Namespace, Name, "cache_bytes_peak"),
"(CacheBytesPeak)", "(CacheBytesPeak)",
nil, nil,
nil, nil,
) )
c.CacheFaultsTotal = prometheus.NewDesc( c.cacheFaultsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cache_faults_total"), prometheus.BuildFQName(types.Namespace, Name, "cache_faults_total"),
"Number of faults which occur when a page sought in the file system cache is not found there and must be retrieved from elsewhere in memory (soft fault) "+ "Number of faults which occur when a page sought in the file system cache is not found there and must be retrieved from elsewhere in memory (soft fault) "+
"or from disk (hard fault) (Cache Faults/sec)", "or from disk (hard fault) (Cache Faults/sec)",
nil, nil,
nil, nil,
) )
c.CommitLimit = prometheus.NewDesc( c.commitLimit = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "commit_limit"), prometheus.BuildFQName(types.Namespace, Name, "commit_limit"),
"(CommitLimit)", "(CommitLimit)",
nil, nil,
nil, nil,
) )
c.CommittedBytes = prometheus.NewDesc( c.committedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "committed_bytes"), prometheus.BuildFQName(types.Namespace, Name, "committed_bytes"),
"(CommittedBytes)", "(CommittedBytes)",
nil, nil,
nil, nil,
) )
c.DemandZeroFaultsTotal = prometheus.NewDesc( c.demandZeroFaultsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "demand_zero_faults_total"), prometheus.BuildFQName(types.Namespace, Name, "demand_zero_faults_total"),
"The number of zeroed pages required to satisfy faults. Zeroed pages, pages emptied of previously stored data and filled with zeros, are a security"+ "The number of zeroed pages required to satisfy faults. Zeroed pages, pages emptied of previously stored data and filled with zeros, are a security"+
" feature of Windows that prevent processes from seeing data stored by earlier processes that used the memory space (Demand Zero Faults/sec)", " feature of Windows that prevent processes from seeing data stored by earlier processes that used the memory space (Demand Zero Faults/sec)",
nil, nil,
nil, nil,
) )
c.FreeAndZeroPageListBytes = prometheus.NewDesc( c.freeAndZeroPageListBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "free_and_zero_page_list_bytes"), prometheus.BuildFQName(types.Namespace, Name, "free_and_zero_page_list_bytes"),
"The amount of physical memory, in bytes, that is assigned to the free and zero page lists. This memory does not contain cached data. It is immediately"+ "The amount of physical memory, in bytes, that is assigned to the free and zero page lists. This memory does not contain cached data. It is immediately"+
" available for allocation to a process or for system use (FreeAndZeroPageListBytes)", " available for allocation to a process or for system use (FreeAndZeroPageListBytes)",
nil, nil,
nil, nil,
) )
c.FreeSystemPageTableEntries = prometheus.NewDesc( c.freeSystemPageTableEntries = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "free_system_page_table_entries"), prometheus.BuildFQName(types.Namespace, Name, "free_system_page_table_entries"),
"(FreeSystemPageTableEntries)", "(FreeSystemPageTableEntries)",
nil, nil,
nil, nil,
) )
c.ModifiedPageListBytes = prometheus.NewDesc( c.modifiedPageListBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "modified_page_list_bytes"), prometheus.BuildFQName(types.Namespace, Name, "modified_page_list_bytes"),
"The amount of physical memory, in bytes, that is assigned to the modified page list. This memory contains cached data and code that is not actively in "+ "The amount of physical memory, in bytes, that is assigned to the modified page list. This memory contains cached data and code that is not actively in "+
"use by processes, the system and the system cache (ModifiedPageListBytes)", "use by processes, the system and the system cache (ModifiedPageListBytes)",
nil, nil,
nil, nil,
) )
c.PageFaultsTotal = prometheus.NewDesc( c.pageFaultsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "page_faults_total"), prometheus.BuildFQName(types.Namespace, Name, "page_faults_total"),
"Overall rate at which faulted pages are handled by the processor (Page Faults/sec)", "Overall rate at which faulted pages are handled by the processor (Page Faults/sec)",
nil, nil,
nil, nil,
) )
c.SwapPageReadsTotal = prometheus.NewDesc( c.swapPageReadsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "swap_page_reads_total"), prometheus.BuildFQName(types.Namespace, Name, "swap_page_reads_total"),
"Number of disk page reads (a single read operation reading several pages is still only counted once) (PageReadsPersec)", "Number of disk page reads (a single read operation reading several pages is still only counted once) (PageReadsPersec)",
nil, nil,
nil, nil,
) )
c.SwapPagesReadTotal = prometheus.NewDesc( c.swapPagesReadTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "swap_pages_read_total"), prometheus.BuildFQName(types.Namespace, Name, "swap_pages_read_total"),
"Number of pages read across all page reads (ie counting all pages read even if they are read in a single operation) (PagesInputPersec)", "Number of pages read across all page reads (ie counting all pages read even if they are read in a single operation) (PagesInputPersec)",
nil, nil,
nil, nil,
) )
c.SwapPagesWrittenTotal = prometheus.NewDesc( c.swapPagesWrittenTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "swap_pages_written_total"), prometheus.BuildFQName(types.Namespace, Name, "swap_pages_written_total"),
"Number of pages written across all page writes (ie counting all pages written even if they are written in a single operation) (PagesOutputPersec)", "Number of pages written across all page writes (ie counting all pages written even if they are written in a single operation) (PagesOutputPersec)",
nil, nil,
nil, nil,
) )
c.SwapPageOperationsTotal = prometheus.NewDesc( c.swapPageOperationsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "swap_page_operations_total"), prometheus.BuildFQName(types.Namespace, Name, "swap_page_operations_total"),
"Total number of swap page read and writes (PagesPersec)", "Total number of swap page read and writes (PagesPersec)",
nil, nil,
nil, nil,
) )
c.SwapPageWritesTotal = prometheus.NewDesc( c.swapPageWritesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "swap_page_writes_total"), prometheus.BuildFQName(types.Namespace, Name, "swap_page_writes_total"),
"Number of disk page writes (a single write operation writing several pages is still only counted once) (PageWritesPersec)", "Number of disk page writes (a single write operation writing several pages is still only counted once) (PageWritesPersec)",
nil, nil,
nil, nil,
) )
c.PoolNonpagedAllocsTotal = prometheus.NewDesc( c.poolNonPagedAllocationsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pool_nonpaged_allocs_total"), prometheus.BuildFQName(types.Namespace, Name, "pool_nonpaged_allocs_total"),
"The number of calls to allocate space in the nonpaged pool. The nonpaged pool is an area of system memory area for objects that cannot be written"+ "The number of calls to allocate space in the nonpaged pool. The nonpaged pool is an area of system memory area for objects that cannot be written"+
" to disk, and must remain in physical memory as long as they are allocated (PoolNonpagedAllocs)", " to disk, and must remain in physical memory as long as they are allocated (PoolNonpagedAllocs)",
nil, nil,
nil, nil,
) )
c.PoolNonpagedBytes = prometheus.NewDesc( c.poolNonPagedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pool_nonpaged_bytes"), prometheus.BuildFQName(types.Namespace, Name, "pool_nonpaged_bytes"),
"Number of bytes in the non-paged pool, an area of the system virtual memory that is used for objects that cannot be written to disk, but must "+ "Number of bytes in the non-paged pool, an area of the system virtual memory that is used for objects that cannot be written to disk, but must "+
"remain in physical memory as long as they are allocated (PoolNonpagedBytes)", "remain in physical memory as long as they are allocated (PoolNonpagedBytes)",
nil, nil,
nil, nil,
) )
c.PoolPagedAllocsTotal = prometheus.NewDesc( c.poolPagedAllocationsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pool_paged_allocs_total"), prometheus.BuildFQName(types.Namespace, Name, "pool_paged_allocs_total"),
"Number of calls to allocate space in the paged pool, regardless of the amount of space allocated in each call (PoolPagedAllocs)", "Number of calls to allocate space in the paged pool, regardless of the amount of space allocated in each call (PoolPagedAllocs)",
nil, nil,
nil, nil,
) )
c.PoolPagedBytes = prometheus.NewDesc( c.poolPagedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pool_paged_bytes"), prometheus.BuildFQName(types.Namespace, Name, "pool_paged_bytes"),
"(PoolPagedBytes)", "(PoolPagedBytes)",
nil, nil,
nil, nil,
) )
c.PoolPagedResidentBytes = prometheus.NewDesc( c.poolPagedResidentBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pool_paged_resident_bytes"), prometheus.BuildFQName(types.Namespace, Name, "pool_paged_resident_bytes"),
"The size, in bytes, of the portion of the paged pool that is currently resident and active in physical memory. The paged pool is an area of the "+ "The size, in bytes, of the portion of the paged pool that is currently resident and active in physical memory. The paged pool is an area of the "+
"system virtual memory that is used for objects that can be written to disk when they are not being used (PoolPagedResidentBytes)", "system virtual memory that is used for objects that can be written to disk when they are not being used (PoolPagedResidentBytes)",
nil, nil,
nil, nil,
) )
c.StandbyCacheCoreBytes = prometheus.NewDesc( c.standbyCacheCoreBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "standby_cache_core_bytes"), prometheus.BuildFQName(types.Namespace, Name, "standby_cache_core_bytes"),
"The amount of physical memory, in bytes, that is assigned to the core standby cache page lists. This memory contains cached data and code that is "+ "The amount of physical memory, in bytes, that is assigned to the core standby cache page lists. This memory contains cached data and code that is "+
"not actively in use by processes, the system and the system cache (StandbyCacheCoreBytes)", "not actively in use by processes, the system and the system cache (StandbyCacheCoreBytes)",
nil, nil,
nil, nil,
) )
c.StandbyCacheNormalPriorityBytes = prometheus.NewDesc( c.standbyCacheNormalPriorityBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "standby_cache_normal_priority_bytes"), prometheus.BuildFQName(types.Namespace, Name, "standby_cache_normal_priority_bytes"),
"The amount of physical memory, in bytes, that is assigned to the normal priority standby cache page lists. This memory contains cached data and "+ "The amount of physical memory, in bytes, that is assigned to the normal priority standby cache page lists. This memory contains cached data and "+
"code that is not actively in use by processes, the system and the system cache (StandbyCacheNormalPriorityBytes)", "code that is not actively in use by processes, the system and the system cache (StandbyCacheNormalPriorityBytes)",
nil, nil,
nil, nil,
) )
c.StandbyCacheReserveBytes = prometheus.NewDesc( c.standbyCacheReserveBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "standby_cache_reserve_bytes"), prometheus.BuildFQName(types.Namespace, Name, "standby_cache_reserve_bytes"),
"The amount of physical memory, in bytes, that is assigned to the reserve standby cache page lists. This memory contains cached data and code "+ "The amount of physical memory, in bytes, that is assigned to the reserve standby cache page lists. This memory contains cached data and code "+
"that is not actively in use by processes, the system and the system cache (StandbyCacheReserveBytes)", "that is not actively in use by processes, the system and the system cache (StandbyCacheReserveBytes)",
nil, nil,
nil, nil,
) )
c.SystemCacheResidentBytes = prometheus.NewDesc( c.systemCacheResidentBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "system_cache_resident_bytes"), prometheus.BuildFQName(types.Namespace, Name, "system_cache_resident_bytes"),
"The size, in bytes, of the portion of the system file cache which is currently resident and active in physical memory (SystemCacheResidentBytes)", "The size, in bytes, of the portion of the system file cache which is currently resident and active in physical memory (SystemCacheResidentBytes)",
nil, nil,
nil, nil,
) )
c.SystemCodeResidentBytes = prometheus.NewDesc( c.systemCodeResidentBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "system_code_resident_bytes"), prometheus.BuildFQName(types.Namespace, Name, "system_code_resident_bytes"),
"The size, in bytes, of the pageable operating system code that is currently resident and active in physical memory (SystemCodeResidentBytes)", "The size, in bytes, of the pageable operating system code that is currently resident and active in physical memory (SystemCodeResidentBytes)",
nil, nil,
nil, nil,
) )
c.SystemCodeTotalBytes = prometheus.NewDesc( c.systemCodeTotalBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "system_code_total_bytes"), prometheus.BuildFQName(types.Namespace, Name, "system_code_total_bytes"),
"The size, in bytes, of the pageable operating system code currently mapped into the system virtual address space (SystemCodeTotalBytes)", "The size, in bytes, of the pageable operating system code currently mapped into the system virtual address space (SystemCodeTotalBytes)",
nil, nil,
nil, nil,
) )
c.SystemDriverResidentBytes = prometheus.NewDesc( c.systemDriverResidentBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "system_driver_resident_bytes"), prometheus.BuildFQName(types.Namespace, Name, "system_driver_resident_bytes"),
"The size, in bytes, of the pageable physical memory being used by device drivers. It is the working set (physical memory area) of the drivers (SystemDriverResidentBytes)", "The size, in bytes, of the pageable physical memory being used by device drivers. It is the working set (physical memory area) of the drivers (SystemDriverResidentBytes)",
nil, nil,
nil, nil,
) )
c.SystemDriverTotalBytes = prometheus.NewDesc( c.systemDriverTotalBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "system_driver_total_bytes"), prometheus.BuildFQName(types.Namespace, Name, "system_driver_total_bytes"),
"The size, in bytes, of the pageable virtual memory currently being used by device drivers. Pageable memory can be written to disk when it is not being used (SystemDriverTotalBytes)", "The size, in bytes, of the pageable virtual memory currently being used by device drivers. Pageable memory can be written to disk when it is not being used (SystemDriverTotalBytes)",
nil, nil,
nil, nil,
) )
c.TransitionFaultsTotal = prometheus.NewDesc( c.transitionFaultsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transition_faults_total"), prometheus.BuildFQName(types.Namespace, Name, "transition_faults_total"),
"Number of faults rate at which page faults are resolved by recovering pages that were being used by another process sharing the page, or were on the "+ "Number of faults rate at which page faults are resolved by recovering pages that were being used by another process sharing the page, or were on the "+
"modified page list or the standby list, or were being written to disk at the time of the page fault (TransitionFaultsPersec)", "modified page list or the standby list, or were being written to disk at the time of the page fault (TransitionFaultsPersec)",
nil, nil,
nil, nil,
) )
c.TransitionPagesRepurposedTotal = prometheus.NewDesc( c.transitionPagesRepurposedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "transition_pages_repurposed_total"), prometheus.BuildFQName(types.Namespace, Name, "transition_pages_repurposed_total"),
"Transition Pages RePurposed is the rate at which the number of transition cache pages were reused for a different purpose (TransitionPagesRePurposedPersec)", "Transition Pages RePurposed is the rate at which the number of transition cache pages were reused for a different purpose (TransitionPagesRePurposedPersec)",
nil, nil,
nil, nil,
) )
c.WriteCopiesTotal = prometheus.NewDesc( c.writeCopiesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "write_copies_total"), prometheus.BuildFQName(types.Namespace, Name, "write_copies_total"),
"The number of page faults caused by attempting to write that were satisfied by copying the page from elsewhere in physical memory (WriteCopiesPersec)", "The number of page faults caused by attempting to write that were satisfied by copying the page from elsewhere in physical memory (WriteCopiesPersec)",
nil, nil,
@@ -290,9 +297,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting memory metrics", "desc", desc, "err", err) if err := c.collect(ctx, logger, ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting memory metrics", "err", err)
return err return err
} }
return nil return nil
@@ -335,203 +343,204 @@ type memory struct {
WriteCopiesPersec float64 `perflib:"Write Copies/sec"` WriteCopiesPersec float64 `perflib:"Write Copies/sec"`
} }
func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var dst []memory var dst []memory
if err := perflib.UnmarshalObject(ctx.PerfObjects["Memory"], &dst, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["Memory"], &dst, logger); err != nil {
return nil, err return err
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AvailableBytes, c.availableBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].AvailableBytes, dst[0].AvailableBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CacheBytes, c.cacheBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].CacheBytes, dst[0].CacheBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CacheBytesPeak, c.cacheBytesPeak,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].CacheBytesPeak, dst[0].CacheBytesPeak,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CacheFaultsTotal, c.cacheFaultsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].CacheFaultsPersec, dst[0].CacheFaultsPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CommitLimit, c.commitLimit,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].CommitLimit, dst[0].CommitLimit,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CommittedBytes, c.committedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].CommittedBytes, dst[0].CommittedBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DemandZeroFaultsTotal, c.demandZeroFaultsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].DemandZeroFaultsPersec, dst[0].DemandZeroFaultsPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FreeAndZeroPageListBytes, c.freeAndZeroPageListBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].FreeAndZeroPageListBytes, dst[0].FreeAndZeroPageListBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FreeSystemPageTableEntries, c.freeSystemPageTableEntries,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].FreeSystemPageTableEntries, dst[0].FreeSystemPageTableEntries,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ModifiedPageListBytes, c.modifiedPageListBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].ModifiedPageListBytes, dst[0].ModifiedPageListBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PageFaultsTotal, c.pageFaultsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PageFaultsPersec, dst[0].PageFaultsPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SwapPageReadsTotal, c.swapPageReadsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PageReadsPersec, dst[0].PageReadsPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SwapPagesReadTotal, c.swapPagesReadTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PagesInputPersec, dst[0].PagesInputPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SwapPagesWrittenTotal, c.swapPagesWrittenTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PagesOutputPersec, dst[0].PagesOutputPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SwapPageOperationsTotal, c.swapPageOperationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PagesPersec, dst[0].PagesPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SwapPageWritesTotal, c.swapPageWritesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PageWritesPersec, dst[0].PageWritesPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PoolNonpagedAllocsTotal, c.poolNonPagedAllocationsTotal,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].PoolNonpagedAllocs, dst[0].PoolNonpagedAllocs,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PoolNonpagedBytes, c.poolNonPagedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].PoolNonpagedBytes, dst[0].PoolNonpagedBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PoolPagedAllocsTotal, c.poolPagedAllocationsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].PoolPagedAllocs, dst[0].PoolPagedAllocs,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PoolPagedBytes, c.poolPagedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].PoolPagedBytes, dst[0].PoolPagedBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PoolPagedResidentBytes, c.poolPagedResidentBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].PoolPagedResidentBytes, dst[0].PoolPagedResidentBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.StandbyCacheCoreBytes, c.standbyCacheCoreBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].StandbyCacheCoreBytes, dst[0].StandbyCacheCoreBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.StandbyCacheNormalPriorityBytes, c.standbyCacheNormalPriorityBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].StandbyCacheNormalPriorityBytes, dst[0].StandbyCacheNormalPriorityBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.StandbyCacheReserveBytes, c.standbyCacheReserveBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].StandbyCacheReserveBytes, dst[0].StandbyCacheReserveBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SystemCacheResidentBytes, c.systemCacheResidentBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].SystemCacheResidentBytes, dst[0].SystemCacheResidentBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SystemCodeResidentBytes, c.systemCodeResidentBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].SystemCodeResidentBytes, dst[0].SystemCodeResidentBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SystemCodeTotalBytes, c.systemCodeTotalBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].SystemCodeTotalBytes, dst[0].SystemCodeTotalBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SystemDriverResidentBytes, c.systemDriverResidentBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].SystemDriverResidentBytes, dst[0].SystemDriverResidentBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SystemDriverTotalBytes, c.systemDriverTotalBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
dst[0].SystemDriverTotalBytes, dst[0].SystemDriverTotalBytes,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TransitionFaultsTotal, c.transitionFaultsTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].TransitionFaultsPersec, dst[0].TransitionFaultsPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TransitionPagesRepurposedTotal, c.transitionPagesRepurposedTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].TransitionPagesRePurposedPersec, dst[0].TransitionPagesRePurposedPersec,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.WriteCopiesTotal, c.writeCopiesTotal,
prometheus.CounterValue, prometheus.CounterValue,
dst[0].WriteCopiesPersec, dst[0].WriteCopiesPersec,
) )
return nil, nil return nil
} }

View File

@@ -0,0 +1,306 @@
package mscluster
import (
"errors"
"fmt"
"slices"
"strings"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
)
const Name = "mscluster"
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
}
var ConfigDefaults = Config{
CollectorsEnabled: []string{
"cluster",
"network",
"node",
"resource",
"resourcegroup",
},
}
// A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics.
type Collector struct {
config Config
wmiClient *wmi.Client
// cluster
clusterAddEvictDelay *prometheus.Desc
clusterAdminAccessPoint *prometheus.Desc
clusterAutoAssignNodeSite *prometheus.Desc
clusterAutoBalancerLevel *prometheus.Desc
clusterAutoBalancerMode *prometheus.Desc
clusterBackupInProgress *prometheus.Desc
clusterBlockCacheSize *prometheus.Desc
clusterClusSvcHangTimeout *prometheus.Desc
clusterClusSvcRegroupOpeningTimeout *prometheus.Desc
clusterClusSvcRegroupPruningTimeout *prometheus.Desc
clusterClusSvcRegroupStageTimeout *prometheus.Desc
clusterClusSvcRegroupTickInMilliseconds *prometheus.Desc
clusterClusterEnforcedAntiAffinity *prometheus.Desc
clusterClusterFunctionalLevel *prometheus.Desc
clusterClusterGroupWaitDelay *prometheus.Desc
clusterClusterLogLevel *prometheus.Desc
clusterClusterLogSize *prometheus.Desc
clusterClusterUpgradeVersion *prometheus.Desc
clusterCrossSiteDelay *prometheus.Desc
clusterCrossSiteThreshold *prometheus.Desc
clusterCrossSubnetDelay *prometheus.Desc
clusterCrossSubnetThreshold *prometheus.Desc
clusterCsvBalancer *prometheus.Desc
clusterDatabaseReadWriteMode *prometheus.Desc
clusterDefaultNetworkRole *prometheus.Desc
clusterDetectedCloudPlatform *prometheus.Desc
clusterDetectManagedEvents *prometheus.Desc
clusterDetectManagedEventsThreshold *prometheus.Desc
clusterDisableGroupPreferredOwnerRandomization *prometheus.Desc
clusterDrainOnShutdown *prometheus.Desc
clusterDynamicQuorumEnabled *prometheus.Desc
clusterEnableSharedVolumes *prometheus.Desc
clusterFixQuorum *prometheus.Desc
clusterGracePeriodEnabled *prometheus.Desc
clusterGracePeriodTimeout *prometheus.Desc
clusterGroupDependencyTimeout *prometheus.Desc
clusterHangRecoveryAction *prometheus.Desc
clusterIgnorePersistentStateOnStartup *prometheus.Desc
clusterLogResourceControls *prometheus.Desc
clusterLowerQuorumPriorityNodeId *prometheus.Desc
clusterMaxNumberOfNodes *prometheus.Desc
clusterMessageBufferLength *prometheus.Desc
clusterMinimumNeverPreemptPriority *prometheus.Desc
clusterMinimumPreemptorPriority *prometheus.Desc
clusterNetftIPSecEnabled *prometheus.Desc
clusterPlacementOptions *prometheus.Desc
clusterPlumbAllCrossSubnetRoutes *prometheus.Desc
clusterPreventQuorum *prometheus.Desc
clusterQuarantineDuration *prometheus.Desc
clusterQuarantineThreshold *prometheus.Desc
clusterQuorumArbitrationTimeMax *prometheus.Desc
clusterQuorumArbitrationTimeMin *prometheus.Desc
clusterQuorumLogFileSize *prometheus.Desc
clusterQuorumTypeValue *prometheus.Desc
clusterRequestReplyTimeout *prometheus.Desc
clusterResiliencyDefaultPeriod *prometheus.Desc
clusterResiliencyLevel *prometheus.Desc
clusterResourceDllDeadlockPeriod *prometheus.Desc
clusterRootMemoryReserved *prometheus.Desc
clusterRouteHistoryLength *prometheus.Desc
clusterS2DBusTypes *prometheus.Desc
clusterS2DCacheDesiredState *prometheus.Desc
clusterS2DCacheFlashReservePercent *prometheus.Desc
clusterS2DCachePageSizeKBytes *prometheus.Desc
clusterS2DEnabled *prometheus.Desc
clusterS2DIOLatencyThreshold *prometheus.Desc
clusterS2DOptimizations *prometheus.Desc
clusterSameSubnetDelay *prometheus.Desc
clusterSameSubnetThreshold *prometheus.Desc
clusterSecurityLevel *prometheus.Desc
clusterSecurityLevelForStorage *prometheus.Desc
clusterSharedVolumeVssWriterOperationTimeout *prometheus.Desc
clusterShutdownTimeoutInMinutes *prometheus.Desc
clusterUseClientAccessNetworksForSharedVolumes *prometheus.Desc
clusterWitnessDatabaseWriteTimeout *prometheus.Desc
clusterWitnessDynamicWeight *prometheus.Desc
clusterWitnessRestartInterval *prometheus.Desc
// network
networkCharacteristics *prometheus.Desc
networkFlags *prometheus.Desc
networkMetric *prometheus.Desc
networkRole *prometheus.Desc
networkState *prometheus.Desc
// node
nodeBuildNumber *prometheus.Desc
nodeCharacteristics *prometheus.Desc
nodeDetectedCloudPlatform *prometheus.Desc
nodeDynamicWeight *prometheus.Desc
nodeFlags *prometheus.Desc
nodeMajorVersion *prometheus.Desc
nodeMinorVersion *prometheus.Desc
nodeNeedsPreventQuorum *prometheus.Desc
nodeNodeDrainStatus *prometheus.Desc
nodeNodeHighestVersion *prometheus.Desc
nodeNodeLowestVersion *prometheus.Desc
nodeNodeWeight *prometheus.Desc
nodeState *prometheus.Desc
nodeStatusInformation *prometheus.Desc
resourceCharacteristics *prometheus.Desc
resourceDeadlockTimeout *prometheus.Desc
resourceEmbeddedFailureAction *prometheus.Desc
resourceFlags *prometheus.Desc
resourceIsAlivePollInterval *prometheus.Desc
resourceLooksAlivePollInterval *prometheus.Desc
resourceMonitorProcessId *prometheus.Desc
resourceOwnerNode *prometheus.Desc
resourcePendingTimeout *prometheus.Desc
resourceResourceClass *prometheus.Desc
resourceRestartAction *prometheus.Desc
resourceRestartDelay *prometheus.Desc
resourceRestartPeriod *prometheus.Desc
resourceRestartThreshold *prometheus.Desc
resourceRetryPeriodOnFailure *prometheus.Desc
resourceState *prometheus.Desc
resourceSubClass *prometheus.Desc
// ResourceGroup
resourceGroupAutoFailbackType *prometheus.Desc
resourceGroupCharacteristics *prometheus.Desc
resourceGroupColdStartSetting *prometheus.Desc
resourceGroupDefaultOwner *prometheus.Desc
resourceGroupFailbackWindowEnd *prometheus.Desc
resourceGroupFailbackWindowStart *prometheus.Desc
resourceGroupFailOverPeriod *prometheus.Desc
resourceGroupFailOverThreshold *prometheus.Desc
resourceGroupFlags *prometheus.Desc
resourceGroupGroupType *prometheus.Desc
resourceGroupOwnerNode *prometheus.Desc
resourceGroupPriority *prometheus.Desc
resourceGroupResiliencyPeriod *prometheus.Desc
resourceGroupState *prometheus.Desc
}
func New(config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}
if config.CollectorsEnabled == nil {
config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled
}
c := &Collector{
config: *config,
}
return c
}
func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
config: ConfigDefaults,
}
c.config.CollectorsEnabled = make([]string, 0)
var collectorsEnabled string
app.Flag(
"collectors.mscluster.enabled",
"Comma-separated list of collectors to use.",
).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringVar(&collectorsEnabled)
app.Action(func(*kingpin.ParseContext) error {
c.config.CollectorsEnabled = strings.Split(collectorsEnabled, ",")
return nil
})
return c
}
func (c *Collector) GetName() string {
return Name
}
func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
return []string{"Memory"}, nil
}
func (c *Collector) Close() error {
return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if len(c.config.CollectorsEnabled) == 0 {
return nil
}
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
if slices.Contains(c.config.CollectorsEnabled, "cluster") {
c.buildCluster()
}
if slices.Contains(c.config.CollectorsEnabled, "network") {
c.buildNetwork()
}
if slices.Contains(c.config.CollectorsEnabled, "node") {
c.buildNode()
}
if slices.Contains(c.config.CollectorsEnabled, "resource") {
c.buildResource()
}
if slices.Contains(c.config.CollectorsEnabled, "resourcegroup") {
c.buildResourceGroup()
}
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, _ log.Logger, ch chan<- prometheus.Metric) error {
if len(c.config.CollectorsEnabled) == 0 {
return nil
}
var (
err error
errs []error
nodeNames []string
)
if slices.Contains(c.config.CollectorsEnabled, "cluster") {
if err = c.collectCluster(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect cluster metrics: %w", err))
}
}
if slices.Contains(c.config.CollectorsEnabled, "network") {
if err = c.collectNetwork(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect network metrics: %w", err))
}
}
if slices.Contains(c.config.CollectorsEnabled, "node") {
if nodeNames, err = c.collectNode(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect node metrics: %w", err))
}
}
if slices.Contains(c.config.CollectorsEnabled, "resource") {
if err = c.collectResource(ch, nodeNames); err != nil {
errs = append(errs, fmt.Errorf("failed to collect resource metrics: %w", err))
}
}
if slices.Contains(c.config.CollectorsEnabled, "resourcegroup") {
if err = c.collectResourceGroup(ch, nodeNames); err != nil {
errs = append(errs, fmt.Errorf("failed to collect resource group metrics: %w", err))
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}

View File

@@ -0,0 +1,102 @@
package mscluster
import (
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus"
)
const nameNetwork = Name + "_network"
// msClusterNetwork represents the MSCluster_Network WMI class
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
type msClusterNetwork struct {
Name string
Characteristics uint
Flags uint
Metric uint
Role uint
State uint
}
func (c *Collector) buildNetwork() {
c.networkCharacteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNetwork, "characteristics"),
"Provides the characteristics of the network.",
[]string{"name"},
nil,
)
c.networkFlags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNetwork, "flags"),
"Provides access to the flags set for the node. ",
[]string{"name"},
nil,
)
c.networkMetric = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNetwork, "metric"),
"The metric of a cluster network (networks with lower values are used first). If this value is set, then the AutoMetric property is set to false.",
[]string{"name"},
nil,
)
c.networkRole = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNetwork, "role"),
"Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both ",
[]string{"name"},
nil,
)
c.networkState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNetwork, "state"),
"Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up",
[]string{"name"},
nil,
)
}
// Collect sends the metric values for each metric
// to the provided prometheus metric channel.
func (c *Collector) collectNetwork(ch chan<- prometheus.Metric) error {
var dst []msClusterNetwork
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Network", &dst, nil, "root/MSCluster"); err != nil {
return err
}
for _, v := range dst {
ch <- prometheus.MustNewConstMetric(
c.networkCharacteristics,
prometheus.GaugeValue,
float64(v.Characteristics),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.networkFlags,
prometheus.GaugeValue,
float64(v.Flags),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.networkMetric,
prometheus.GaugeValue,
float64(v.Metric),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.networkRole,
prometheus.GaugeValue,
float64(v.Role),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.networkState,
prometheus.GaugeValue,
float64(v.State),
v.Name,
)
}
return nil
}

View File

@@ -1,153 +1,15 @@
package mscluster_node package mscluster
import ( import (
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const Name = "mscluster_node" const nameNode = Name + "_node"
type Config struct{} // msClusterNode represents the MSCluster_Node WMI class
var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI MSCluster_Node metrics
type collector struct {
logger log.Logger
BuildNumber *prometheus.Desc
Characteristics *prometheus.Desc
DetectedCloudPlatform *prometheus.Desc
DynamicWeight *prometheus.Desc
Flags *prometheus.Desc
MajorVersion *prometheus.Desc
MinorVersion *prometheus.Desc
NeedsPreventQuorum *prometheus.Desc
NodeDrainStatus *prometheus.Desc
NodeHighestVersion *prometheus.Desc
NodeLowestVersion *prometheus.Desc
NodeWeight *prometheus.Desc
State *prometheus.Desc
StatusInformation *prometheus.Desc
}
func New(logger log.Logger, _ *Config) types.Collector {
c := &collector{}
c.SetLogger(logger)
return c
}
func NewWithFlags(_ *kingpin.Application) types.Collector {
return &collector{}
}
func (c *collector) GetName() string {
return Name
}
func (c *collector) SetLogger(logger log.Logger) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Memory"}, nil
}
func (c *collector) Build() error {
c.BuildNumber = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "build_number"),
"Provides access to the node's BuildNumber property.",
[]string{"name"},
nil,
)
c.Characteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "characteristics"),
"Provides access to the characteristics set for the node.",
[]string{"name"},
nil,
)
c.DetectedCloudPlatform = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "detected_cloud_platform"),
"(DetectedCloudPlatform)",
[]string{"name"},
nil,
)
c.DynamicWeight = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "dynamic_weight"),
"The dynamic vote weight of the node adjusted by dynamic quorum feature.",
[]string{"name"},
nil,
)
c.Flags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "flags"),
"Provides access to the flags set for the node.",
[]string{"name"},
nil,
)
c.MajorVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "major_version"),
"Provides access to the node's MajorVersion property, which specifies the major portion of the Windows version installed.",
[]string{"name"},
nil,
)
c.MinorVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "minor_version"),
"Provides access to the node's MinorVersion property, which specifies the minor portion of the Windows version installed.",
[]string{"name"},
nil,
)
c.NeedsPreventQuorum = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "needs_prevent_quorum"),
"Whether the cluster service on that node should be started with prevent quorum flag.",
[]string{"name"},
nil,
)
c.NodeDrainStatus = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "node_drain_status"),
"The current node drain status of a node. 0: Not Initiated; 1: In Progress; 2: Completed; 3: Failed",
[]string{"name"},
nil,
)
c.NodeHighestVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "node_highest_version"),
"Provides access to the node's NodeHighestVersion property, which specifies the highest possible version of the cluster service with which the node can join or communicate.",
[]string{"name"},
nil,
)
c.NodeLowestVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "node_lowest_version"),
"Provides access to the node's NodeLowestVersion property, which specifies the lowest possible version of the cluster service with which the node can join or communicate.",
[]string{"name"},
nil,
)
c.NodeWeight = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "node_weight"),
"The vote weight of the node.",
[]string{"name"},
nil,
)
c.State = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "state"),
"Returns the current state of a node. -1: Unknown; 0: Up; 1: Down; 2: Paused; 3: Joining",
[]string{"name"},
nil,
)
c.StatusInformation = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "status_information"),
"The isolation or quarantine status of the node.",
[]string{"name"},
nil,
)
return nil
}
// MSCluster_Node docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node
type MSCluster_Node struct { type msClusterNode struct {
Name string Name string
BuildNumber uint BuildNumber uint
@@ -166,115 +28,205 @@ type MSCluster_Node struct {
StatusInformation uint StatusInformation uint
} }
func (c *Collector) buildNode() {
c.nodeBuildNumber = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "build_number"),
"Provides access to the node's BuildNumber property.",
[]string{"name"},
nil,
)
c.nodeCharacteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "characteristics"),
"Provides access to the characteristics set for the node.",
[]string{"name"},
nil,
)
c.nodeDetectedCloudPlatform = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "detected_cloud_platform"),
"(DetectedCloudPlatform)",
[]string{"name"},
nil,
)
c.nodeDynamicWeight = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "dynamic_weight"),
"The dynamic vote weight of the node adjusted by dynamic quorum feature.",
[]string{"name"},
nil,
)
c.nodeFlags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "flags"),
"Provides access to the flags set for the node.",
[]string{"name"},
nil,
)
c.nodeMajorVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "major_version"),
"Provides access to the node's MajorVersion property, which specifies the major portion of the Windows version installed.",
[]string{"name"},
nil,
)
c.nodeMinorVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "minor_version"),
"Provides access to the node's MinorVersion property, which specifies the minor portion of the Windows version installed.",
[]string{"name"},
nil,
)
c.nodeNeedsPreventQuorum = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "needs_prevent_quorum"),
"Whether the cluster service on that node should be started with prevent quorum flag.",
[]string{"name"},
nil,
)
c.nodeNodeDrainStatus = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "node_drain_status"),
"The current node drain status of a node. 0: Not Initiated; 1: In Progress; 2: Completed; 3: Failed",
[]string{"name"},
nil,
)
c.nodeNodeHighestVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "node_highest_version"),
"Provides access to the node's NodeHighestVersion property, which specifies the highest possible version of the cluster service with which the node can join or communicate.",
[]string{"name"},
nil,
)
c.nodeNodeLowestVersion = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "node_lowest_version"),
"Provides access to the node's NodeLowestVersion property, which specifies the lowest possible version of the cluster service with which the node can join or communicate.",
[]string{"name"},
nil,
)
c.nodeNodeWeight = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "node_weight"),
"The vote weight of the node.",
[]string{"name"},
nil,
)
c.nodeState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "state"),
"Returns the current state of a node. -1: Unknown; 0: Up; 1: Down; 2: Paused; 3: Joining",
[]string{"name"},
nil,
)
c.nodeStatusInformation = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "status_information"),
"The isolation or quarantine status of the node.",
[]string{"name"},
nil,
)
}
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectNode(ch chan<- prometheus.Metric) ([]string, error) {
var dst []MSCluster_Node var dst []msClusterNode
q := wmi.QueryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { if err := c.wmiClient.Query("SELECT * FROM MSCluster_Node", &dst, nil, "root/MSCluster"); err != nil {
return err return nil, err
} }
for _, v := range dst { nodeNames := make([]string, 0, len(dst))
for _, v := range dst {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BuildNumber, c.nodeBuildNumber,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.BuildNumber), float64(v.BuildNumber),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Characteristics, c.nodeCharacteristics,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Characteristics), float64(v.Characteristics),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DetectedCloudPlatform, c.nodeDetectedCloudPlatform,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.DetectedCloudPlatform), float64(v.DetectedCloudPlatform),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DynamicWeight, c.nodeDynamicWeight,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.DynamicWeight), float64(v.DynamicWeight),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Flags, c.nodeFlags,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Flags), float64(v.Flags),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MajorVersion, c.nodeMajorVersion,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.MajorVersion), float64(v.MajorVersion),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MinorVersion, c.nodeMinorVersion,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.MinorVersion), float64(v.MinorVersion),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NeedsPreventQuorum, c.nodeNeedsPreventQuorum,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.NeedsPreventQuorum), float64(v.NeedsPreventQuorum),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NodeDrainStatus, c.nodeNodeDrainStatus,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.NodeDrainStatus), float64(v.NodeDrainStatus),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NodeHighestVersion, c.nodeNodeHighestVersion,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.NodeHighestVersion), float64(v.NodeHighestVersion),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NodeLowestVersion, c.nodeNodeLowestVersion,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.NodeLowestVersion), float64(v.NodeLowestVersion),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NodeWeight, c.nodeNodeWeight,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.NodeWeight), float64(v.NodeWeight),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.State, c.nodeState,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.State), float64(v.State),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.StatusInformation, c.nodeStatusInformation,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.StatusInformation), float64(v.StatusInformation),
v.Name, v.Name,
) )
nodeNames = append(nodeNames, v.Name)
} }
return nil return nodeNames, nil
} }

View File

@@ -1,170 +1,19 @@
package mscluster_resource package mscluster
import ( import (
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const Name = "mscluster_resource" const nameResource = Name + "_resource"
type Config struct{} // msClusterResource represents the MSCluster_Resource WMI class
var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI MSCluster_Resource metrics
type collector struct {
logger log.Logger
Characteristics *prometheus.Desc
DeadlockTimeout *prometheus.Desc
EmbeddedFailureAction *prometheus.Desc
Flags *prometheus.Desc
IsAlivePollInterval *prometheus.Desc
LooksAlivePollInterval *prometheus.Desc
MonitorProcessId *prometheus.Desc
PendingTimeout *prometheus.Desc
ResourceClass *prometheus.Desc
RestartAction *prometheus.Desc
RestartDelay *prometheus.Desc
RestartPeriod *prometheus.Desc
RestartThreshold *prometheus.Desc
RetryPeriodOnFailure *prometheus.Desc
State *prometheus.Desc
Subclass *prometheus.Desc
}
func New(logger log.Logger, _ *Config) types.Collector {
c := &collector{}
c.SetLogger(logger)
return c
}
func NewWithFlags(_ *kingpin.Application) types.Collector {
return &collector{}
}
func (c *collector) GetName() string {
return Name
}
func (c *collector) SetLogger(logger log.Logger) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Memory"}, nil
}
func (c *collector) Build() error {
c.Characteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "characteristics"),
"Provides the characteristics of the object.",
[]string{"type", "owner_group", "name"},
nil,
)
c.DeadlockTimeout = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "deadlock_timeout"),
"Indicates the length of time to wait, in milliseconds, before declaring a deadlock in any call into a resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.EmbeddedFailureAction = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "embedded_failure_action"),
"The time, in milliseconds, that a resource should remain in a failed state before the Cluster service attempts to restart it.",
[]string{"type", "owner_group", "name"},
nil,
)
c.Flags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "flags"),
"Provides access to the flags set for the object.",
[]string{"type", "owner_group", "name"},
nil,
)
c.IsAlivePollInterval = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "is_alive_poll_interval"),
"Provides access to the resource's IsAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it is operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the IsAlivePollInterval property for the resource type associated with the resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.LooksAlivePollInterval = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "looks_alive_poll_interval"),
"Provides access to the resource's LooksAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it appears operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the LooksAlivePollInterval property for the resource type associated with the resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.MonitorProcessId = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "monitor_process_id"),
"Provides the process ID of the resource host service that is currently hosting the resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.PendingTimeout = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "pending_timeout"),
"Provides access to the resource's PendingTimeout property. If a resource cannot be brought online or taken offline in the number of milliseconds specified by the PendingTimeout property, the resource is forcibly terminated.",
[]string{"type", "owner_group", "name"},
nil,
)
c.ResourceClass = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "resource_class"),
"Gets or sets the resource class of a resource. 0: Unknown; 1: Storage; 2: Network; 32768: Unknown ",
[]string{"type", "owner_group", "name"},
nil,
)
c.RestartAction = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "restart_action"),
"Provides access to the resource's RestartAction property, which is the action to be taken by the Cluster Service if the resource fails.",
[]string{"type", "owner_group", "name"},
nil,
)
c.RestartDelay = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "restart_delay"),
"Indicates the time delay before a failed resource is restarted.",
[]string{"type", "owner_group", "name"},
nil,
)
c.RestartPeriod = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "restart_period"),
"Provides access to the resource's RestartPeriod property, which is interval of time, in milliseconds, during which a specified number of restart attempts can be made on a nonresponsive resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.RestartThreshold = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "restart_threshold"),
"Provides access to the resource's RestartThreshold property which is the maximum number of restart attempts that can be made on a resource within an interval defined by the RestartPeriod property before the Cluster Service initiates the action specified by the RestartAction property.",
[]string{"type", "owner_group", "name"},
nil,
)
c.RetryPeriodOnFailure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "retry_period_on_failure"),
"Provides access to the resource's RetryPeriodOnFailure property, which is the interval of time (in milliseconds) that a resource should remain in a failed state before the Cluster service attempts to restart it.",
[]string{"type", "owner_group", "name"},
nil,
)
c.State = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "state"),
"The current state of the resource. -1: Unknown; 0: Inherited; 1: Initializing; 2: Online; 3: Offline; 4: Failed; 128: Pending; 129: Online Pending; 130: Offline Pending ",
[]string{"type", "owner_group", "name"},
nil,
)
c.Subclass = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "subclass"),
"Provides the list of references to nodes that can be the owner of this resource.",
[]string{"type", "owner_group", "name"},
nil,
)
return nil
}
// MSCluster_Resource docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource
type MSCluster_Resource struct { type msClusterResource struct {
Name string Name string
Type string Type string
OwnerGroup string OwnerGroup string
OwnerNode string
Characteristics uint Characteristics uint
DeadlockTimeout uint DeadlockTimeout uint
@@ -184,124 +33,247 @@ type MSCluster_Resource struct {
Subclass uint Subclass uint
} }
func (c *Collector) buildResource() {
c.resourceCharacteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "characteristics"),
"Provides the characteristics of the object.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceDeadlockTimeout = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "deadlock_timeout"),
"Indicates the length of time to wait, in milliseconds, before declaring a deadlock in any call into a resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceEmbeddedFailureAction = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "embedded_failure_action"),
"The time, in milliseconds, that a resource should remain in a failed state before the Cluster service attempts to restart it.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceFlags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "flags"),
"Provides access to the flags set for the object.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceIsAlivePollInterval = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "is_alive_poll_interval"),
"Provides access to the resource's IsAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it is operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the IsAlivePollInterval property for the resource type associated with the resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceLooksAlivePollInterval = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "looks_alive_poll_interval"),
"Provides access to the resource's LooksAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it appears operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the LooksAlivePollInterval property for the resource type associated with the resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceMonitorProcessId = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "monitor_process_id"),
"Provides the process ID of the resource host service that is currently hosting the resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceOwnerNode = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "owner_node"),
"The node hosting the resource. 0: Not hosted; 1: Hosted",
[]string{"type", "owner_group", "node_name", "name"},
nil,
)
c.resourceOwnerNode = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "owner_node"),
"The node hosting the resource. 0: Not hosted; 1: Hosted",
[]string{"type", "owner_group", "node_name", "name"},
nil,
)
c.resourcePendingTimeout = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "pending_timeout"),
"Provides access to the resource's PendingTimeout property. If a resource cannot be brought online or taken offline in the number of milliseconds specified by the PendingTimeout property, the resource is forcibly terminated.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceResourceClass = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "resource_class"),
"Gets or sets the resource class of a resource. 0: Unknown; 1: Storage; 2: Network; 32768: Unknown ",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceRestartAction = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "restart_action"),
"Provides access to the resource's RestartAction property, which is the action to be taken by the Cluster Service if the resource fails.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceRestartDelay = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "restart_delay"),
"Indicates the time delay before a failed resource is restarted.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceRestartPeriod = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "restart_period"),
"Provides access to the resource's RestartPeriod property, which is interval of time, in milliseconds, during which a specified number of restart attempts can be made on a nonresponsive resource.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceRestartThreshold = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "restart_threshold"),
"Provides access to the resource's RestartThreshold property which is the maximum number of restart attempts that can be made on a resource within an interval defined by the RestartPeriod property before the Cluster Service initiates the action specified by the RestartAction property.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceRetryPeriodOnFailure = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "retry_period_on_failure"),
"Provides access to the resource's RetryPeriodOnFailure property, which is the interval of time (in milliseconds) that a resource should remain in a failed state before the Cluster service attempts to restart it.",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "state"),
"The current state of the resource. -1: Unknown; 0: Inherited; 1: Initializing; 2: Online; 3: Offline; 4: Failed; 128: Pending; 129: Online Pending; 130: Offline Pending ",
[]string{"type", "owner_group", "name"},
nil,
)
c.resourceSubClass = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "subclass"),
"Provides the list of references to nodes that can be the owner of this resource.",
[]string{"type", "owner_group", "name"},
nil,
)
}
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectResource(ch chan<- prometheus.Metric, nodeNames []string) error {
var dst []MSCluster_Resource var dst []msClusterResource
q := wmi.QueryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { if err := c.wmiClient.Query("SELECT * FROM MSCluster_Resource", &dst, nil, "root/MSCluster"); err != nil {
return err return err
} }
for _, v := range dst { for _, v := range dst {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Characteristics, c.resourceCharacteristics,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Characteristics), float64(v.Characteristics),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DeadlockTimeout, c.resourceDeadlockTimeout,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.DeadlockTimeout), float64(v.DeadlockTimeout),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.EmbeddedFailureAction, c.resourceEmbeddedFailureAction,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.EmbeddedFailureAction), float64(v.EmbeddedFailureAction),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Flags, c.resourceFlags,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Flags), float64(v.Flags),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.IsAlivePollInterval, c.resourceIsAlivePollInterval,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.IsAlivePollInterval), float64(v.IsAlivePollInterval),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LooksAlivePollInterval, c.resourceLooksAlivePollInterval,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.LooksAlivePollInterval), float64(v.LooksAlivePollInterval),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MonitorProcessId, c.resourceMonitorProcessId,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.MonitorProcessId), float64(v.MonitorProcessId),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
for _, nodeName := range nodeNames {
isCurrentState := 0.0
if v.OwnerNode == nodeName {
isCurrentState = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.resourceOwnerNode,
prometheus.GaugeValue,
isCurrentState,
v.Type, v.OwnerGroup, nodeName, v.Name,
)
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PendingTimeout, c.resourcePendingTimeout,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.PendingTimeout), float64(v.PendingTimeout),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ResourceClass, c.resourceResourceClass,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.ResourceClass), float64(v.ResourceClass),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RestartAction, c.resourceRestartAction,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.RestartAction), float64(v.RestartAction),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RestartDelay, c.resourceRestartDelay,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.RestartDelay), float64(v.RestartDelay),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RestartPeriod, c.resourceRestartPeriod,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.RestartPeriod), float64(v.RestartPeriod),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RestartThreshold, c.resourceRestartThreshold,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.RestartThreshold), float64(v.RestartThreshold),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.RetryPeriodOnFailure, c.resourceRetryPeriodOnFailure,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.RetryPeriodOnFailure), float64(v.RetryPeriodOnFailure),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.State, c.resourceState,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.State), float64(v.State),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Subclass, c.resourceSubClass,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Subclass), float64(v.Subclass),
v.Type, v.OwnerGroup, v.Name, v.Type, v.OwnerGroup, v.Name,

View File

@@ -1,148 +1,15 @@
package mscluster_resourcegroup package mscluster
import ( import (
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const Name = "mscluster_resourcegroup" const nameResourceGroup = Name + "_resourcegroup"
type Config struct{} // msClusterResourceGroup represents the MSCluster_ResourceGroup WMI class
var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI MSCluster_ResourceGroup metrics
type collector struct {
logger log.Logger
AutoFailbackType *prometheus.Desc
Characteristics *prometheus.Desc
ColdStartSetting *prometheus.Desc
DefaultOwner *prometheus.Desc
FailbackWindowEnd *prometheus.Desc
FailbackWindowStart *prometheus.Desc
FailoverPeriod *prometheus.Desc
FailoverThreshold *prometheus.Desc
FaultDomain *prometheus.Desc
Flags *prometheus.Desc
GroupType *prometheus.Desc
PlacementOptions *prometheus.Desc
Priority *prometheus.Desc
ResiliencyPeriod *prometheus.Desc
State *prometheus.Desc
}
func New(logger log.Logger, _ *Config) types.Collector {
c := &collector{}
c.SetLogger(logger)
return c
}
func NewWithFlags(_ *kingpin.Application) types.Collector {
return &collector{}
}
func (c *collector) GetName() string {
return Name
}
func (c *collector) SetLogger(logger log.Logger) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Memory"}, nil
}
func (c *collector) Build() error {
c.AutoFailbackType = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "auto_failback_type"),
"Provides access to the group's AutoFailbackType property.",
[]string{"name"},
nil,
)
c.Characteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "characteristics"),
"Provides the characteristics of the group.",
[]string{"name"},
nil,
)
c.ColdStartSetting = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "cold_start_setting"),
"Indicates whether a group can start after a cluster cold start.",
[]string{"name"},
nil,
)
c.DefaultOwner = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "default_owner"),
"Number of the last node the resource group was activated on or explicitly moved to.",
[]string{"name"},
nil,
)
c.FailbackWindowEnd = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failback_window_end"),
"The FailbackWindowEnd property provides the latest time that the group can be moved back to the node identified as its preferred node.",
[]string{"name"},
nil,
)
c.FailbackWindowStart = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failback_window_start"),
"The FailbackWindowStart property provides the earliest time (that is, local time as kept by the cluster) that the group can be moved back to the node identified as its preferred node.",
[]string{"name"},
nil,
)
c.FailoverPeriod = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_period"),
"The FailoverPeriod property specifies a number of hours during which a maximum number of failover attempts, specified by the FailoverThreshold property, can occur.",
[]string{"name"},
nil,
)
c.FailoverThreshold = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "failover_threshold"),
"The FailoverThreshold property specifies the maximum number of failover attempts.",
[]string{"name"},
nil,
)
c.Flags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "flags"),
"Provides access to the flags set for the group. ",
[]string{"name"},
nil,
)
c.GroupType = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "group_type"),
"The Type of the resource group.",
[]string{"name"},
nil,
)
c.Priority = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "priority"),
"Priority value of the resource group",
[]string{"name"},
nil,
)
c.ResiliencyPeriod = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "resiliency_period"),
"The resiliency period for this group, in seconds.",
[]string{"name"},
nil,
)
c.State = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "state"),
"The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending",
[]string{"name"},
nil,
)
return nil
}
// MSCluster_ResourceGroup docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup // - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup
type MSCluster_ResourceGroup struct { type msClusterResourceGroup struct {
Name string Name string
AutoFailbackType uint AutoFailbackType uint
@@ -155,113 +22,218 @@ type MSCluster_ResourceGroup struct {
FailoverThreshold uint FailoverThreshold uint
Flags uint Flags uint
GroupType uint GroupType uint
OwnerNode string
Priority uint Priority uint
ResiliencyPeriod uint ResiliencyPeriod uint
State uint State uint
} }
func (c *Collector) buildResourceGroup() {
c.resourceGroupAutoFailbackType = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "auto_failback_type"),
"Provides access to the group's AutoFailbackType property.",
[]string{"name"},
nil,
)
c.resourceGroupCharacteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "characteristics"),
"Provides the characteristics of the group.",
[]string{"name"},
nil,
)
c.resourceGroupColdStartSetting = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "cold_start_setting"),
"Indicates whether a group can start after a cluster cold start.",
[]string{"name"},
nil,
)
c.resourceGroupDefaultOwner = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "default_owner"),
"Number of the last node the resource group was activated on or explicitly moved to.",
[]string{"name"},
nil,
)
c.resourceGroupFailbackWindowEnd = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "failback_window_end"),
"The FailbackWindowEnd property provides the latest time that the group can be moved back to the node identified as its preferred node.",
[]string{"name"},
nil,
)
c.resourceGroupFailbackWindowStart = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "failback_window_start"),
"The FailbackWindowStart property provides the earliest time (that is, local time as kept by the cluster) that the group can be moved back to the node identified as its preferred node.",
[]string{"name"},
nil,
)
c.resourceGroupFailOverPeriod = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "failover_period"),
"The FailoverPeriod property specifies a number of hours during which a maximum number of failover attempts, specified by the FailoverThreshold property, can occur.",
[]string{"name"},
nil,
)
c.resourceGroupFailOverThreshold = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "failover_threshold"),
"The FailoverThreshold property specifies the maximum number of failover attempts.",
[]string{"name"},
nil,
)
c.resourceGroupFlags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "flags"),
"Provides access to the flags set for the group. ",
[]string{"name"},
nil,
)
c.resourceGroupGroupType = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "group_type"),
"The Type of the resource group.",
[]string{"name"},
nil,
)
c.resourceGroupOwnerNode = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "owner_node"),
"The node hosting the resource group. 0: Not hosted; 1: Hosted",
[]string{"node_name", "name"},
nil,
)
c.resourceGroupOwnerNode = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "owner_node"),
"The node hosting the resource group. 0: Not hosted; 1: Hosted",
[]string{"node_name", "name"},
nil,
)
c.resourceGroupPriority = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "priority"),
"Priority value of the resource group",
[]string{"name"},
nil,
)
c.resourceGroupResiliencyPeriod = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "resiliency_period"),
"The resiliency period for this group, in seconds.",
[]string{"name"},
nil,
)
c.resourceGroupState = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResourceGroup, "state"),
"The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending",
[]string{"name"},
nil,
)
}
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) collectResourceGroup(ch chan<- prometheus.Metric, nodeNames []string) error {
var dst []MSCluster_ResourceGroup var dst []msClusterResourceGroup
q := wmi.QueryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { if err := c.wmiClient.Query("SELECT * FROM MSCluster_ResourceGroup", &dst, nil, "root/MSCluster"); err != nil {
return err return err
} }
for _, v := range dst { for _, v := range dst {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AutoFailbackType, c.resourceGroupAutoFailbackType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.AutoFailbackType), float64(v.AutoFailbackType),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Characteristics, c.resourceGroupCharacteristics,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Characteristics), float64(v.Characteristics),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ColdStartSetting, c.resourceGroupColdStartSetting,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.ColdStartSetting), float64(v.ColdStartSetting),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.DefaultOwner, c.resourceGroupDefaultOwner,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.DefaultOwner), float64(v.DefaultOwner),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailbackWindowEnd, c.resourceGroupFailbackWindowEnd,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.FailbackWindowEnd), float64(v.FailbackWindowEnd),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailbackWindowStart, c.resourceGroupFailbackWindowStart,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.FailbackWindowStart), float64(v.FailbackWindowStart),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverPeriod, c.resourceGroupFailOverPeriod,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.FailoverPeriod), float64(v.FailoverPeriod),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FailoverThreshold, c.resourceGroupFailOverThreshold,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.FailoverThreshold), float64(v.FailoverThreshold),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Flags, c.resourceGroupFlags,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Flags), float64(v.Flags),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.GroupType, c.resourceGroupGroupType,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.GroupType), float64(v.GroupType),
v.Name, v.Name,
) )
for _, nodeName := range nodeNames {
isCurrentState := 0.0
if v.OwnerNode == nodeName {
isCurrentState = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.resourceGroupOwnerNode,
prometheus.GaugeValue,
isCurrentState,
nodeName, v.Name,
)
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Priority, c.resourceGroupPriority,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.Priority), float64(v.Priority),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ResiliencyPeriod, c.resourceGroupResiliencyPeriod,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.ResiliencyPeriod), float64(v.ResiliencyPeriod),
v.Name, v.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.State, c.resourceGroupState,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(v.State), float64(v.State),
v.Name, v.Name,
) )
} }
return nil return nil

View File

@@ -1,144 +0,0 @@
package mscluster_network
import (
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
)
const Name = "mscluster_network"
type Config struct{}
var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI MSCluster_Network metrics
type collector struct {
logger log.Logger
Characteristics *prometheus.Desc
Flags *prometheus.Desc
Metric *prometheus.Desc
Role *prometheus.Desc
State *prometheus.Desc
}
func New(logger log.Logger, _ *Config) types.Collector {
c := &collector{}
c.SetLogger(logger)
return c
}
func NewWithFlags(_ *kingpin.Application) types.Collector {
return &collector{}
}
func (c *collector) GetName() string {
return Name
}
func (c *collector) SetLogger(logger log.Logger) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Memory"}, nil
}
func (c *collector) Build() error {
c.Characteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "characteristics"),
"Provides the characteristics of the network.",
[]string{"name"},
nil,
)
c.Flags = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "flags"),
"Provides access to the flags set for the node. ",
[]string{"name"},
nil,
)
c.Metric = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "metric"),
"The metric of a cluster network (networks with lower values are used first). If this value is set, then the AutoMetric property is set to false.",
[]string{"name"},
nil,
)
c.Role = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "role"),
"Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both ",
[]string{"name"},
nil,
)
c.State = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "state"),
"Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up",
[]string{"name"},
nil,
)
return nil
}
// MSCluster_Network docs:
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
type MSCluster_Network struct {
Name string
Characteristics uint
Flags uint
Metric uint
Role uint
State uint
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []MSCluster_Network
q := wmi.QueryAll(&dst, c.logger)
if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil {
return err
}
for _, v := range dst {
ch <- prometheus.MustNewConstMetric(
c.Characteristics,
prometheus.GaugeValue,
float64(v.Characteristics),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.Flags,
prometheus.GaugeValue,
float64(v.Flags),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.Metric,
prometheus.GaugeValue,
float64(v.Metric),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.Role,
prometheus.GaugeValue,
float64(v.Role),
v.Name,
)
ch <- prometheus.MustNewConstMetric(
c.State,
prometheus.GaugeValue,
float64(v.State),
v.Name,
)
}
return nil
}

View File

@@ -3,6 +3,7 @@
package msmq package msmq
import ( import (
"errors"
"strings" "strings"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
@@ -10,91 +11,103 @@ import (
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus-community/windows_exporter/pkg/utils"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const ( const Name = "msmq"
Name = "msmq"
FlagMsmqWhereClause = "collector.msmq.msmq-where"
)
type Config struct { type Config struct {
QueryWhereClause string `yaml:"query_where_clause"` QueryWhereClause *string `yaml:"query_where_clause"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
QueryWhereClause: "", QueryWhereClause: utils.ToPTR(""),
} }
// A collector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
queryWhereClause *string bytesInJournalQueue *prometheus.Desc
bytesInQueue *prometheus.Desc
BytesinJournalQueue *prometheus.Desc messagesInJournalQueue *prometheus.Desc
BytesinQueue *prometheus.Desc messagesInQueue *prometheus.Desc
MessagesinJournalQueue *prometheus.Desc
MessagesinQueue *prometheus.Desc
} }
func New(logger log.Logger, config *Config) types.Collector { func New(config *Config) *Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &collector{ if config.QueryWhereClause == nil {
queryWhereClause: &config.QueryWhereClause, config.QueryWhereClause = ConfigDefaults.QueryWhereClause
} }
c.SetLogger(logger)
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(app *kingpin.Application) types.Collector { func NewWithFlags(app *kingpin.Application) *Collector {
return &collector{ c := &Collector{
queryWhereClause: app. config: ConfigDefaults,
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.").
Default(ConfigDefaults.QueryWhereClause).String(),
} }
app.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.").
Default(*c.config.QueryWhereClause).StringVar(c.config.QueryWhereClause)
return c
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
if utils.IsEmpty(c.queryWhereClause) { return nil
_ = level.Warn(c.logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!") }
func (c *Collector) Build(logger log.Logger, wmiClient *wmi.Client) error {
logger = log.With(logger, "collector", Name)
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
} }
c.BytesinJournalQueue = prometheus.NewDesc( c.wmiClient = wmiClient
if *c.config.QueryWhereClause == "" {
_ = level.Warn(logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!")
}
c.bytesInJournalQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bytes_in_journal_queue"), prometheus.BuildFQName(types.Namespace, Name, "bytes_in_journal_queue"),
"Size of queue journal in bytes", "Size of queue journal in bytes",
[]string{"name"}, []string{"name"},
nil, nil,
) )
c.BytesinQueue = prometheus.NewDesc( c.bytesInQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bytes_in_queue"), prometheus.BuildFQName(types.Namespace, Name, "bytes_in_queue"),
"Size of queue in bytes", "Size of queue in bytes",
[]string{"name"}, []string{"name"},
nil, nil,
) )
c.MessagesinJournalQueue = prometheus.NewDesc( c.messagesInJournalQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "messages_in_journal_queue"), prometheus.BuildFQName(types.Namespace, Name, "messages_in_journal_queue"),
"Count messages in queue journal", "Count messages in queue journal",
[]string{"name"}, []string{"name"},
nil, nil,
) )
c.MessagesinQueue = prometheus.NewDesc( c.messagesInQueue = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "messages_in_queue"), prometheus.BuildFQName(types.Namespace, Name, "messages_in_queue"),
"Count messages in queue", "Count messages in queue",
[]string{"name"}, []string{"name"},
@@ -105,58 +118,65 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting msmq metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting msmq metrics", "err", err)
return err return err
} }
return nil return nil
} }
type Win32_PerfRawData_MSMQ_MSMQQueue struct { type msmqQueue struct {
Name string Name string
BytesinJournalQueue uint64 BytesInJournalQueue uint64
BytesinQueue uint64 BytesInQueue uint64
MessagesinJournalQueue uint64 MessagesInJournalQueue uint64
MessagesinQueue uint64 MessagesInQueue uint64
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_MSMQ_MSMQQueue var dst []msmqQueue
q := wmi.QueryAllWhere(&dst, *c.queryWhereClause, c.logger)
if err := wmi.Query(q, &dst); err != nil { query := "SELECT * FROM Win32_PerfRawData_MSMQ_MSMQQueue"
return nil, err if *c.config.QueryWhereClause != "" {
query += " WHERE " + *c.config.QueryWhereClause
}
if err := c.wmiClient.Query(query, &dst); err != nil {
return err
} }
for _, msmq := range dst { for _, msmq := range dst {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesinJournalQueue, c.bytesInJournalQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.BytesinJournalQueue), float64(msmq.BytesInJournalQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesinQueue, c.bytesInQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.BytesinQueue), float64(msmq.BytesInQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MessagesinJournalQueue, c.messagesInJournalQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.MessagesinJournalQueue), float64(msmq.MessagesInJournalQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MessagesinQueue, c.messagesInQueue,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(msmq.MessagesinQueue), float64(msmq.MessagesInQueue),
strings.ToLower(msmq.Name), strings.ToLower(msmq.Name),
) )
} }
return nil, nil
return nil
} }

View File

@@ -8,6 +8,6 @@ import (
) )
func BenchmarkCollector(b *testing.B) { func BenchmarkCollector(b *testing.B) {
// No context name required as collector source is WMI // No context name required as Collector source is WMI
testutils.FuncBenchmarkCollector(b, msmq.Name, msmq.NewWithFlags) testutils.FuncBenchmarkCollector(b, msmq.Name, msmq.NewWithFlags)
} }

File diff suppressed because it is too large Load Diff

View File

@@ -12,192 +12,199 @@ import (
"github.com/prometheus-community/windows_exporter/pkg/perflib" "github.com/prometheus-community/windows_exporter/pkg/perflib"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const ( const Name = "net"
Name = "net"
FlagNicExclude = "collector.net.nic-exclude"
FlagNicInclude = "collector.net.nic-include"
)
type Config struct { type Config struct {
NicInclude string `yaml:"nic_include"` NicExclude *regexp.Regexp `yaml:"nic_exclude"`
NicExclude string `yaml:"nic_exclude"` NicInclude *regexp.Regexp `yaml:"nic_include"`
} }
var ConfigDefaults = Config{ var ConfigDefaults = Config{
NicInclude: ".+", NicExclude: types.RegExpEmpty,
NicExclude: "", NicInclude: types.RegExpAny,
} }
var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
// A collector is a Prometheus collector for Perflib Network Interface metrics // A Collector is a Prometheus Collector for Perflib Network Interface metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
nicInclude *string bytesReceivedTotal *prometheus.Desc
nicExclude *string bytesSentTotal *prometheus.Desc
bytesTotal *prometheus.Desc
BytesReceivedTotal *prometheus.Desc outputQueueLength *prometheus.Desc
BytesSentTotal *prometheus.Desc packetsOutboundDiscarded *prometheus.Desc
BytesTotal *prometheus.Desc packetsOutboundErrors *prometheus.Desc
OutputQueueLength *prometheus.Desc packetsTotal *prometheus.Desc
PacketsOutboundDiscarded *prometheus.Desc packetsReceivedDiscarded *prometheus.Desc
PacketsOutboundErrors *prometheus.Desc packetsReceivedErrors *prometheus.Desc
PacketsTotal *prometheus.Desc packetsReceivedTotal *prometheus.Desc
PacketsReceivedDiscarded *prometheus.Desc packetsReceivedUnknown *prometheus.Desc
PacketsReceivedErrors *prometheus.Desc packetsSentTotal *prometheus.Desc
PacketsReceivedTotal *prometheus.Desc currentBandwidth *prometheus.Desc
PacketsReceivedUnknown *prometheus.Desc
PacketsSentTotal *prometheus.Desc
CurrentBandwidth *prometheus.Desc
nicIncludePattern *regexp.Regexp
nicExcludePattern *regexp.Regexp
} }
func New(logger log.Logger, config *Config) types.Collector { func New(config *Config) *Collector {
if config == nil { if config == nil {
config = &ConfigDefaults config = &ConfigDefaults
} }
c := &collector{ if config.NicExclude == nil {
nicExclude: &config.NicExclude, config.NicExclude = ConfigDefaults.NicExclude
nicInclude: &config.NicInclude,
} }
c.SetLogger(logger)
return c
}
func NewWithFlags(app *kingpin.Application) types.Collector { if config.NicInclude == nil {
c := &collector{ config.NicInclude = ConfigDefaults.NicInclude
nicInclude: app.Flag( }
FlagNicInclude,
"Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.NicInclude).String(),
nicExclude: app.Flag( c := &Collector{
FlagNicExclude, config: *config,
"Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.",
).Default(ConfigDefaults.NicExclude).String(),
} }
return c return c
} }
func (c *collector) GetName() string { func NewWithFlags(app *kingpin.Application) *Collector {
c := &Collector{
config: ConfigDefaults,
}
var nicExclude, nicInclude string
app.Flag(
"collector.net.nic-exclude",
"Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.",
).Default(c.config.NicExclude.String()).StringVar(&nicExclude)
app.Flag(
"collector.net.nic-include",
"Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.",
).Default(c.config.NicInclude.String()).StringVar(&nicInclude)
app.Action(func(*kingpin.ParseContext) error {
var err error
c.config.NicExclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", nicExclude))
if err != nil {
return fmt.Errorf("collector.net.nic-exclude: %w", err)
}
c.config.NicInclude, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", nicInclude))
if err != nil {
return fmt.Errorf("collector.net.nic-include: %w", err)
}
return nil
})
return c
}
func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{"Network Interface"}, nil return []string{"Network Interface"}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.BytesReceivedTotal = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.bytesReceivedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bytes_received_total"), prometheus.BuildFQName(types.Namespace, Name, "bytes_received_total"),
"(Network.BytesReceivedPerSec)", "(Network.BytesReceivedPerSec)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.BytesSentTotal = prometheus.NewDesc( c.bytesSentTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bytes_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "bytes_sent_total"),
"(Network.BytesSentPerSec)", "(Network.BytesSentPerSec)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.BytesTotal = prometheus.NewDesc( c.bytesTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "bytes_total"),
"(Network.BytesTotalPerSec)", "(Network.BytesTotalPerSec)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.OutputQueueLength = prometheus.NewDesc( c.outputQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "output_queue_length_packets"), prometheus.BuildFQName(types.Namespace, Name, "output_queue_length_packets"),
"(Network.OutputQueueLength)", "(Network.OutputQueueLength)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsOutboundDiscarded = prometheus.NewDesc( c.packetsOutboundDiscarded = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_outbound_discarded_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_outbound_discarded_total"),
"(Network.PacketsOutboundDiscarded)", "(Network.PacketsOutboundDiscarded)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsOutboundErrors = prometheus.NewDesc( c.packetsOutboundErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_outbound_errors_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_outbound_errors_total"),
"(Network.PacketsOutboundErrors)", "(Network.PacketsOutboundErrors)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsReceivedDiscarded = prometheus.NewDesc( c.packetsReceivedDiscarded = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_received_discarded_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_received_discarded_total"),
"(Network.PacketsReceivedDiscarded)", "(Network.PacketsReceivedDiscarded)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsReceivedErrors = prometheus.NewDesc( c.packetsReceivedErrors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_received_errors_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_received_errors_total"),
"(Network.PacketsReceivedErrors)", "(Network.PacketsReceivedErrors)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsReceivedTotal = prometheus.NewDesc( c.packetsReceivedTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_received_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_received_total"),
"(Network.PacketsReceivedPerSec)", "(Network.PacketsReceivedPerSec)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsReceivedUnknown = prometheus.NewDesc( c.packetsReceivedUnknown = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_received_unknown_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_received_unknown_total"),
"(Network.PacketsReceivedUnknown)", "(Network.PacketsReceivedUnknown)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsTotal = prometheus.NewDesc( c.packetsTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_total"),
"(Network.PacketsPerSec)", "(Network.PacketsPerSec)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.PacketsSentTotal = prometheus.NewDesc( c.packetsSentTotal = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "packets_sent_total"), prometheus.BuildFQName(types.Namespace, Name, "packets_sent_total"),
"(Network.PacketsSentPerSec)", "(Network.PacketsSentPerSec)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
c.CurrentBandwidth = prometheus.NewDesc( c.currentBandwidth = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_bandwidth_bytes"), prometheus.BuildFQName(types.Namespace, Name, "current_bandwidth_bytes"),
"(Network.CurrentBandwidth)", "(Network.CurrentBandwidth)",
[]string{"nic"}, []string{"nic"},
nil, nil,
) )
var err error
c.nicIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicInclude))
if err != nil {
return err
}
c.nicExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicExclude))
if err != nil {
return err
}
return nil return nil
} }
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting net metrics", "desc", desc, "err", err) if err := c.collect(ctx, logger, ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting net metrics", "err", err)
return err return err
} }
return nil return nil
@@ -228,16 +235,17 @@ type networkInterface struct {
CurrentBandwidth float64 `perflib:"Current Bandwidth"` CurrentBandwidth float64 `perflib:"Current Bandwidth"`
} }
func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ctx *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
logger = log.With(logger, "collector", Name)
var dst []networkInterface var dst []networkInterface
if err := perflib.UnmarshalObject(ctx.PerfObjects["Network Interface"], &dst, c.logger); err != nil { if err := perflib.UnmarshalObject(ctx.PerfObjects["Network Interface"], &dst, logger); err != nil {
return nil, err return err
} }
for _, nic := range dst { for _, nic := range dst {
if c.nicExcludePattern.MatchString(nic.Name) || if c.config.NicExclude.MatchString(nic.Name) ||
!c.nicIncludePattern.MatchString(nic.Name) { !c.config.NicInclude.MatchString(nic.Name) {
continue continue
} }
@@ -248,83 +256,84 @@ func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metri
// Counters // Counters
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesReceivedTotal, c.bytesReceivedTotal,
prometheus.CounterValue, prometheus.CounterValue,
nic.BytesReceivedPerSec, nic.BytesReceivedPerSec,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesSentTotal, c.bytesSentTotal,
prometheus.CounterValue, prometheus.CounterValue,
nic.BytesSentPerSec, nic.BytesSentPerSec,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesTotal, c.bytesTotal,
prometheus.CounterValue, prometheus.CounterValue,
nic.BytesTotalPerSec, nic.BytesTotalPerSec,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.OutputQueueLength, c.outputQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
nic.OutputQueueLength, nic.OutputQueueLength,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsOutboundDiscarded, c.packetsOutboundDiscarded,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsOutboundDiscarded, nic.PacketsOutboundDiscarded,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsOutboundErrors, c.packetsOutboundErrors,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsOutboundErrors, nic.PacketsOutboundErrors,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsTotal, c.packetsTotal,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsPerSec, nic.PacketsPerSec,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedDiscarded, c.packetsReceivedDiscarded,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsReceivedDiscarded, nic.PacketsReceivedDiscarded,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedErrors, c.packetsReceivedErrors,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsReceivedErrors, nic.PacketsReceivedErrors,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedTotal, c.packetsReceivedTotal,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsReceivedPerSec, nic.PacketsReceivedPerSec,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedUnknown, c.packetsReceivedUnknown,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsReceivedUnknown, nic.PacketsReceivedUnknown,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PacketsSentTotal, c.packetsSentTotal,
prometheus.CounterValue, prometheus.CounterValue,
nic.PacketsSentPerSec, nic.PacketsSentPerSec,
name, name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CurrentBandwidth, c.currentBandwidth,
prometheus.GaugeValue, prometheus.GaugeValue,
nic.CurrentBandwidth/8, nic.CurrentBandwidth/8,
name, name,
) )
} }
return nil, nil
return nil
} }

View File

@@ -11,9 +11,9 @@ import (
) )
func BenchmarkCollector(b *testing.B) { func BenchmarkCollector(b *testing.B) {
// Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces. // PrinterInclude is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces.
localNicInclude := ".+" localNicInclude := ".+"
kingpin.CommandLine.GetArg(net.FlagNicInclude).StringVar(&localNicInclude) kingpin.CommandLine.GetArg("collector.net.nic-include").StringVar(&localNicInclude)
testutils.FuncBenchmarkCollector(b, net.Name, net.NewWithFlags) testutils.FuncBenchmarkCollector(b, net.Name, net.NewWithFlags)
} }

View File

@@ -7,6 +7,8 @@ import (
) )
func TestNetworkToInstanceName(t *testing.T) { func TestNetworkToInstanceName(t *testing.T) {
t.Parallel()
data := map[string]string{ data := map[string]string{
"Intel[R] Dual Band Wireless-AC 8260": "Intel_R__Dual_Band_Wireless_AC_8260", "Intel[R] Dual Band Wireless-AC 8260": "Intel_R__Dual_Band_Wireless_AC_8260",
} }

View File

@@ -3,13 +3,14 @@
package netframework_clrexceptions package netframework_clrexceptions
import ( import (
"github.com/prometheus-community/windows_exporter/pkg/types" "errors"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrexceptions" const Name = "netframework_clrexceptions"
@@ -18,58 +19,70 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
NumberofExcepsThrown *prometheus.Desc numberOfExceptionsThrown *prometheus.Desc
NumberofFilters *prometheus.Desc numberOfFilters *prometheus.Desc
NumberofFinallys *prometheus.Desc numberOfFinally *prometheus.Desc
ThrowToCatchDepth *prometheus.Desc throwToCatchDepth *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.NumberofExcepsThrown = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.numberOfExceptionsThrown = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "exceptions_thrown_total"), prometheus.BuildFQName(types.Namespace, Name, "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.", "Displays the total number of exceptions thrown since the application started. This includes both .NET exceptions and unmanaged exceptions that are converted into .NET exceptions.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberofFilters = prometheus.NewDesc( c.numberOfFilters = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "exceptions_filters_total"), prometheus.BuildFQName(types.Namespace, Name, "exceptions_filters_total"),
"Displays the total number of .NET exception filters executed. An exception filter evaluates regardless of whether an exception is handled.", "Displays the total number of .NET exception filters executed. An exception filter evaluates regardless of whether an exception is handled.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberofFinallys = prometheus.NewDesc( c.numberOfFinally = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "exceptions_finallys_total"), prometheus.BuildFQName(types.Namespace, Name, "exceptions_finallys_total"),
"Displays the total number of finally blocks executed. Only the finally blocks executed for an exception are counted; finally blocks on normal code paths are not counted by this counter.", "Displays the total number of finally blocks executed. Only the finally blocks executed for an exception are counted; finally blocks on normal code paths are not counted by this counter.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.ThrowToCatchDepth = prometheus.NewDesc( c.throwToCatchDepth = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "throw_to_catch_depth_total"), prometheus.BuildFQName(types.Namespace, Name, "throw_to_catch_depth_total"),
"Displays the total number of stack frames traversed, from the frame that threw the exception to the frame that handled the exception.", "Displays the total number of stack frames traversed, from the frame that threw the exception to the frame that handled the exception.",
[]string{"process"}, []string{"process"},
@@ -80,9 +93,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrexceptions metrics", "err", err)
return err return err
} }
return nil return nil
@@ -98,47 +112,45 @@ type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
ThrowToCatchDepthPersec uint32 ThrowToCatchDepthPersec uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRExceptions", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofExcepsThrown, c.numberOfExceptionsThrown,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberofExcepsThrown), float64(process.NumberofExcepsThrown),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofFilters, c.numberOfFilters,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberofFiltersPersec), float64(process.NumberofFiltersPersec),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofFinallys, c.numberOfFinally,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberofFinallysPersec), float64(process.NumberofFinallysPersec),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ThrowToCatchDepth, c.throwToCatchDepth,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.ThrowToCatchDepthPersec), float64(process.ThrowToCatchDepthPersec),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -8,6 +8,6 @@ import (
) )
func BenchmarkCollector(b *testing.B) { func BenchmarkCollector(b *testing.B) {
// No context name required as collector source is WMI // No context name required as Collector source is WMI
testutils.FuncBenchmarkCollector(b, netframework_clrexceptions.Name, netframework_clrexceptions.NewWithFlags) testutils.FuncBenchmarkCollector(b, netframework_clrexceptions.Name, netframework_clrexceptions.NewWithFlags)
} }

View File

@@ -3,13 +3,14 @@
package netframework_clrinterop package netframework_clrinterop
import ( import (
"github.com/prometheus-community/windows_exporter/pkg/types" "errors"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrinterop" const Name = "netframework_clrinterop"
@@ -18,51 +19,63 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
NumberofCCWs *prometheus.Desc numberOfCCWs *prometheus.Desc
Numberofmarshalling *prometheus.Desc numberOfMarshalling *prometheus.Desc
NumberofStubs *prometheus.Desc numberOfStubs *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.NumberofCCWs = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.numberOfCCWs = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "com_callable_wrappers_total"), prometheus.BuildFQName(types.Namespace, Name, "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.", "Displays the current number of COM callable wrappers (CCWs). A CCW is a proxy for a managed object being referenced from an unmanaged COM client.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.Numberofmarshalling = prometheus.NewDesc( c.numberOfMarshalling = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "interop_marshalling_total"), prometheus.BuildFQName(types.Namespace, Name, "interop_marshalling_total"),
"Displays the total number of times arguments and return values have been marshaled from managed to unmanaged code, and vice versa, since the application started.", "Displays the total number of times arguments and return values have been marshaled from managed to unmanaged code, and vice versa, since the application started.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberofStubs = prometheus.NewDesc( c.numberOfStubs = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "interop_stubs_created_total"), prometheus.BuildFQName(types.Namespace, Name, "interop_stubs_created_total"),
"Displays the current number of stubs created by the common language runtime. Stubs are responsible for marshaling arguments and return values from managed to unmanaged code, and vice versa, during a COM interop call or a platform invoke call.", "Displays the current number of stubs created by the common language runtime. Stubs are responsible for marshaling arguments and return values from managed to unmanaged code, and vice versa, during a COM interop call or a platform invoke call.",
[]string{"process"}, []string{"process"},
@@ -73,9 +86,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrinterop metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrinterop metrics", "err", err)
return err return err
} }
return nil return nil
@@ -91,40 +105,38 @@ type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
NumberofTLBimportsPersec uint32 NumberofTLBimportsPersec uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRInterop", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofCCWs, c.numberOfCCWs,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberofCCWs), float64(process.NumberofCCWs),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Numberofmarshalling, c.numberOfMarshalling,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.Numberofmarshalling), float64(process.Numberofmarshalling),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofStubs, c.numberOfStubs,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberofStubs), float64(process.NumberofStubs),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -7,8 +7,8 @@ import (
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrjit" const Name = "netframework_clrjit"
@@ -17,58 +17,65 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
NumberofMethodsJitted *prometheus.Desc numberOfMethodsJitted *prometheus.Desc
TimeinJit *prometheus.Desc timeInJit *prometheus.Desc
StandardJitFailures *prometheus.Desc standardJitFailures *prometheus.Desc
TotalNumberofILBytesJitted *prometheus.Desc totalNumberOfILBytesJitted *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.NumberofMethodsJitted = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, _ *wmi.Client) error {
c.numberOfMethodsJitted = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "jit_methods_total"), prometheus.BuildFQName(types.Namespace, Name, "jit_methods_total"),
"Displays the total number of methods JIT-compiled since the application started. This counter does not include pre-JIT-compiled methods.", "Displays the total number of methods JIT-compiled since the application started. This counter does not include pre-JIT-compiled methods.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TimeinJit = prometheus.NewDesc( c.timeInJit = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "jit_time_percent"), prometheus.BuildFQName(types.Namespace, Name, "jit_time_percent"),
"Displays the percentage of time spent in JIT compilation. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled.", "Displays the percentage of time spent in JIT compilation. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.StandardJitFailures = prometheus.NewDesc( c.standardJitFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "jit_standard_failures_total"), prometheus.BuildFQName(types.Namespace, Name, "jit_standard_failures_total"),
"Displays the peak number of methods the JIT compiler has failed to compile since the application started. This failure can occur if the MSIL cannot be verified or if there is an internal error in the JIT compiler.", "Displays the peak number of methods the JIT compiler has failed to compile since the application started. This failure can occur if the MSIL cannot be verified or if there is an internal error in the JIT compiler.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalNumberofILBytesJitted = prometheus.NewDesc( c.totalNumberOfILBytesJitted = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "jit_il_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "jit_il_bytes_total"),
"Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by the just-in-time (JIT) compiler since the application started", "Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by the just-in-time (JIT) compiler since the application started",
[]string{"process"}, []string{"process"},
@@ -79,9 +86,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrjit metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrjit metrics", "err", err)
return err return err
} }
return nil return nil
@@ -99,47 +107,45 @@ type Win32_PerfRawData_NETFramework_NETCLRJit struct {
TotalNumberofILBytesJitted uint32 TotalNumberofILBytesJitted uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRJit var dst []Win32_PerfRawData_NETFramework_NETCLRJit
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRJit", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofMethodsJitted, c.numberOfMethodsJitted,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberofMethodsJitted), float64(process.NumberofMethodsJitted),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeinJit, c.timeInJit,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.PercentTimeinJit)/float64(process.Frequency_PerfTime), float64(process.PercentTimeinJit)/float64(process.Frequency_PerfTime),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.StandardJitFailures, c.standardJitFailures,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.StandardJitFailures), float64(process.StandardJitFailures),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalNumberofILBytesJitted, c.totalNumberOfILBytesJitted,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalNumberofILBytesJitted), float64(process.TotalNumberofILBytesJitted),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -3,12 +3,14 @@
package netframework_clrloading package netframework_clrloading
import ( import (
"errors"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrloading" const Name = "netframework_clrloading"
@@ -17,93 +19,106 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
BytesinLoaderHeap *prometheus.Desc bytesInLoaderHeap *prometheus.Desc
Currentappdomains *prometheus.Desc currentAppDomains *prometheus.Desc
CurrentAssemblies *prometheus.Desc currentAssemblies *prometheus.Desc
CurrentClassesLoaded *prometheus.Desc currentClassesLoaded *prometheus.Desc
TotalAppdomains *prometheus.Desc totalAppDomains *prometheus.Desc
Totalappdomainsunloaded *prometheus.Desc totalAppDomainsUnloaded *prometheus.Desc
TotalAssemblies *prometheus.Desc totalAssemblies *prometheus.Desc
TotalClassesLoaded *prometheus.Desc totalClassesLoaded *prometheus.Desc
TotalNumberofLoadFailures *prometheus.Desc totalNumberOfLoadFailures *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.BytesinLoaderHeap = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.bytesInLoaderHeap = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "loader_heap_size_bytes"), prometheus.BuildFQName(types.Namespace, Name, "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.", "Displays the current size, in bytes, of the memory committed by the class loader across all application domains. Committed memory is the physical space reserved in the disk paging file.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.Currentappdomains = prometheus.NewDesc( c.currentAppDomains = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "appdomains_loaded_current"), prometheus.BuildFQName(types.Namespace, Name, "appdomains_loaded_current"),
"Displays the current number of application domains loaded in this application.", "Displays the current number of application domains loaded in this application.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.CurrentAssemblies = prometheus.NewDesc( c.currentAssemblies = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "assemblies_loaded_current"), prometheus.BuildFQName(types.Namespace, Name, "assemblies_loaded_current"),
"Displays the current number of assemblies loaded across all application domains in the currently running application. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", "Displays the current number of assemblies loaded across all application domains in the currently running application. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.CurrentClassesLoaded = prometheus.NewDesc( c.currentClassesLoaded = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "classes_loaded_current"), prometheus.BuildFQName(types.Namespace, Name, "classes_loaded_current"),
"Displays the current number of classes loaded in all assemblies.", "Displays the current number of classes loaded in all assemblies.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalAppdomains = prometheus.NewDesc( c.totalAppDomains = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "appdomains_loaded_total"), prometheus.BuildFQName(types.Namespace, Name, "appdomains_loaded_total"),
"Displays the peak number of application domains loaded since the application started.", "Displays the peak number of application domains loaded since the application started.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.Totalappdomainsunloaded = prometheus.NewDesc( c.totalAppDomainsUnloaded = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "appdomains_unloaded_total"), prometheus.BuildFQName(types.Namespace, Name, "appdomains_unloaded_total"),
"Displays the total number of application domains unloaded since the application started. If an application domain is loaded and unloaded multiple times, this counter increments each time the application domain is unloaded.", "Displays the total number of application domains unloaded since the application started. If an application domain is loaded and unloaded multiple times, this counter increments each time the application domain is unloaded.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalAssemblies = prometheus.NewDesc( c.totalAssemblies = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "assemblies_loaded_total"), prometheus.BuildFQName(types.Namespace, Name, "assemblies_loaded_total"),
"Displays the total number of assemblies loaded since the application started. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", "Displays the total number of assemblies loaded since the application started. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalClassesLoaded = prometheus.NewDesc( c.totalClassesLoaded = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "classes_loaded_total"), prometheus.BuildFQName(types.Namespace, Name, "classes_loaded_total"),
"Displays the cumulative number of classes loaded in all assemblies since the application started.", "Displays the cumulative number of classes loaded in all assemblies since the application started.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalNumberofLoadFailures = prometheus.NewDesc( c.totalNumberOfLoadFailures = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "class_load_failures_total"), prometheus.BuildFQName(types.Namespace, Name, "class_load_failures_total"),
"Displays the peak number of classes that have failed to load since the application started.", "Displays the peak number of classes that have failed to load since the application started.",
[]string{"process"}, []string{"process"},
@@ -114,9 +129,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrloading metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrloading metrics", "err", err)
return err return err
} }
return nil return nil
@@ -143,82 +159,80 @@ type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
TotalNumberofLoadFailures uint32 TotalNumberofLoadFailures uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLoading", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.BytesinLoaderHeap, c.bytesInLoaderHeap,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.BytesinLoaderHeap), float64(process.BytesinLoaderHeap),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Currentappdomains, c.currentAppDomains,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Currentappdomains), float64(process.Currentappdomains),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CurrentAssemblies, c.currentAssemblies,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.CurrentAssemblies), float64(process.CurrentAssemblies),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CurrentClassesLoaded, c.currentClassesLoaded,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.CurrentClassesLoaded), float64(process.CurrentClassesLoaded),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalAppdomains, c.totalAppDomains,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalAppdomains), float64(process.TotalAppdomains),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Totalappdomainsunloaded, c.totalAppDomainsUnloaded,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.Totalappdomainsunloaded), float64(process.Totalappdomainsunloaded),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalAssemblies, c.totalAssemblies,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalAssemblies), float64(process.TotalAssemblies),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalClassesLoaded, c.totalClassesLoaded,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalClassesLoaded), float64(process.TotalClassesLoaded),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalNumberofLoadFailures, c.totalNumberOfLoadFailures,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalNumberofLoadFailures), float64(process.TotalNumberofLoadFailures),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -3,12 +3,14 @@
package netframework_clrlocksandthreads package netframework_clrlocksandthreads
import ( import (
"errors"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrlocksandthreads" const Name = "netframework_clrlocksandthreads"
@@ -17,79 +19,92 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
CurrentQueueLength *prometheus.Desc currentQueueLength *prometheus.Desc
NumberofcurrentlogicalThreads *prometheus.Desc numberOfCurrentLogicalThreads *prometheus.Desc
NumberofcurrentphysicalThreads *prometheus.Desc numberOfCurrentPhysicalThreads *prometheus.Desc
Numberofcurrentrecognizedthreads *prometheus.Desc numberOfCurrentRecognizedThreads *prometheus.Desc
Numberoftotalrecognizedthreads *prometheus.Desc numberOfTotalRecognizedThreads *prometheus.Desc
QueueLengthPeak *prometheus.Desc queueLengthPeak *prometheus.Desc
TotalNumberofContentions *prometheus.Desc totalNumberOfContentions *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.CurrentQueueLength = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.currentQueueLength = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_queue_length"), prometheus.BuildFQName(types.Namespace, Name, "current_queue_length"),
"Displays the total number of threads that are currently waiting to acquire a managed lock in the application.", "Displays the total number of threads that are currently waiting to acquire a managed lock in the application.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberofcurrentlogicalThreads = prometheus.NewDesc( c.numberOfCurrentLogicalThreads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "current_logical_threads"), prometheus.BuildFQName(types.Namespace, Name, "current_logical_threads"),
"Displays the number of current managed thread objects in the application. This counter maintains the count of both running and stopped threads. ", "Displays the number of current managed thread objects in the application. This counter maintains the count of both running and stopped threads. ",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberofcurrentphysicalThreads = prometheus.NewDesc( c.numberOfCurrentPhysicalThreads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "physical_threads_current"), prometheus.BuildFQName(types.Namespace, Name, "physical_threads_current"),
"Displays the number of native operating system threads created and owned by the common language runtime to act as underlying threads for managed thread objects. This counter's value does not include the threads used by the runtime in its internal operations; it is a subset of the threads in the operating system process.", "Displays the number of native operating system threads created and owned by the common language runtime to act as underlying threads for managed thread objects. This counter's value does not include the threads used by the runtime in its internal operations; it is a subset of the threads in the operating system process.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.Numberofcurrentrecognizedthreads = prometheus.NewDesc( c.numberOfCurrentRecognizedThreads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "recognized_threads_current"), prometheus.BuildFQName(types.Namespace, Name, "recognized_threads_current"),
"Displays the number of threads that are currently recognized by the runtime. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", "Displays the number of threads that are currently recognized by the runtime. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.Numberoftotalrecognizedthreads = prometheus.NewDesc( c.numberOfTotalRecognizedThreads = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "recognized_threads_total"), prometheus.BuildFQName(types.Namespace, Name, "recognized_threads_total"),
"Displays the total number of threads that have been recognized by the runtime since the application started. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", "Displays the total number of threads that have been recognized by the runtime since the application started. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.QueueLengthPeak = prometheus.NewDesc( c.queueLengthPeak = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "queue_length_total"), prometheus.BuildFQName(types.Namespace, Name, "queue_length_total"),
"Displays the total number of threads that waited to acquire a managed lock since the application started.", "Displays the total number of threads that waited to acquire a managed lock since the application started.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalNumberofContentions = prometheus.NewDesc( c.totalNumberOfContentions = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "contentions_total"), prometheus.BuildFQName(types.Namespace, Name, "contentions_total"),
"Displays the total number of times that threads in the runtime have attempted to acquire a managed lock unsuccessfully.", "Displays the total number of times that threads in the runtime have attempted to acquire a managed lock unsuccessfully.",
[]string{"process"}, []string{"process"},
@@ -100,9 +115,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics", "err", err)
return err return err
} }
return nil return nil
@@ -123,68 +139,66 @@ type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
TotalNumberofContentions uint32 TotalNumberofContentions uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CurrentQueueLength, c.currentQueueLength,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.CurrentQueueLength), float64(process.CurrentQueueLength),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofcurrentlogicalThreads, c.numberOfCurrentLogicalThreads,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.NumberofcurrentlogicalThreads), float64(process.NumberofcurrentlogicalThreads),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofcurrentphysicalThreads, c.numberOfCurrentPhysicalThreads,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.NumberofcurrentphysicalThreads), float64(process.NumberofcurrentphysicalThreads),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Numberofcurrentrecognizedthreads, c.numberOfCurrentRecognizedThreads,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Numberofcurrentrecognizedthreads), float64(process.Numberofcurrentrecognizedthreads),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Numberoftotalrecognizedthreads, c.numberOfTotalRecognizedThreads,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.Numberoftotalrecognizedthreads), float64(process.Numberoftotalrecognizedthreads),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.QueueLengthPeak, c.queueLengthPeak,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.QueueLengthPeak), float64(process.QueueLengthPeak),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalNumberofContentions, c.totalNumberOfContentions,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalNumberofContentions), float64(process.TotalNumberofContentions),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -3,12 +3,14 @@
package netframework_clrmemory package netframework_clrmemory
import ( import (
"errors"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrmemory" const Name = "netframework_clrmemory"
@@ -17,117 +19,127 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
AllocatedBytes *prometheus.Desc allocatedBytes *prometheus.Desc
FinalizationSurvivors *prometheus.Desc finalizationSurvivors *prometheus.Desc
HeapSize *prometheus.Desc heapSize *prometheus.Desc
PromotedBytes *prometheus.Desc promotedBytes *prometheus.Desc
NumberGCHandles *prometheus.Desc numberGCHandles *prometheus.Desc
NumberCollections *prometheus.Desc numberCollections *prometheus.Desc
NumberInducedGC *prometheus.Desc numberInducedGC *prometheus.Desc
NumberofPinnedObjects *prometheus.Desc numberOfPinnedObjects *prometheus.Desc
NumberofSinkBlocksinuse *prometheus.Desc numberOfSinkBlocksInUse *prometheus.Desc
NumberTotalCommittedBytes *prometheus.Desc numberTotalCommittedBytes *prometheus.Desc
NumberTotalreservedBytes *prometheus.Desc numberTotalReservedBytes *prometheus.Desc
TimeinGC *prometheus.Desc timeInGC *prometheus.Desc
PromotedFinalizationMemoryfromGen0 *prometheus.Desc
PromotedMemoryfromGen0 *prometheus.Desc
PromotedMemoryfromGen1 *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.AllocatedBytes = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.allocatedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "allocated_bytes_total"), prometheus.BuildFQName(types.Namespace, Name, "allocated_bytes_total"),
"Displays the total number of bytes allocated on the garbage collection heap.", "Displays the total number of bytes allocated on the garbage collection heap.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.FinalizationSurvivors = prometheus.NewDesc( c.finalizationSurvivors = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "finalization_survivors"), prometheus.BuildFQName(types.Namespace, Name, "finalization_survivors"),
"Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized.", "Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.HeapSize = prometheus.NewDesc( c.heapSize = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "heap_size_bytes"), prometheus.BuildFQName(types.Namespace, Name, "heap_size_bytes"),
"Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated.", "Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated.",
[]string{"process", "area"}, []string{"process", "area"},
nil, nil,
) )
c.PromotedBytes = prometheus.NewDesc( c.promotedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "promoted_bytes"), prometheus.BuildFQName(types.Namespace, Name, "promoted_bytes"),
"Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection.", "Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection.",
[]string{"process", "area"}, []string{"process", "area"},
nil, nil,
) )
c.NumberGCHandles = prometheus.NewDesc( c.numberGCHandles = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "number_gc_handles"), prometheus.BuildFQName(types.Namespace, Name, "number_gc_handles"),
"Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.", "Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberCollections = prometheus.NewDesc( c.numberCollections = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "collections_total"), prometheus.BuildFQName(types.Namespace, Name, "collections_total"),
"Displays the number of times the generation objects are garbage collected since the application started.", "Displays the number of times the generation objects are garbage collected since the application started.",
[]string{"process", "area"}, []string{"process", "area"},
nil, nil,
) )
c.NumberInducedGC = prometheus.NewDesc( c.numberInducedGC = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "induced_gc_total"), prometheus.BuildFQName(types.Namespace, Name, "induced_gc_total"),
"Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect.", "Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberofPinnedObjects = prometheus.NewDesc( c.numberOfPinnedObjects = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "number_pinned_objects"), prometheus.BuildFQName(types.Namespace, Name, "number_pinned_objects"),
"Displays the number of pinned objects encountered in the last garbage collection.", "Displays the number of pinned objects encountered in the last garbage collection.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberofSinkBlocksinuse = prometheus.NewDesc( c.numberOfSinkBlocksInUse = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "number_sink_blocksinuse"), prometheus.BuildFQName(types.Namespace, Name, "number_sink_blocksinuse"),
"Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector.", "Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberTotalCommittedBytes = prometheus.NewDesc( c.numberTotalCommittedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "committed_bytes"), prometheus.BuildFQName(types.Namespace, Name, "committed_bytes"),
"Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file.", "Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.NumberTotalreservedBytes = prometheus.NewDesc( c.numberTotalReservedBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "reserved_bytes"), prometheus.BuildFQName(types.Namespace, Name, "reserved_bytes"),
"Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used.", "Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TimeinGC = prometheus.NewDesc( c.timeInGC = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "gc_time_percent"), prometheus.BuildFQName(types.Namespace, Name, "gc_time_percent"),
"Displays the percentage of time that was spent performing a garbage collection in the last sample.", "Displays the percentage of time that was spent performing a garbage collection in the last sample.",
[]string{"process"}, []string{"process"},
@@ -138,9 +150,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrmemory metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrmemory metrics", "err", err)
return err return err
} }
return nil return nil
@@ -180,35 +193,33 @@ type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
PromotedMemoryfromGen1 uint64 PromotedMemoryfromGen1 uint64
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRMemory", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AllocatedBytes, c.allocatedBytes,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.AllocatedBytesPersec), float64(process.AllocatedBytesPersec),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.FinalizationSurvivors, c.finalizationSurvivors,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.FinalizationSurvivors), float64(process.FinalizationSurvivors),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.HeapSize, c.heapSize,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Gen0heapsize), float64(process.Gen0heapsize),
process.Name, process.Name,
@@ -216,7 +227,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PromotedBytes, c.promotedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Gen0PromotedBytesPerSec), float64(process.Gen0PromotedBytesPerSec),
process.Name, process.Name,
@@ -224,7 +235,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.HeapSize, c.heapSize,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Gen1heapsize), float64(process.Gen1heapsize),
process.Name, process.Name,
@@ -232,7 +243,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PromotedBytes, c.promotedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Gen1PromotedBytesPerSec), float64(process.Gen1PromotedBytesPerSec),
process.Name, process.Name,
@@ -240,7 +251,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.HeapSize, c.heapSize,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Gen2heapsize), float64(process.Gen2heapsize),
process.Name, process.Name,
@@ -248,7 +259,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.HeapSize, c.heapSize,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.LargeObjectHeapsize), float64(process.LargeObjectHeapsize),
process.Name, process.Name,
@@ -256,14 +267,14 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberGCHandles, c.numberGCHandles,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.NumberGCHandles), float64(process.NumberGCHandles),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberCollections, c.numberCollections,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberGen0Collections), float64(process.NumberGen0Collections),
process.Name, process.Name,
@@ -271,7 +282,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberCollections, c.numberCollections,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberGen1Collections), float64(process.NumberGen1Collections),
process.Name, process.Name,
@@ -279,7 +290,7 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberCollections, c.numberCollections,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberGen2Collections), float64(process.NumberGen2Collections),
process.Name, process.Name,
@@ -287,47 +298,47 @@ func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, erro
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberInducedGC, c.numberInducedGC,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberInducedGC), float64(process.NumberInducedGC),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofPinnedObjects, c.numberOfPinnedObjects,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.NumberofPinnedObjects), float64(process.NumberofPinnedObjects),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberofSinkBlocksinuse, c.numberOfSinkBlocksInUse,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.NumberofSinkBlocksinuse), float64(process.NumberofSinkBlocksinuse),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberTotalCommittedBytes, c.numberTotalCommittedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.NumberTotalcommittedBytes), float64(process.NumberTotalcommittedBytes),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberTotalreservedBytes, c.numberTotalReservedBytes,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.NumberTotalreservedBytes), float64(process.NumberTotalreservedBytes),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeinGC, c.timeInGC,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(100*process.PercentTimeinGC)/float64(process.PercentTimeinGC_base), float64(100*process.PercentTimeinGC)/float64(process.PercentTimeinGC_base),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -3,12 +3,14 @@
package netframework_clrremoting package netframework_clrremoting
import ( import (
"errors"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrremoting" const Name = "netframework_clrremoting"
@@ -17,72 +19,85 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
Channels *prometheus.Desc channels *prometheus.Desc
ContextBoundClassesLoaded *prometheus.Desc contextBoundClassesLoaded *prometheus.Desc
ContextBoundObjects *prometheus.Desc contextBoundObjects *prometheus.Desc
ContextProxies *prometheus.Desc contextProxies *prometheus.Desc
Contexts *prometheus.Desc contexts *prometheus.Desc
TotalRemoteCalls *prometheus.Desc totalRemoteCalls *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.Channels = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.channels = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "channels_total"), prometheus.BuildFQName(types.Namespace, Name, "channels_total"),
"Displays the total number of remoting channels registered across all application domains since application started.", "Displays the total number of remoting channels registered across all application domains since application started.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.ContextBoundClassesLoaded = prometheus.NewDesc( c.contextBoundClassesLoaded = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "context_bound_classes_loaded"), prometheus.BuildFQName(types.Namespace, Name, "context_bound_classes_loaded"),
"Displays the current number of context-bound classes that are loaded.", "Displays the current number of context-bound classes that are loaded.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.ContextBoundObjects = prometheus.NewDesc( c.contextBoundObjects = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "context_bound_objects_total"), prometheus.BuildFQName(types.Namespace, Name, "context_bound_objects_total"),
"Displays the total number of context-bound objects allocated.", "Displays the total number of context-bound objects allocated.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.ContextProxies = prometheus.NewDesc( c.contextProxies = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "context_proxies_total"), prometheus.BuildFQName(types.Namespace, Name, "context_proxies_total"),
"Displays the total number of remoting proxy objects in this process since it started.", "Displays the total number of remoting proxy objects in this process since it started.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.Contexts = prometheus.NewDesc( c.contexts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "contexts"), prometheus.BuildFQName(types.Namespace, Name, "contexts"),
"Displays the current number of remoting contexts in the application.", "Displays the current number of remoting contexts in the application.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalRemoteCalls = prometheus.NewDesc( c.totalRemoteCalls = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "remote_calls_total"), prometheus.BuildFQName(types.Namespace, Name, "remote_calls_total"),
"Displays the total number of remote procedure calls invoked since the application started.", "Displays the total number of remote procedure calls invoked since the application started.",
[]string{"process"}, []string{"process"},
@@ -93,9 +108,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrremoting metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrremoting metrics", "err", err)
return err return err
} }
return nil return nil
@@ -113,61 +129,59 @@ type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
TotalRemoteCalls uint32 TotalRemoteCalls uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRRemoting", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Channels, c.channels,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.Channels), float64(process.Channels),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ContextBoundClassesLoaded, c.contextBoundClassesLoaded,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.ContextBoundClassesLoaded), float64(process.ContextBoundClassesLoaded),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ContextBoundObjects, c.contextBoundObjects,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.ContextBoundObjectsAllocPersec), float64(process.ContextBoundObjectsAllocPersec),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ContextProxies, c.contextProxies,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.ContextProxies), float64(process.ContextProxies),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.Contexts, c.contexts,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.Contexts), float64(process.Contexts),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalRemoteCalls, c.totalRemoteCalls,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalRemoteCalls), float64(process.TotalRemoteCalls),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -3,12 +3,14 @@
package netframework_clrsecurity package netframework_clrsecurity
import ( import (
"errors"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "netframework_clrsecurity" const Name = "netframework_clrsecurity"
@@ -17,58 +19,70 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics // A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
NumberLinkTimeChecks *prometheus.Desc numberLinkTimeChecks *prometheus.Desc
TimeinRTchecks *prometheus.Desc timeInRTChecks *prometheus.Desc
StackWalkDepth *prometheus.Desc stackWalkDepth *prometheus.Desc
TotalRuntimeChecks *prometheus.Desc totalRuntimeChecks *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.NumberLinkTimeChecks = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.numberLinkTimeChecks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "link_time_checks_total"), prometheus.BuildFQName(types.Namespace, Name, "link_time_checks_total"),
"Displays the total number of link-time code access security checks since the application started.", "Displays the total number of link-time code access security checks since the application started.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TimeinRTchecks = prometheus.NewDesc( c.timeInRTChecks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "rt_checks_time_percent"), prometheus.BuildFQName(types.Namespace, Name, "rt_checks_time_percent"),
"Displays the percentage of time spent performing runtime code access security checks in the last sample.", "Displays the percentage of time spent performing runtime code access security checks in the last sample.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.StackWalkDepth = prometheus.NewDesc( c.stackWalkDepth = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "stack_walk_depth"), prometheus.BuildFQName(types.Namespace, Name, "stack_walk_depth"),
"Displays the depth of the stack during that last runtime code access security check.", "Displays the depth of the stack during that last runtime code access security check.",
[]string{"process"}, []string{"process"},
nil, nil,
) )
c.TotalRuntimeChecks = prometheus.NewDesc( c.totalRuntimeChecks = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "runtime_checks_total"), prometheus.BuildFQName(types.Namespace, Name, "runtime_checks_total"),
"Displays the total number of runtime code access security checks performed since the application started.", "Displays the total number of runtime code access security checks performed since the application started.",
[]string{"process"}, []string{"process"},
@@ -79,9 +93,10 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics", "desc", desc, "err", err) if err := c.collect(ch); err != nil {
_ = level.Error(logger).Log("msg", "failed collecting win32_perfrawdata_netframework_netclrsecurity metrics", "err", err)
return err return err
} }
return nil return nil
@@ -98,47 +113,45 @@ type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
TotalRuntimeChecks uint32 TotalRuntimeChecks uint32
} }
func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRSecurity", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
for _, process := range dst { for _, process := range dst {
if process.Name == "_Global_" { if process.Name == "_Global_" {
continue continue
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.NumberLinkTimeChecks, c.numberLinkTimeChecks,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.NumberLinkTimeChecks), float64(process.NumberLinkTimeChecks),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TimeinRTchecks, c.timeInRTChecks,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.PercentTimeinRTchecks)/float64(process.Frequency_PerfTime), float64(process.PercentTimeinRTchecks)/float64(process.Frequency_PerfTime),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.StackWalkDepth, c.stackWalkDepth,
prometheus.GaugeValue, prometheus.GaugeValue,
float64(process.StackWalkDepth), float64(process.StackWalkDepth),
process.Name, process.Name,
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.TotalRuntimeChecks, c.totalRuntimeChecks,
prometheus.CounterValue, prometheus.CounterValue,
float64(process.TotalRuntimeChecks), float64(process.TotalRuntimeChecks),
process.Name, process.Name,
) )
} }
return nil, nil return nil
} }

View File

@@ -1,14 +1,15 @@
package nps package nps
import ( import (
"errors"
"fmt" "fmt"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/go-kit/log/level" "github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/yusufpapurcu/wmi"
) )
const Name = "nps" const Name = "nps"
@@ -17,207 +18,219 @@ type Config struct{}
var ConfigDefaults = Config{} var ConfigDefaults = Config{}
// collector is a Prometheus collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics // Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics.
type collector struct { type Collector struct {
logger log.Logger config Config
wmiClient *wmi.Client
AccessAccepts *prometheus.Desc accessAccepts *prometheus.Desc
AccessChallenges *prometheus.Desc accessChallenges *prometheus.Desc
AccessRejects *prometheus.Desc accessRejects *prometheus.Desc
AccessRequests *prometheus.Desc accessRequests *prometheus.Desc
AccessBadAuthenticators *prometheus.Desc accessBadAuthenticators *prometheus.Desc
AccessDroppedPackets *prometheus.Desc accessDroppedPackets *prometheus.Desc
AccessInvalidRequests *prometheus.Desc accessInvalidRequests *prometheus.Desc
AccessMalformedPackets *prometheus.Desc accessMalformedPackets *prometheus.Desc
AccessPacketsReceived *prometheus.Desc accessPacketsReceived *prometheus.Desc
AccessPacketsSent *prometheus.Desc accessPacketsSent *prometheus.Desc
AccessServerResetTime *prometheus.Desc accessServerResetTime *prometheus.Desc
AccessServerUpTime *prometheus.Desc accessServerUpTime *prometheus.Desc
AccessUnknownType *prometheus.Desc accessUnknownType *prometheus.Desc
AccountingRequests *prometheus.Desc accountingRequests *prometheus.Desc
AccountingResponses *prometheus.Desc accountingResponses *prometheus.Desc
AccountingBadAuthenticators *prometheus.Desc accountingBadAuthenticators *prometheus.Desc
AccountingDroppedPackets *prometheus.Desc accountingDroppedPackets *prometheus.Desc
AccountingInvalidRequests *prometheus.Desc accountingInvalidRequests *prometheus.Desc
AccountingMalformedPackets *prometheus.Desc accountingMalformedPackets *prometheus.Desc
AccountingNoRecord *prometheus.Desc accountingNoRecord *prometheus.Desc
AccountingPacketsReceived *prometheus.Desc accountingPacketsReceived *prometheus.Desc
AccountingPacketsSent *prometheus.Desc accountingPacketsSent *prometheus.Desc
AccountingServerResetTime *prometheus.Desc accountingServerResetTime *prometheus.Desc
AccountingServerUpTime *prometheus.Desc accountingServerUpTime *prometheus.Desc
AccountingUnknownType *prometheus.Desc accountingUnknownType *prometheus.Desc
} }
func New(logger log.Logger, _ *Config) types.Collector { func New(config *Config) *Collector {
c := &collector{} if config == nil {
c.SetLogger(logger) config = &ConfigDefaults
}
c := &Collector{
config: *config,
}
return c return c
} }
func NewWithFlags(_ *kingpin.Application) types.Collector { func NewWithFlags(_ *kingpin.Application) *Collector {
return &collector{} return &Collector{}
} }
func (c *collector) GetName() string { func (c *Collector) GetName() string {
return Name return Name
} }
func (c *collector) SetLogger(logger log.Logger) { func (c *Collector) GetPerfCounter(_ log.Logger) ([]string, error) {
c.logger = log.With(logger, "collector", Name)
}
func (c *collector) GetPerfCounter() ([]string, error) {
return []string{}, nil return []string{}, nil
} }
func (c *collector) Build() error { func (c *Collector) Close() error {
c.AccessAccepts = prometheus.NewDesc( return nil
}
func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error {
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
return errors.New("wmiClient or SWbemServicesClient is nil")
}
c.wmiClient = wmiClient
c.accessAccepts = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_accepts"), prometheus.BuildFQName(types.Namespace, Name, "access_accepts"),
"(AccessAccepts)", "(AccessAccepts)",
nil, nil,
nil, nil,
) )
c.AccessChallenges = prometheus.NewDesc( c.accessChallenges = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_challenges"), prometheus.BuildFQName(types.Namespace, Name, "access_challenges"),
"(AccessChallenges)", "(AccessChallenges)",
nil, nil,
nil, nil,
) )
c.AccessRejects = prometheus.NewDesc( c.accessRejects = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_rejects"), prometheus.BuildFQName(types.Namespace, Name, "access_rejects"),
"(AccessRejects)", "(AccessRejects)",
nil, nil,
nil, nil,
) )
c.AccessRequests = prometheus.NewDesc( c.accessRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_requests"), prometheus.BuildFQName(types.Namespace, Name, "access_requests"),
"(AccessRequests)", "(AccessRequests)",
nil, nil,
nil, nil,
) )
c.AccessBadAuthenticators = prometheus.NewDesc( c.accessBadAuthenticators = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_bad_authenticators"), prometheus.BuildFQName(types.Namespace, Name, "access_bad_authenticators"),
"(BadAuthenticators)", "(BadAuthenticators)",
nil, nil,
nil, nil,
) )
c.AccessDroppedPackets = prometheus.NewDesc( c.accessDroppedPackets = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_dropped_packets"), prometheus.BuildFQName(types.Namespace, Name, "access_dropped_packets"),
"(DroppedPackets)", "(DroppedPackets)",
nil, nil,
nil, nil,
) )
c.AccessInvalidRequests = prometheus.NewDesc( c.accessInvalidRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_invalid_requests"), prometheus.BuildFQName(types.Namespace, Name, "access_invalid_requests"),
"(InvalidRequests)", "(InvalidRequests)",
nil, nil,
nil, nil,
) )
c.AccessMalformedPackets = prometheus.NewDesc( c.accessMalformedPackets = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_malformed_packets"), prometheus.BuildFQName(types.Namespace, Name, "access_malformed_packets"),
"(MalformedPackets)", "(MalformedPackets)",
nil, nil,
nil, nil,
) )
c.AccessPacketsReceived = prometheus.NewDesc( c.accessPacketsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_packets_received"), prometheus.BuildFQName(types.Namespace, Name, "access_packets_received"),
"(PacketsReceived)", "(PacketsReceived)",
nil, nil,
nil, nil,
) )
c.AccessPacketsSent = prometheus.NewDesc( c.accessPacketsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_packets_sent"), prometheus.BuildFQName(types.Namespace, Name, "access_packets_sent"),
"(PacketsSent)", "(PacketsSent)",
nil, nil,
nil, nil,
) )
c.AccessServerResetTime = prometheus.NewDesc( c.accessServerResetTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_server_reset_time"), prometheus.BuildFQName(types.Namespace, Name, "access_server_reset_time"),
"(ServerResetTime)", "(ServerResetTime)",
nil, nil,
nil, nil,
) )
c.AccessServerUpTime = prometheus.NewDesc( c.accessServerUpTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_server_up_time"), prometheus.BuildFQName(types.Namespace, Name, "access_server_up_time"),
"(ServerUpTime)", "(ServerUpTime)",
nil, nil,
nil, nil,
) )
c.AccessUnknownType = prometheus.NewDesc( c.accessUnknownType = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "access_unknown_type"), prometheus.BuildFQName(types.Namespace, Name, "access_unknown_type"),
"(UnknownType)", "(UnknownType)",
nil, nil,
nil, nil,
) )
c.AccountingRequests = prometheus.NewDesc( c.accountingRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_requests"), prometheus.BuildFQName(types.Namespace, Name, "accounting_requests"),
"(AccountingRequests)", "(AccountingRequests)",
nil, nil,
nil, nil,
) )
c.AccountingResponses = prometheus.NewDesc( c.accountingResponses = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_responses"), prometheus.BuildFQName(types.Namespace, Name, "accounting_responses"),
"(AccountingResponses)", "(AccountingResponses)",
nil, nil,
nil, nil,
) )
c.AccountingBadAuthenticators = prometheus.NewDesc( c.accountingBadAuthenticators = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_bad_authenticators"), prometheus.BuildFQName(types.Namespace, Name, "accounting_bad_authenticators"),
"(BadAuthenticators)", "(BadAuthenticators)",
nil, nil,
nil, nil,
) )
c.AccountingDroppedPackets = prometheus.NewDesc( c.accountingDroppedPackets = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_dropped_packets"), prometheus.BuildFQName(types.Namespace, Name, "accounting_dropped_packets"),
"(DroppedPackets)", "(DroppedPackets)",
nil, nil,
nil, nil,
) )
c.AccountingInvalidRequests = prometheus.NewDesc( c.accountingInvalidRequests = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_invalid_requests"), prometheus.BuildFQName(types.Namespace, Name, "accounting_invalid_requests"),
"(InvalidRequests)", "(InvalidRequests)",
nil, nil,
nil, nil,
) )
c.AccountingMalformedPackets = prometheus.NewDesc( c.accountingMalformedPackets = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_malformed_packets"), prometheus.BuildFQName(types.Namespace, Name, "accounting_malformed_packets"),
"(MalformedPackets)", "(MalformedPackets)",
nil, nil,
nil, nil,
) )
c.AccountingNoRecord = prometheus.NewDesc( c.accountingNoRecord = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_no_record"), prometheus.BuildFQName(types.Namespace, Name, "accounting_no_record"),
"(NoRecord)", "(NoRecord)",
nil, nil,
nil, nil,
) )
c.AccountingPacketsReceived = prometheus.NewDesc( c.accountingPacketsReceived = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_packets_received"), prometheus.BuildFQName(types.Namespace, Name, "accounting_packets_received"),
"(PacketsReceived)", "(PacketsReceived)",
nil, nil,
nil, nil,
) )
c.AccountingPacketsSent = prometheus.NewDesc( c.accountingPacketsSent = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_packets_sent"), prometheus.BuildFQName(types.Namespace, Name, "accounting_packets_sent"),
"(PacketsSent)", "(PacketsSent)",
nil, nil,
nil, nil,
) )
c.AccountingServerResetTime = prometheus.NewDesc( c.accountingServerResetTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_server_reset_time"), prometheus.BuildFQName(types.Namespace, Name, "accounting_server_reset_time"),
"(ServerResetTime)", "(ServerResetTime)",
nil, nil,
nil, nil,
) )
c.AccountingServerUpTime = prometheus.NewDesc( c.accountingServerUpTime = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_server_up_time"), prometheus.BuildFQName(types.Namespace, Name, "accounting_server_up_time"),
"(ServerUpTime)", "(ServerUpTime)",
nil, nil,
nil, nil,
) )
c.AccountingUnknownType = prometheus.NewDesc( c.accountingUnknownType = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "accounting_unknown_type"), prometheus.BuildFQName(types.Namespace, Name, "accounting_unknown_type"),
"(UnknownType)", "(UnknownType)",
nil, nil,
@@ -228,20 +241,21 @@ func (c *collector) Build() error {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- prometheus.Metric) error {
if desc, err := c.CollectAccept(ch); err != nil { logger = log.With(logger, "collector", Name)
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("failed collecting NPS accept data: %s %v", desc, err)) if err := c.CollectAccept(ch); err != nil {
_ = level.Error(logger).Log("msg", fmt.Sprintf("failed collecting NPS accept data: %s", err))
return err return err
} }
if desc, err := c.CollectAccounting(ch); err != nil { if err := c.CollectAccounting(ch); err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("failed collecting NPS accounting data: %s %v", desc, err)) _ = level.Error(logger).Log("msg", fmt.Sprintf("failed collecting NPS accounting data: %s", err))
return err return err
} }
return nil return nil
} }
// Win32_PerfRawData_IAS_NPSAuthenticationServer docs: // Win32_PerfRawData_IAS_NPSAuthenticationServer docs:
// at the moment there is no Microsoft documentation // at the moment there is no Microsoft documentation.
type Win32_PerfRawData_IAS_NPSAuthenticationServer struct { type Win32_PerfRawData_IAS_NPSAuthenticationServer struct {
Name string Name string
@@ -279,172 +293,170 @@ type Win32_PerfRawData_IAS_NPSAccountingServer struct {
// CollectAccept sends the metric values for each metric // CollectAccept sends the metric values for each metric
// to the provided prometheus Metric channel. // to the provided prometheus Metric channel.
func (c *collector) CollectAccept(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) CollectAccept(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_IAS_NPSAuthenticationServer", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessAccepts, c.accessAccepts,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessAccepts), float64(dst[0].AccessAccepts),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessChallenges, c.accessChallenges,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessChallenges), float64(dst[0].AccessChallenges),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessRejects, c.accessRejects,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessRejects), float64(dst[0].AccessRejects),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessRequests, c.accessRequests,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessRequests), float64(dst[0].AccessRequests),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessBadAuthenticators, c.accessBadAuthenticators,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessBadAuthenticators), float64(dst[0].AccessBadAuthenticators),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessDroppedPackets, c.accessDroppedPackets,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessDroppedPackets), float64(dst[0].AccessDroppedPackets),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessInvalidRequests, c.accessInvalidRequests,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessInvalidRequests), float64(dst[0].AccessInvalidRequests),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessMalformedPackets, c.accessMalformedPackets,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessMalformedPackets), float64(dst[0].AccessMalformedPackets),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessPacketsReceived, c.accessPacketsReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessPacketsReceived), float64(dst[0].AccessPacketsReceived),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessPacketsSent, c.accessPacketsSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessPacketsSent), float64(dst[0].AccessPacketsSent),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessServerResetTime, c.accessServerResetTime,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessServerResetTime), float64(dst[0].AccessServerResetTime),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessServerUpTime, c.accessServerUpTime,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessServerUpTime), float64(dst[0].AccessServerUpTime),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessUnknownType, c.accessUnknownType,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccessUnknownType), float64(dst[0].AccessUnknownType),
) )
return nil, nil return nil
} }
func (c *collector) CollectAccounting(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *Collector) CollectAccounting(ch chan<- prometheus.Metric) error {
var dst []Win32_PerfRawData_IAS_NPSAccountingServer var dst []Win32_PerfRawData_IAS_NPSAccountingServer
q := wmi.QueryAll(&dst, c.logger) if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_IAS_NPSAccountingServer", &dst); err != nil {
if err := wmi.Query(q, &dst); err != nil { return err
return nil, err
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingRequests, c.accountingRequests,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingRequests), float64(dst[0].AccountingRequests),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingResponses, c.accountingResponses,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingResponses), float64(dst[0].AccountingResponses),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingBadAuthenticators, c.accountingBadAuthenticators,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingBadAuthenticators), float64(dst[0].AccountingBadAuthenticators),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingDroppedPackets, c.accountingDroppedPackets,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingDroppedPackets), float64(dst[0].AccountingDroppedPackets),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingInvalidRequests, c.accountingInvalidRequests,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingInvalidRequests), float64(dst[0].AccountingInvalidRequests),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingMalformedPackets, c.accountingMalformedPackets,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingMalformedPackets), float64(dst[0].AccountingMalformedPackets),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingNoRecord, c.accountingNoRecord,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingNoRecord), float64(dst[0].AccountingNoRecord),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingPacketsReceived, c.accountingPacketsReceived,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingPacketsReceived), float64(dst[0].AccountingPacketsReceived),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingPacketsSent, c.accountingPacketsSent,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingPacketsSent), float64(dst[0].AccountingPacketsSent),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingServerResetTime, c.accountingServerResetTime,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingServerResetTime), float64(dst[0].AccountingServerResetTime),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingServerUpTime, c.accountingServerUpTime,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingServerUpTime), float64(dst[0].AccountingServerUpTime),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccountingUnknownType, c.accountingUnknownType,
prometheus.CounterValue, prometheus.CounterValue,
float64(dst[0].AccountingUnknownType), float64(dst[0].AccountingUnknownType),
) )
return nil, nil return nil
} }

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