Compare commits

...

257 Commits

Author SHA1 Message Date
Ben Reedy
e07b2053af Merge pull request #937 from breed808/iis_flags
Add missing whitelist/blacklist checks for IIS
2022-02-02 18:18:13 +10:00
Ben Reedy
7d3c0d3b76 Add missing whitelist/blacklist checks for IIS
Checks were removed in 82f17fd despite flags still being present.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2022-02-02 08:56:50 +10:00
Ben Reedy
27b2ca0b76 Merge pull request #921 from aymericDD/fix/903
fix: iis metrics greater than IIS v7
2022-01-31 18:53:59 +10:00
Aymeric Daurelle
803a0a9a70 fix: iis metrics greater than IIS v7
The IIS >= 8 metrics was updated two times by application and caused a fatal error. The purpose
of this fix is to update metrics one time by application.

Signed-off-by: Aymeric Daurelle <aymeric.daurelle@cdiscount.com>
2022-01-31 09:24:52 +01:00
Ben Reedy
4891acba2d Merge pull request #934 from prometheus-community/dependabot/go_modules/github.com/prometheus/client_golang-1.12.1
Bump github.com/prometheus/client_golang from 1.11.0 to 1.12.1
2022-01-30 15:46:21 +10:00
Ben Reedy
fa51270218 Add new client_golang metrics to e2e output
Introduced in github.com/prometheus/client_golang v1.12.0

Signed-off-by: Ben Reedy <breed808@breed808.com>
2022-01-30 15:31:53 +10:00
dependabot[bot]
a68e6af15a Bump github.com/prometheus/client_golang from 1.11.0 to 1.12.1
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.11.0 to 1.12.1.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.11.0...v1.12.1)

---
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>
2022-01-30 04:49:07 +00:00
Ben Reedy
7ad9b6d74a Merge pull request #927 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.9.2
Bump github.com/Microsoft/hcsshim from 0.9.1 to 0.9.2
2022-01-30 14:48:21 +10:00
dependabot[bot]
9acd5e695e Bump github.com/Microsoft/hcsshim from 0.9.1 to 0.9.2
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.9.1...v0.9.2)

---
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>
2022-01-30 04:38:23 +00:00
Ben Reedy
277f141587 Merge pull request #924 from breed808/e2e_fix
Don't upgrade dependencies when installing tools
2022-01-30 12:12:45 +10:00
Ben Reedy
2a5c51a236 Don't upgrade dependencies when installing tools
Dependency upgrade has resulted in github.com/prometheus/client_golang
being upgraded from v1.11.0 to v1.12.0 prior to end-to-end test.
This new release introduces new `go_*` metrics, causing the test to
fail on the unexpected output.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2022-01-23 09:19:06 +10:00
Ben Reedy
ce205d4c4d Merge pull request #909 from akrauza/more-adfs-metrics-again
Add more ADFS metrics from `AD FS` CounterSet
2022-01-11 09:10:28 +10:00
Austin D. Krauza
2ed0ae837c Add more ADFS metrics from AD FS CounterSet
Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Reformat adfsCollector struct

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Add metrics to ADFS collector documentation

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Update ADFS collector with useful queries and links to documentation

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Remove bad table formatter

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Reformat ADFS collector using gofmt

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Fix ADFS Config and Artifact DB Query time metrics

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Update ADFS collector for Config and Artifact DB Query time from gauge to counter

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>

Update ADFS collector for Config and Artifact DB Query time from gauge to counter

Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>
2022-01-10 17:27:34 -05:00
Ben Reedy
a56ec9166b Merge pull request #912 from breed808/installer_port
Port should default to 9182 if not defined
2022-01-06 18:18:19 +10:00
Calle Pettersson
e03432a22d Merge pull request #901 from mjtrangoni/fix-some-promtool-warnings
Fix some promtool warnings
2022-01-06 09:12:55 +01:00
Ben Reedy
be004b8423 Port should default to 9182 if not defined
Resolves #911 which was introduced by 45e9357a.

This is due to the exporter only using the default port if no LISTEN_ADDR
**and** no LISTEN_PORT is defined.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2022-01-06 07:57:31 +10:00
Ben Reedy
e08a0411d6 Merge pull request #908 from akrauza/ADCS
Update repository readme with ADCS documentation link
2022-01-05 07:33:25 +10:00
Austin D. Krauza
3d7894049f Update repository readme with ADCS documentation link
Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>
2022-01-04 10:51:49 -05:00
Ben Reedy
de664d4b93 Merge pull request #905 from mjtrangoni/fix-counter-promtool-warnings
Fix counter metrics should have "_total" suffix issue
2022-01-03 08:06:01 +10:00
Ben Reedy
78e026b6ee Merge pull request #906 from mjtrangoni/fix-badge-gh-actions
README.md: Replace the AppVeyor badge with the GH Actions one
2022-01-03 08:04:26 +10:00
Ben Reedy
9eba8dd024 Merge pull request #896 from mjtrangoni/add-codespell
codespell: add GH Action for checking spelling issues
2022-01-03 08:03:05 +10:00
Mario Trangoni
01100d3e6e README.md: Replace the AppVeyor badge with the GH Actions one
Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2022-01-02 18:59:32 +01:00
Mario Trangoni
0f1eb4a936 Fix counter metrics should have "_total" suffix issue
Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2022-01-02 18:47:17 +01:00
Mario Trangoni
a8eefae123 codespell: add GH Action for checking spelling issues
After fixing all spelling issues in #892, this will prevent us for
adding new ones.

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2022-01-02 18:21:43 +01:00
Ben Reedy
746158d354 Merge pull request #895 from akrauza/ADCS
Add Collector for Active Directory Certificate Services (ADCS)
2022-01-02 19:43:47 +10:00
Ben Reedy
d9f4264fc4 Merge pull request #898 from breed808/github_actions
Migrate CI/CD to Github Actions
2022-01-02 19:15:40 +10:00
Austin D. Krauza
a89b53779d Initial commit for ADCS collector
Signed-off-by: Austin D. Krauza <krauza.austin@gmail.com>
2022-01-02 01:24:11 -05:00
Ben Reedy
27ceeecff3 Merge pull request #902 from breed808/textfile
Move textfile mtime metric from loop
2022-01-02 08:32:08 +10:00
Ben Reedy
1ba5835af6 Move textfile mtime metric from loop
Loop was erroneously creating duplicate `windows_textfile_mtime_seconds`
metrics, causing the exporter to return a HTTP 500 error and no metrics
from any collector.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2022-01-01 11:48:19 +10:00
Ben Reedy
0db956aa4d Migrate CI/CD to Github Actions
Signed-off-by: Ben Reedy <breed808@breed808.com>
2022-01-01 10:04:33 +10:00
Mario Trangoni
9d1628a329 promtool: Fix windows_time_ntp_client_time_source_count
Related to #659, this is a breaking change!

Fixes
```
windows_time_ntp_client_time_source_count non-histogram and non-summary metrics should not have "_count" suffix
```
for the time collector.

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-31 13:51:07 +01:00
Mario Trangoni
fc33fa320b promtool: Fix *_handle_count and *_thread_count
Related to #659, this is a breaking change!

Fixes

```
windows_process_handle_count non-histogram and non-summary metrics should not have "_count" suffix
windows_process_thread_count non-histogram and non-summary metrics should not have "_count" suffix
```

for process and terminal_services collectors.

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-31 13:51:07 +01:00
Ben Reedy
b6f88cbbdd Use pwsh to run e2e-test target
Powershell >= 5 is required for the `New-Guid` command in the e2e script.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-12-30 20:49:46 +10:00
Calle Pettersson
4b9b9e97cb Merge pull request #893 from prometheus-community/new-appveyor-token
Update CI token
2021-12-28 22:00:26 +01:00
Calle Pettersson
3ebe0e937e Update CI token
Signed-off-by: Calle Pettersson <calle@cape.nu>
2021-12-28 21:44:22 +01:00
Ben Reedy
4d771d2bce Merge pull request #892 from mjtrangoni/fix-golanci-lint
Fix and update golanci-lint reported issues
2021-12-25 10:34:02 +10:00
Mario Trangoni
919f90a571 golangci-lint: Acknowledge all remaining checks and update golanci-lint to v1.43.0
Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-24 11:19:05 +01:00
Ben Reedy
c7d07a37ea Merge pull request #883 from breed808/msi_listen_port
Remove explicit LISTEN_PORT from MSI installer
2021-12-19 08:30:21 +10:00
Ben Reedy
87c21bfa50 Merge pull request #891 from breed808/update_perflib
Update Perflib dependency
2021-12-19 08:27:14 +10:00
Mario Trangoni
df4f6b206b revive: make type exportable and remove unnecessary log word
See,
```
log/gokit_adapter.go:9:26: unexported-return: exported func NewToolkitAdapter returns unexported type *log.logAdapter, which can be annoying to use (revive)
func NewToolkitAdapter() *logAdapter {
                         ^
```

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-18 19:54:31 +01:00
Mario Trangoni
9e3c585a28 revive: Remove unnecessary = 0 from var declaration.
See,
```
$ GOOS=windows GOARCH=amd64 golangci-lint run  ./... 2>1 | grep var-declaration
collector/os.go:205:22: var-declaration: should drop = 0 from declaration of var fsipf; it is the zero value (revive)
collector/os.go:226:23: var-declaration: should drop = 0 from declaration of var pfbRaw; it is the zero value (revive)
```

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-18 19:30:47 +01:00
Mario Trangoni
e4a43c539b codespell: Fix word spelling issues
See,
```
$ codespell --skip=".git,./vendor" --ignore-words-list=calle
./exporter.go:262: overriden ==> overridden
./collector/dfsr.go:132: receieved ==> received
./collector/dns.go:140: reponses ==> responses
./collector/exchange.go:238: occational ==> occasional
./collector/mssql.go:1961: shoud ==> should
./collector/process.go:137: sharable ==> shareable
./collector/remote_fx.go:64: seccond ==> second
./docs/collector.dfsr.md:47: fils ==> fills, files, file
./docs/collector.exchange.md:39: lengt ==> length
./docs/collector.fsrmquota.md:3: Ressource ==> Resource
./docs/collector.fsrmquota.md:51: Ressource ==> Resource
./docs/collector.os.md:20: sotred ==> sorted, stored
./docs/collector.process.md:56: sharable ==> shareable
./docs/collector.smtp.md:27: mailformed ==> malformed
```

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-18 19:19:06 +01:00
Mario Trangoni
03e15a0f80 unconvert: Remove unnecessary conversion
See,
```
collector/os.go:306:10: unnecessary conversion (unconvert)
		float64(fsipf),
		       ^
```

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-18 19:05:31 +01:00
Mario Trangoni
b98a956d51 gofmt: Fix File is not gofmt-ed with -s for go1.17
Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2021-12-18 19:01:29 +01:00
Calle Pettersson
524bfde5a3 Merge pull request #887 from SouenMazouin/fix/request-error-total-iis
fix: add missing metrics for IIS version >= 8
2021-12-18 15:28:17 +01:00
Ben Reedy
963cee0a13 Update Perflib dependency
Dependabot has likely passed over this as there has been no tagged
release.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-12-18 19:31:08 +10:00
Ben Reedy
45e9357ad9 Remove explicit LISTEN_PORT from MSI installer
Explicit setting of listening port in the service definition causes port
setting in configuration file to be ignored.

Exporter already defines a default port (9812) if one is not specified,
so no impact from this change is anticipated.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-12-18 18:34:47 +10:00
Souen Mazouin
6120ea9be1 fix: add missing metrics for IIS version >= 8
Allows the following metrics to be exposed again, they had disappeared after the migration to perflib :
- worker_request_errors_total
- worker_current_websocket_requests
- worker_websocket_connection_accepted_total
- worker_websocket_connection_rejected_total

Signed-off-by: Souen Mazouin <souen.mazouin@cdiscount.com>
2021-12-14 17:44:08 +01:00
Ben Reedy
376060b053 Merge pull request #884 from prometheus-community/dependabot/go_modules/github.com/prometheus/exporter-toolkit-0.7.1
Bump github.com/prometheus/exporter-toolkit from 0.7.0 to 0.7.1
2021-12-14 10:45:31 +10:00
dependabot[bot]
e04c4aab29 Bump github.com/prometheus/exporter-toolkit from 0.7.0 to 0.7.1
Bumps [github.com/prometheus/exporter-toolkit](https://github.com/prometheus/exporter-toolkit) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/prometheus/exporter-toolkit/releases)
- [Changelog](https://github.com/prometheus/exporter-toolkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prometheus/exporter-toolkit/compare/v0.7.0...v0.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-06 11:35:00 +00:00
Ben Reedy
479e6b1381 Merge pull request #882 from geraudster/fix/textfile_default_path
Fix default path for textfile collector
2021-12-02 13:13:13 +10:00
Géraud Duge de bernonville
f6f7dc96e9 Get EXE directory
Signed-off-by: Géraud Duge de bernonville <geraud.dugedebernonville@ext.cdiscount.com>
2021-12-01 10:41:46 +01:00
Ben Reedy
f84f54afda Merge pull request #875 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.9.1
Bump github.com/Microsoft/hcsshim from 0.8.6 to 0.9.1
2021-11-15 08:27:59 +10:00
dependabot[bot]
e22ef6e3cc Bump github.com/Microsoft/hcsshim from 0.8.6 to 0.9.1
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.8.6 to 0.9.1.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.8.6...v0.9.1)

---
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>
2021-11-14 21:57:35 +00:00
Ben Reedy
02b69afe8b Merge pull request #874 from prometheus-community/dependabot/go_modules/github.com/sirupsen/logrus-1.8.1
Bump github.com/sirupsen/logrus from 1.6.0 to 1.8.1
2021-11-15 07:42:52 +10:00
dependabot[bot]
b7a0a09e58 Bump github.com/sirupsen/logrus from 1.6.0 to 1.8.1
Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.6.0 to 1.8.1.
- [Release notes](https://github.com/sirupsen/logrus/releases)
- [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sirupsen/logrus/compare/v1.6.0...v1.8.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-14 21:29:14 +00:00
Ben Reedy
6105792f29 Merge pull request #876 from prometheus-community/dependabot/go_modules/github.com/dimchansky/utfbom-1.1.1
Bump github.com/dimchansky/utfbom from 1.1.0 to 1.1.1
2021-11-15 07:23:25 +10:00
Ben Reedy
1fbc626ee2 Merge pull request #873 from prometheus-community/dependabot/go_modules/github.com/prometheus/common-0.32.1
Bump github.com/prometheus/common from 0.32.0 to 0.32.1
2021-11-15 07:21:13 +10:00
dependabot[bot]
ca07abc1cd Bump github.com/dimchansky/utfbom from 1.1.0 to 1.1.1
Bumps [github.com/dimchansky/utfbom](https://github.com/dimchansky/utfbom) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/dimchansky/utfbom/releases)
- [Commits](https://github.com/dimchansky/utfbom/compare/v1.1.0...v1.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-14 11:50:42 +00:00
dependabot[bot]
60583c3366 Bump github.com/prometheus/common from 0.32.0 to 0.32.1
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.32.0 to 0.32.1.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.32.0...v0.32.1)

---
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>
2021-11-14 11:42:09 +00:00
Ben Reedy
a7dcf5896c Merge pull request #871 from breed808/dependabot
Add Dependabot dependency tracking
2021-11-14 21:38:36 +10:00
Ben Reedy
438cb87fc7 Add Dependabot dependency tracking
Bot will submit PRs when new dependency versions are detected,
preventing dependencies from becoming out-of-date.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-11-14 21:34:26 +10:00
Ben Reedy
f8b6260ab5 Merge pull request #862 from breed808/dependencies
Update dependencies
2021-11-14 11:11:43 +10:00
Calle Pettersson
d2b3f0f94b Merge pull request #869 from rnjstjdgh/master
Update collector.net.md
2021-11-11 09:14:54 +01:00
rnjstjdgh
d6b4466bc3 Update collector.net.md
Signed-off-by: rnjstjdgh <gshgsh0831@gmail.com>
2021-11-11 14:52:32 +09:00
Calle Pettersson
ce3d517cb3 Merge pull request #863 from jsturtevant/fix-service-identification
use IsWindowsService to detect if running as service
2021-11-05 18:47:18 +01:00
James Sturtevant
a6ea021468 use IsWindowsService to detect if running as service
Signed-off-by: James Sturtevant <jstur@microsoft.com>
2021-11-05 10:15:39 -07:00
Ben Reedy
b58dfdf4f3 Update perflib_exporter dependency
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-11-05 18:30:03 +10:00
Ben Reedy
676eb55f99 Update Prometheus dependencies
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-11-05 18:30:01 +10:00
Ben Reedy
121d9980c1 Replace go-kit/kit with go-kit/log
External log package has been extracted to a separate external
repository and module.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-11-05 18:29:59 +10:00
Calle Pettersson
947d8473e0 Merge pull request #861 from prometheus-community/maintainers-contacts
Update MAINTAINERS with security contacts
2021-10-29 10:36:43 +02:00
Calle Pettersson
c1569686f7 Update MAINTAINERS with security contacts
Signed-off-by: Calle Pettersson <calle@cape.nu>
2021-10-27 20:46:46 +02:00
Ben Reedy
75966fd37c Merge pull request #848 from ArtamonovEvgenii/master
Set relative default path for textfile collector
2021-10-23 14:27:00 +10:00
eartamonov
d0cfc14af9 Set relative default path for textfile collector
Signed-off-by: Artamonov Evgenii <evgenyi.artamonov@gmail.com>
2021-10-19 14:23:11 +03:00
Ben Reedy
941b66d342 Merge pull request #846 from JDA88/patch-1
Document expected delays in the size metrics
2021-10-01 08:13:58 +10:00
Ben Reedy
388195be97 Update e2e output to match help text changes
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-10-01 08:09:03 +10:00
JDA88
bbefd8ac97 Document expected delays in the size metrics
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-10-01 07:58:04 +10:00
Ben Reedy
5b92e1bd3d Merge pull request #841 from breed808/thermal_empty
Thermalzone: return error on empty result
2021-10-01 05:45:09 +10:00
Dave Owen
82f17fd607 Collect IIS metrics using Perflib (#832)
Rewrite IIS collector to use Perflib

Signed-off-by: David Owen <dowen@meddbase.com>
2021-09-25 17:00:39 +02:00
Ben Reedy
3e37b7b6f0 Merge pull request #840 from newrelic-forks/fix_service_memory_leak
Service Api collection close servicehandler to avoid memory leak
2021-09-25 18:22:21 +10:00
Ben Reedy
5d29ff6497 Thermalzone: return error on empty result
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-09-25 15:35:45 +10:00
Alvaro Cabanas
f4f5aaf146 Service Api collection close servicehandler to avoid memory leak
Signed-off-by: Alvaro Cabanas <acabanas@newrelic.com>
2021-09-23 17:45:31 +02:00
Ben Reedy
5931604b58 Merge pull request #812 from carlossscastro/master
Services collection using API (no WMI)
2021-08-26 08:26:07 +10:00
Carlos Castro
67ca5e5ef2 Update service.go
Signed-off-by: Carlos Castro <ccastro@newrelic.com>
2021-08-25 17:19:41 +01:00
Carlos Castro
384183120f Update service.go
Signed-off-by: Carlos Castro <ccastro@newrelic.com>
2021-08-25 17:19:41 +01:00
Carlos Castro
a9ac2d4672 Collect services using windows api
Signed-off-by: Carlos Castro <ccastro@newrelic.com>
2021-08-25 17:19:41 +01:00
Benjamin Blattberg
1b96bb6d08 Add MSSQL Wait Statistics (#793)
Signed-off-by: benjaminjb <benjamin.blattberg@gmail.com>
2021-06-29 21:32:08 +02:00
Ben Reedy
cc45eeb90b Merge pull request #809 from breed808/process_working_set_private
Add missing Process Collector metrics
2021-06-25 08:36:43 +10:00
Ben Reedy
4b2cd0a024 Merge pull request #759 from breed808/textfile
Fix textfile crashes with duplicate metrics
2021-06-25 08:36:21 +10:00
Ben Reedy
ad447a6b08 Add unit suffix to process working_set metric
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-06-19 09:02:30 +10:00
Ben Reedy
e4d7604193 Move process metric documentation to markdown file
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-06-19 09:02:28 +10:00
Ben Reedy
757f88be04 Add missing process counters
Working Set Private and Working Set Peak were being collected, but not
exposed by the exporter.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-06-19 09:02:26 +10:00
Calle Pettersson
cff484b5e1 Merge pull request #804 from max-len/bandwidth-bytes
Export CurrentBandwidth as bytes
2021-06-16 20:16:45 +02:00
Calle Pettersson
2dc568b5cd Merge pull request #805 from max-len/typo
Fix typo: process_memory_limit_bytes
2021-06-16 20:14:55 +02:00
Calle Pettersson
448f505729 Merge pull request #807 from max-len/doc-cpu
Fix doc: collector.cpu.md
2021-06-16 20:12:59 +02:00
Max Lendrich
6d1ba11a8e Fix doc: collector.cpu.md
Signed-off-by: Max Lendrich <maximilian.lendrich@sap.com>
2021-06-16 15:18:29 +02:00
Max Lendrich
0f5a232142 Fix typo
Signed-off-by: Max Lendrich <maximilian.lendrich@sap.com>
2021-06-15 12:38:23 +02:00
Max Lendrich
bbab591570 Export CurrentBandwidth as bytes
From https://prometheus.io/docs/practices/naming/:
To avoid confusion combining different metrics, always use bytes, even
where bits appear more common.

Fixes #800

Signed-off-by: Max Lendrich <maximilian.lendrich@sap.com>
2021-06-14 17:33:27 +02:00
Ben Reedy
2bc3c1859a Merge pull request #802 from breed808/log_dependency
Replace deprecated log lib in remaining collectors
2021-06-12 19:52:29 +10:00
Ben Reedy
7c61a4dc25 Run "go mod tidy" on project
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-06-12 11:57:46 +10:00
Ben Reedy
5a57da53be Replace deprecated log lib in remaining collectors
Some collectors were missed when migrating to the local
github.com/prometheus-community/windows_exporter/log library.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-06-12 11:57:40 +10:00
Calle Pettersson
72c46664db Merge pull request #789 from Wittionary/issue-776
Fixes #776
2021-05-25 07:35:49 +02:00
Witt Allen
8689c41c68 Added a 'data source' field to specify hcsshim of Host Compute Services in Hyper-V is used
Signed-off-by: Witt Allen <qwert59@gmail.com>
2021-05-24 00:57:20 -05:00
Calle Pettersson
74eac8f29b Merge pull request #788 from benridley/bugfix_sysinfo_layout
Correct layout of SystemInfo structs
2021-05-21 09:41:34 +02:00
Ben Ridley
bb48f1caac Correct layout of SystemInfo structs to prevent incorrect fields being read
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-05-20 16:30:52 -07:00
Ben Reedy
068d03bd01 Merge pull request #783 from breed808/msmq_remove_hardcoded_queue
Remove hard-coded "Computer Queues" filter
2021-05-17 16:58:50 +10:00
Ben Reedy
5072879dca Check duplicates across entire textfile set
Check all textfile metrics will be checked for duplicates. If duplicates
are detected, drop all metrics and log error.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-05-17 16:54:28 +10:00
Ben Reedy
0fb7eec670 Remove hard-coded "Computer Queues" filter
msmq collector would only collect from a hard-coded "Computer Queues"
queue.
Removal of filter allows other queues to be queried with
the collector.msmq.msmq-where flag.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-05-16 14:53:54 +10:00
Ben Reedy
4293497b29 Fix textfile crashes with duplicate metrics
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-05-12 20:57:17 +10:00
Ben Reedy
95f10f19cb Merge pull request #778 from Wittionary/fix-issue-777
Fixes #777
2021-05-03 14:23:03 +10:00
Witt
288f2a60e7 Changed 'Yes' to 'No' to reflect current state of collectors enabled by default
Signed-off-by: Witt Allen <qwert59@gmail.com>
2021-05-02 19:40:33 -05:00
Ben Reedy
2e32b0e2b1 Merge pull request #767 from louij2/patch-1
Update collector.service.md
2021-05-01 13:14:26 +10:00
Calle Pettersson
09759a4e8c Merge pull request #698 from ramonsmits/patch-1
Example - Using [defaults] with `--collectors.enabled` argument
2021-04-25 19:53:42 +02:00
louij2
dfd42a6c0c Update collector.service.md
Added more details for monitoring multiple services.

Signed-off-by: Luca Chana <clubdog123@gmail.com>
2021-04-24 21:05:36 +01:00
Ramon Smits
576c3bf918 Example - Using [defaults] with --collectors.enabled argument
Signed-off-by: Ramon Smits <ramon.smits@gmail.com>
2021-04-23 18:52:52 +02:00
Ben Reedy
19fee044bf Merge pull request #765 from breed808/checksums
CI: Output artifacts in single, flat directory.
2021-04-20 19:00:35 +10:00
Ben Reedy
45a74fdb7f CI: Output artifacts in single, flat directory.
Nested directories caused issues with promu checksum output, causing
user checks of the sha265sums.txt file to fail as the filenames did not
match.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-04-19 19:38:17 +10:00
Ben Reedy
db00553ca6 Merge pull request #744 from breed808/tests
Add benchmark for each collector
2021-04-01 22:35:08 +10:00
Ben Reedy
a2c4bf6a2d Add benchmark for each collector
Benchmarks will allow for easier identification of slow collectors.
Additionally, they increase test coverage of the collectors, with some
collectors now reaching 80-95% coverage with this change.

Collector benchmarks have been structed so that common functionality is
present in `collector/collector_test.go` as is done with non-test
functionality in `collector/collector.go`.
Test logic that is specific to individual collectors is present in the
collector test file (E.G. `collector/process_test.go` for the Process
collector).

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-04-01 22:28:54 +10:00
Calle Pettersson
7adcac8f39 Merge pull request #702 from benridley/dev_cs_collector
Replace WMI in cs and os collectors
2021-03-30 21:26:23 +02:00
Ben Ridley
863b7d8ab4 Merge branch 'dev_cs_collector' of https://github.com/benridley/windows_exporter into dev_cs_collector 2021-03-29 10:14:26 -07:00
Ben Ridley
33c6b2c6a5 Address GitHub feedback
- Defer registry close calls
- Ensure size parameter in GetComputerName is properly specified
- Clean up some comments to ensure correctness

Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-29 10:13:36 -07:00
Calle Pettersson
6dee2422e1 Merge pull request #753 from prometheus-community/fix-ci
Update CI to install tools with go install rather than go get
2021-03-28 10:41:25 +02:00
Calle Pettersson
5d224b43ca Update CI to install tools with go install rather than go get
Signed-off-by: Calle Pettersson <calle@cape.nu>
2021-03-27 15:30:50 +01:00
Calle Pettersson
3f2a143104 Merge pull request #748 from majerus1223/remote_interactive
Fix typo on remote_interactive
2021-03-19 11:34:25 +01:00
Ben Ridley
ee3848141c Simplify struct usage and comments
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
Ben Ridley
df2a7a9ec0 Remove temporary uintptr values, as the garbage collector can move addresses from under them.
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
Ben Ridley
05f0f6f688 Add idiomatic wrappers to be exposed publically, and hide low-level
WinAPI operations

Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
Ben Ridley
d947d0f6db Refactor remaining sysinfoapi calls into header package
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
Ben Ridley
d063bc0842 Add correct scrape context to OS benchmark
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
retryW
dd473c4807 Fixed paging free bytes
moved

Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
retryW
7bd58abd27 Converted PagingFreeBytes to use perflib
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
retryW
6f941044c7 Change Sprintf interpolation to use explicit types
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
retryW
3da11645cf added os_test.go and removed wmi for testing
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
retryW
048bff919e Converted most metrics to non-wmi
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
retryW
f76334213d Convert os time and timezone from WMI to native go
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
Ben Ridley
71054ac429 Replace the CS collector with native WinAPI calls to sysinfoapi
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-18 16:18:47 -07:00
Ben Ridley
248b7214e3 Move netapi free back to a defer statement
Signed-off-by: Ben Ridley <benridley29@gmail.com>
2021-03-19 10:13:04 +11:00
majerus
094558b1f1 Fix typo
Signed-off-by: majerus <james_majerus@msn.com>
2021-03-16 09:12:56 -05:00
Ben Reedy
18495abb69 Merge pull request #736 from basroovers/master
Typo in tcp doc
2021-03-07 11:04:18 +10:00
Calle Pettersson
f316d81d50 Merge pull request #735 from roidelapluie/web-cfg-file
Update web config file flag to match upstream
2021-02-24 15:15:07 +01:00
Bas Roovers
cc709ac380 Update collector.tcp.md
Changed windows_tcp_connections_established to gauge in tcp doc

Signed-off-by: Bas Roovers <basroovers@icloud.com>
2021-02-24 14:39:07 +01:00
Julien Pivotto
2262b88fac Update web config file flag to match upstream
Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
2021-02-24 00:23:38 +01:00
Ben Reedy
795cc5ca85 Merge pull request #730 from breed808/experimental_warnings
Move experimental warnings from init()
2021-02-22 18:53:05 +10:00
Ben Reedy
ce0513f69d Move experimental warnings from init()
init() causes warnings to be emitted despite collectors not being enabled.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-02-20 09:03:42 +10:00
Ben Reedy
ee146b3710 Merge pull request #726 from higels/cpu_info_collector
Add a cpu_info collector
2021-02-20 08:55:06 +10:00
Steffen Higel
a9752ebc1e adding a "data source" field to the documentation, to make it clear that this data comes from WMI
Signed-off-by: Steffen Higel <higels@valvesoftware.com>
2021-02-19 08:30:12 -08:00
Calle Pettersson
d54aa033b1 Merge pull request #723 from breed808/cache_collector
Cache collector
2021-02-19 09:44:24 +01:00
Ben Reedy
3682c1b9af Rewrite cache collector to use perflib
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-02-19 18:29:37 +10:00
Ben Reedy
5af2a781cb Merge pull request #693 from SuperQ/https
Add HTTPS configuration
2021-02-19 18:20:06 +10:00
Steffen Higel
7086e0f627 Add a cpu_info collector
The cpu_info collector exposes a single metric per socket with some
information on installed CPUs, somewhat like the node_cpu_info metric

Signed-off-by: Steffen Higel <higels@valvesoftware.com>
2021-02-15 17:13:58 -08:00
Bill Bagdon
682378e170 Add docs
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-02-12 18:13:04 +10:00
Bagdon, Bill
c1fff498c6 Create cache collector
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-02-12 18:13:01 +10:00
Ben Reedy
648b6e0ab5 Merge pull request #719 from breed808/dfsr_unique_metric_names
Ensure dfsr collector metric names are unique
2021-02-09 21:36:49 +10:00
Ben Reedy
e9abe4d5f5 Ensure dfsr collector metric names are unique
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-02-08 09:38:29 +10:00
Ben Reedy
0af38ddbcf Merge pull request #716 from jsturtevant/add-containerd-support
Set container collector prefix based on owner property
2021-02-05 07:39:51 +10:00
James Sturtevant
b615301efc set prefix based on owner property
Signed-off-by: James Sturtevant <jstur@microsoft.com>
2021-02-04 09:41:59 -08:00
Ben Reedy
25eb64bb3d Merge pull request #717 from jsturtevant/patch-1
Use correct metric name for windows_net_packets_outbound_discarded
2021-02-03 07:12:13 +10:00
James Sturtevant
19fbd57f60 Use correct metric name
Signed-off-by: James Sturtevant <jstur@microsoft.com>
2021-02-02 11:47:20 -08:00
Ben Reedy
b9b60f1ea0 Merge pull request #710 from breed808/dfsr_descriptions
Add missing dfsr metric descriptions
2021-02-02 13:45:37 +10:00
Calle Pettersson
eaa003f5af Add gokit adapter to make https toolkit work
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2021-01-30 11:53:51 +01:00
Calle Pettersson
c5a545540d Take over prometheus/common/log into local log package
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2021-01-30 11:53:51 +01:00
Calle Pettersson
054cf5c5f5 Include log from prometheus/common/log
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2021-01-30 11:53:51 +01:00
Ben Kochie
cdc81b03d5 Add HTTPS configuration
Add the exporter-toolkit https package to allow configuring TLS and
auth.

Signed-off-by: Ben Kochie <superq@gmail.com>
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2021-01-30 11:53:51 +01:00
Ben Reedy
e141e531ed Remove unused dfsr meta metrics and function
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-01-30 18:56:45 +10:00
Ben Reedy
b44d855fe0 Add missing dfsr metric descriptions
Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-01-30 17:10:37 +10:00
Ben Reedy
4b66473d2e Merge pull request #706 from breed808/284
Remove "total" suffix from dns_memory_used_bytes
2021-01-30 14:39:59 +10:00
Ben Reedy
556138189a Remove "total" suffix from dns_memory_used_bytes
Metric is a gauge and therefore should not have the "total" suffix.
2021-01-27 07:24:23 +10:00
Ben Reedy
7456afecae Merge pull request #689 from breed808/time_doc
Document version requirement for time collector
2021-01-22 17:58:29 +10:00
Ben Reedy
8407f4aeb8 Document version requirement for time collector
Windows Server 2016 or newer is required for the collector, as the
perflib counters were not exposed in previous versions.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2021-01-17 10:57:51 +10:00
Ben Reedy
6b8e9bee3f Merge pull request #699 from prometheus-community/repo_sync
Synchronize common files from prometheus/prometheus
2021-01-17 10:44:12 +10:00
prombot
eb15f8ee80 Update common Prometheus files
Signed-off-by: prombot <prometheus-team@googlegroups.com>
2021-01-17 00:06:11 +00:00
Ben Reedy
2c7bea1892 Merge pull request #691 from breed808/mssql_label
Rename mssql instance label to mssql_instance
2021-01-14 21:12:28 +10:00
Ben Reedy
59ba77b87f Rename mssql instance label to mssql_instance
Instance label is conflicting with default Prometheus "instance" label
which is added when scraping targets.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-31 09:36:36 +10:00
Ben Reedy
9723aa2218 Merge pull request #671 from breed808/dfsr
Add DFSR collector
2020-12-20 12:26:12 +10:00
Ben Reedy
9d03debcb6 Add experimental notice to dfsr collector
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-20 12:10:38 +10:00
Ben Reedy
2837bdfb50 Add/move DFSR metric units to end of metric name
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-09 19:55:14 +10:00
Ben Reedy
a1a986f4d0 Reset mssql child failure counter on each scrape
Resolves issue where collector would always return a failure after an
inital failure, as the counter was not reset.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-09 19:55:14 +10:00
Ben Reedy
769b15eb86 Execute DFSR child collectors serially
Previous concurrent setup was not required due to speed of Perflib
collectors.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-09 19:55:13 +10:00
Ben Reedy
b5ce53fdac Merge mssql and dfsr expandEnabledCollectors func
Move to common collector.go and add function test.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-09 19:55:13 +10:00
Ben Reedy
ccac306c2d Rewrite DFSR collector to use sub collectors
DFSR collector now follow similar structure to the MSSQL collector,
where several 'child' collectors are run concurrently, depending on user
input from the `--collectors.dfsr.sources-enabled` flag.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-09 19:55:13 +10:00
Ben Reedy
df0618e64d Add DFSR collectors
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-09 19:55:13 +10:00
Ben Reedy
433e00a20b Add CI support for textfile collector
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-07 08:01:07 +10:00
Ben Reedy
e8ffeaa0d7 Add end-to-end test to Appveyor CI
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-07 08:01:07 +10:00
Ben Reedy
c93b709f96 Make build idempotent
Only rebuild windows_exporter.exe on changes to any Go source files.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-07 08:01:07 +10:00
Ben Reedy
b300998b4b Add smoketest script
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-12-07 08:01:07 +10:00
Ben Reedy
6e0ac6a1fc Update prometheus client library to v1.8.0
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-30 09:26:34 +10:00
Ben Reedy
ec6b7210e3 Fix network collector metric names
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-30 09:21:09 +10:00
Ben Reedy
704f6e2fe4 Fix ADFS collector metric names
Prometheus counters should have a '_total' suffix

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-30 09:21:09 +10:00
Calle Pettersson
7a16d111b0 Clarify supported versions of Windows
Installation on versions previous to Win7/Server2008R2 will now fail

Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-11-23 12:40:19 +10:00
Ben Reedy
82471f39cd Add missing time entry in docs README
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-23 12:29:01 +10:00
Ben Reedy
23dafc93ed Add SMTP collector
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-23 12:29:01 +10:00
Calle Pettersson
cdbb27d0b4 Fix collector flags not being registered
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-11-07 17:13:00 +10:00
Calle Pettersson
2fbd0464dc Merge pull request #651 from breed808/config_files
Fix exporter failing to start without config flag
2020-11-07 07:25:24 +01:00
Ben Reedy
f616589c5f Fix exporter failing to start without config flag
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-03 19:46:05 +10:00
Ben Reedy
f623c0ed89 Add unit test for config flattening functions
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
ce5c6eed72 Add configuration file documentation
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
d7122930d0 Flatten nested YAML data in specified config file
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
96aa2cf095 Add initial support for YAML configuration files
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Ben Reedy
6231eb43e8 Use kingpin application for flags
Will be required to pass application object to config file functions.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-11-02 08:40:59 +10:00
Calle Pettersson
0880ec6a1a Add service dependency on wmiApSrv
This appears to fix service startup issues on certain systems, eg #637

Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-11-02 08:38:42 +10:00
Calle Pettersson
8f85475725 Add CODEOWNERS file
Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-11-02 08:33:45 +10:00
Björn Fischer
a4aef9b3c7 adds whitelist for exchange collectors (#642)
adds enable flag for exchange collectors

Signed-off-by: Björn Fischer <bfischer@inovex.de>
2020-11-01 18:26:14 +01:00
Calle Pettersson
637fc246af Merge pull request #640 from fischerman/filter_collectors
Add URL filter for collectors
2020-11-01 13:38:54 +01:00
Björn Fischer
6b141a128c Add docs for filtering enabled collectors
Signed-off-by: Björn Fischer <bfischer@inovex.de>
2020-10-26 14:10:53 +01:00
Björn Fischer
e97a04ed65 Add URL filter for collectors
Signed-off-by: Björn Fischer <bfischer@inovex.de>
2020-10-26 14:10:53 +01:00
Ben Reedy
cdfe3cf258 Add Windows Time Service collector
Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-10-26 19:09:25 +10:00
Calle Pettersson
24fe6813b2 Merge pull request #632 from prometheus-community/fix-hyperv-panic
Fix panic in HyperV collector on input format mismatch
2020-10-26 09:01:37 +01:00
Ben Reedy
7eab1fc411 Set mssql transactions_active to Gauge.
Change also renames metric to avoid confusion.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2020-10-23 06:42:48 +10:00
Calle Pettersson
78918f7034 Merge pull request #633 from prometheus-community/maintainer-breed808
Update MAINTAINERS.md
2020-10-21 10:00:52 +02:00
Calle Pettersson
59e72c7016 Update MAINTAINERS.md
Add Ben Reedy
2020-10-21 08:49:17 +02:00
Calle Pettersson
49c082d594 Fix panic in HyperV collector on input format mismatch
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-10-19 18:02:51 +02:00
Calle Pettersson
b7b19aafa0 Merge pull request #630 from fpco/629-bump-go-version
Bump Go version from 1.13 to 1.15 for CI
2020-10-19 15:42:54 +02:00
Calle Pettersson
3624ea3bba Merge pull request #631 from dcrn/upgrade_wmi_lib
Upgrade WMI library
2020-10-19 15:01:01 +02:00
Michael Snoyman
898c17e657 Bump Go version from 1.13 to 1.15 for CI
Fixes #629, by including bugfix for
https://github.com/golang/go/issues/35447

Signed-off-by: Michael Snoyman <michael@snoyman.com>
2020-10-19 15:59:39 +03:00
Declan Curran
f9790f03fb Merge branch 'master' into upgrade_wmi_lib 2020-10-19 13:54:42 +01:00
Declan Curran
3708c85611 Updated wmi library as described in #446
Signed-off-by: Declan Curran <dcrn@users.noreply.github.com>
2020-10-19 13:53:36 +01:00
Calle Pettersson
7a5dc3c6f5 Merge pull request #615 from mallenLF/tcp-perflib
Convert the tcp collector to use perflib and support TCPv6 counters
2020-10-19 12:18:11 +02:00
Calle Pettersson
8f2f9d83f9 Merge pull request #623 from prometheus-community/remove-cs-metrics-from-memory-docs
Remove cs metrics from memory collector docs
2020-10-10 21:01:59 +02:00
Calle Pettersson
c5ea575fb1 Remove cs metrics from memory collector docs
Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-10-10 21:01:20 +02:00
Michael Allen
be39c1126a Document changes to the tcp collector
Note that TCPv6 metrics are now exported, and there is a new label, `af`.

Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-10-10 11:50:41 -07:00
Calle Pettersson
6765935d17 Merge pull request #563 from prometheus-community/set-versioninfo
Set Windows versioninfo on build
2020-10-10 10:44:06 +02:00
Calle Pettersson
51dd61beeb Set Windows versioninfo on build
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-10-10 10:33:48 +02:00
Calle Pettersson
a30422c31c Merge pull request #597 from prometheus-community/installer-phase
Change upgrade phase
2020-10-10 10:27:47 +02:00
Calle Pettersson
332a903757 Merge pull request #608 from siku4/add-firewall-remoteaddress-option-to-installer
Enable the use of remote ip addresses in Windows Firewall exception
2020-10-10 10:27:23 +02:00
Calle Pettersson
6e518f21bb Merge pull request #618 from ashumkin/readme-fix
Fix metrics description
2020-10-10 09:07:45 +02:00
Alexey Shumkin
3bf94cdaf6 Fix metrics description
`windows_mssql_locks_lock_timeouts` and
`windows_mssql_locks_lock_timeouts_excluding_NOWAIT` metrics have
exchanged descriptions.

According to
https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object
    ---
    Lock Timeouts     | Number of lock requests per second that
    (timeout > 0)/sec | timed out, but excluding requests for NOWAIT locks.
    ---
    Lock Timeouts/sec | Number of lock requests per second that timed
                      | out, including requests for NOWAIT locks.
    ---

Metrics gathered are correct but descriptions are exchanged.

Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
2020-10-09 14:16:06 +03:00
Michael Allen
94bda6aa79 Expose TCPv6 performance counters in the tcp collector
Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-10-08 11:43:39 -07:00
Michael Allen
380eff24c9 Convert the tcp collector to use perflib instead of WMI
Using perflib is substantially faster and more reliable than using WMI to
retrieve Windows performance counter data.

Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-10-07 22:25:58 -07:00
siku4
2ebea42de5 Enable the use of remote ip addresses for fw rule
Signed-off-by: siku4 <sk@sik-net.de>
2020-10-05 11:46:39 +02:00
Calle Pettersson
d39d5230ab Change upgrade phase
With afterInstallExecute, the old installation is only removed after the new one is finished, which has led to some users seeing the new version failing to start, leading to the install rolling back. afterInstallInitialize, in contrast, uninstalls before the new installation.

Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-09-12 16:38:41 +02:00
Calle Pettersson
922c08b85b Merge pull request #592 from mallenLF/mssql-perflib
Use perflib to gather metrics in the mssql collector
2020-09-07 09:21:27 +02:00
Michael Allen
a3867b8dbf Correct a typo where "perflib" was misspelled in a struct field tag
Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-09-06 18:26:02 -07:00
Michael Allen
3b2ef6287c Rename MSSQL metrics data structs for clarity
The old names were hard to read, but had to be named as such to work with
the WMI library. Now that raw performance counter data are used instead of
WMI, we are free to name the data structs freely.

Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-09-03 17:38:55 -07:00
Michael Allen
8d0d7b31b1 Add perflib annotations to struct win32PerfRawDataSqlServerTransactions
Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-08-31 23:32:09 -07:00
Michael Allen
24470eb17e Use perflib to gather metrics in the mssql collector
The perflib-based access code replaces WMI and is substantially more efficient
and stable, leading to fewer collection timeouts in the mssql collector.

Signed-off-by: Michael Allen <MAllen@laserfiche.com>
2020-08-31 21:52:15 -07:00
Calle Pettersson
6bcaee5885 Add flags to README 2020-07-10 13:52:24 +02:00
Calle Pettersson
ea557547dd Merge pull request #565 from eloekset/patch-1
Fix usage instructions
2020-07-06 13:24:00 +02:00
Eivind Gussiås Løkseth
3c90b96cc6 Fix usage instructions
Fixes #564
`promu build -v` is the correct command to build **windows_exporter** (no . as argument for local directory)

Signed-off-by: Eivind Gussiås Løkseth <eloekset@msn.com>
2020-07-06 10:20:27 +02:00
Calle Pettersson
a03f9ef01b Merge pull request #562 from clain23/patch-2
added dhcp help link
2020-07-03 21:01:51 +02:00
Igor Kudrin
391335a91f added dhcp help link
Signed-off-by: Igor Kudrin <kudrin@kudrin-macbook.local>
2020-07-03 20:27:14 +03:00
Calle Pettersson
6367863c43 Merge pull request #556 from JDA88/master
Add Hyper-V queries example
2020-06-28 13:10:54 +02:00
Calle Pettersson
5c7c0aaa69 Apply suggestions from code review
Signed-off-by: Calle Pettersson <calle@cape.nu>
2020-06-28 12:19:43 +02:00
Rasmus Hansen
51f1f884e7 Add hyperv queries example
Signed-off-by: D'ALMEIDA Jorge <67072186+JDA88@users.noreply.github.com>
2020-06-28 12:01:50 +02:00
Calle Pettersson
7d2511b7ab Merge pull request #554 from prometheus-community/repo_sync
Synchronize common files from prometheus/prometheus
2020-06-23 22:09:34 +02:00
Rasmus Hansen
f1384759cb Add endpoint for getting the version of the binary (#555)
* Add endpoint for getting the version of the binary

Fixes #553

Signed-off-by: Zlepper <hansen13579@gmail.com>
2020-06-23 12:48:19 +02:00
prombot
3316dc502d Update common Prometheus files
Signed-off-by: prombot <prometheus-team@googlegroups.com>
2020-06-23 00:12:11 +00:00
Calle Pettersson
c9f1e5068a Merge pull request #540 from prometheus-community/fix-fsrm-build-failure
Revert fsrm struct removal
2020-06-07 18:06:37 +02:00
Calle Pettersson
86dc495aeb Revert fsrm struct removal
Signed-off-by: Calle Pettersson <carlpett@users.noreply.github.com>
2020-06-07 17:58:14 +02:00
nwies
418b5b3ca9 Add Collector for Microsoft FileSystem Resource Manager Quotas (#437)
Add Collector for Microsoft FileSystem Resource Manager

Signed-off-by: nwies <nicolas.wies@gmail.com>
2020-06-07 17:40:55 +02:00
Calle Pettersson
f2d8418e9f Merge pull request #533 from breed808/dhcp_fix
Fix DHCP helptext
2020-06-07 15:43:26 +02:00
Calle Pettersson
0fbdfae85c Merge pull request #527 from paologallinaharbur/feat/ServiceStartName
feat (service): added support for service StartName
2020-06-07 15:43:10 +02:00
Ben Kochie
501ac3da4c Merge pull request #534 from prometheus-community/superq/maintainers
Update maintainers
2020-06-02 20:21:34 +02:00
paologallinaharbur
dd6bfbe963 fix: changed label name, added documentation
Signed-off-by: paologallinaharbur <paologallina1992@gmail.com>
2020-06-01 16:10:48 +02:00
paologallinaharbur
a4f815b5fd feat (service): added support for service StartName
Signed-off-by: paologallinaharbur <paologallina1992@gmail.com>
2020-06-01 16:10:48 +02:00
Ben Kochie
44d419e8fa Update maintainers
* Update filename.
* Add Brian Brazil as community steward.

Signed-off-by: Ben Kochie <superq@gmail.com>
2020-06-01 11:36:54 +02:00
Ben Reedy
cd8d676443 Fix DHCP helptext 2020-06-01 18:17:25 +10:00
140 changed files with 10507 additions and 3199 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @prometheus-community/windows_exporter-reviewers

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"

142
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,142 @@
name: windows_exporter CI/CD
# Trigger on pull requests and releases
# Deployments will only occur for releases (see `if` clauses in the build job).
on:
pull_request:
branches:
- master
release:
types:
- published
- edited
jobs:
test:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '^1.17.5'
- name: Test
run: make test
- name: Install e2e deps
run: |
go get github.com/prometheus/promu@v0.11.1
go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.2.0
# GOPATH\bin dir must be appended to PATH else the `promu` command won't be found
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: e2e Test
run: make e2e-test
lint:
runs-on: windows-2019
steps:
# `gofmt` linter run by golangci-lint fails on CRLF line endings (the default for Windows)
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '^1.17.5'
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.43
args: "--timeout=5m"
# golangci-lint action doesn't always provide helpful output, so re-run without the action for
# better output of the problem.
# The cache from the golangci-lint step is re-used here, so this step should finish quickly.
- name: errors
if: ${{ failure() }}
run: golangci-lint run --timeout=5m -c .golangci.yaml
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: codespell-project/actions-codespell@master
with:
check_filenames: true
# When using this Action in other repos, the --skip option below can be removed
skip: ./.git
ignore_words_list: calle
build:
runs-on: windows-2019
needs:
- test
- lint
- codespell
steps:
- uses: actions/checkout@v2
with:
# fetch-depth required for gitversion in `Build` step
fetch-depth: 0
- uses: actions/setup-go@v2
with:
go-version: '^1.17.5'
- name: Install Build deps
run: |
go get github.com/prometheus/promu@v0.11.1
go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.2.0
# GOPATH\bin dir must be added to PATH else the `promu` and `goversioninfo` commands won't be found
echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Build
run: |
$ErrorActionPreference = "Stop"
gitversion /output json /showvariable FullSemVer | Set-Content VERSION -PassThru
$Version = Get-Content VERSION
# Windows versioninfo resources need the file version by parts (but product version is free text)
$VersionParts = ($Version -replace '^v?([0-9\.]+).*$','$1').Split(".")
goversioninfo.exe -ver-major $VersionParts[0] -ver-minor $VersionParts[1] -ver-patch $VersionParts[2] -product-version $Version -platform-specific
make crossbuild
# GH requires all files to have different names, so add version/arch to differentiate
foreach($Arch in "amd64","386") {
Move-Item output\$Arch\windows_exporter.exe output\windows_exporter-$Version-$Arch.exe
}
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
name: windows_exporter_binaries
path: output\windows_exporter-*.exe
- name: Build Release Artifacts
if: startsWith(github.ref, 'refs/tags/')
run: |
$ErrorActionPreference = "Stop"
$BuildVersion = Get-Content VERSION
$TagName = $env:GITHUB_REF -replace 'refs/tags/', ''
# The MSI version is not semver compliant, so just take the numerical parts
$MSIVersion = $TagName -replace '^v?([0-9\.]+).*$','$1'
foreach($Arch in "amd64","386") {
Write-Verbose "Building windows_exporter $MSIVersion msi for $Arch"
.\installer\build.ps1 -PathToExecutable .\output\windows_exporter-$BuildVersion-$Arch.exe -Version $MSIVersion -Arch "$Arch"
Move-Item installer\Output\windows_exporter-$MSIVersion-$Arch.msi output\
}
promu checksum output\
- name: Release
if: startsWith(github.ref, 'refs/tags/')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
$TagName = $env:GITHUB_REF -replace 'refs/tags/', ''
Get-ChildItem -Path output\* -Include @('windows_exporter*.msi', 'windows_exporter*.exe', 'sha256sums.txt') | Foreach-Object {gh release upload $TagName $_}

3
.gitignore vendored
View File

@@ -4,4 +4,5 @@ VERSION
*.un~
output/
.vscode
.idea
.idea
*.syso

View File

@@ -3,11 +3,10 @@ linters:
enable:
- deadcode
- errcheck
- golint
- revive
- govet
- gofmt
- ineffassign
- interfacer
- structcheck
- unconvert
- varcheck
@@ -20,4 +19,7 @@ issues:
- # Golint has many capitalisation complaints on WMI class names
text: "`?\\w+`? should be `?\\w+`?"
linters:
- golint
- revive
- text: "don't use ALL_CAPS in Go names; use CamelCase"
linters:
- revive

View File

@@ -1,4 +0,0 @@
Contributors in alphabetical order
* [Martin Lindhe](https://github.com/martinlindhe)
* [Calle Pettersson](https://github.com/carlpett)

3
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,3 @@
## Prometheus Community Code of Conduct
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).

9
MAINTAINERS.md Normal file
View File

@@ -0,0 +1,9 @@
Maintainers in alphabetical order
* [Ben Reedy](https://github.com/breed808) - breed808@breed808.com
* [Calle Pettersson](https://github.com/carlpett) - calle@cape.nu
Alumni
* [Brian Brazil](https://github.com/brian-brazil)
* [Martin Lindhe](https://github.com/martinlindhe)

View File

@@ -1,14 +1,23 @@
export GOOS=windows
build:
.PHONY: build
build: windows_exporter.exe
windows_exporter.exe: **/*.go
promu build -v
test:
go test -v ./...
bench:
go test -v -bench='benchmark(cpu|logicaldisk|logon|memory|net|process|service|system|tcp|time)collector' ./...
lint:
golangci-lint -c .golangci.yaml run
.PHONY: e2e-test
e2e-test: windows_exporter.exe
pwsh -NonInteractive -ExecutionPolicy Bypass -File .\tools\end-to-end-test.ps1
fmt:
gofmt -l -w -s .

View File

@@ -1,6 +1,6 @@
# windows_exporter
[![Build status](https://ci.appveyor.com/api/projects/status/xoym3fftr7giasiw/branch/master?svg=true)](https://ci.appveyor.com/project/prometheus-community/windows-exporter)
![Build Status](https://github.com/prometheus-community/windows_exporter/workflows/windows_exporter%20CI/CD/badge.svg)
A Prometheus exporter for Windows machines.
@@ -10,12 +10,18 @@ A Prometheus exporter for Windows machines.
Name | Description | Enabled by default
---------|-------------|--------------------
[ad](docs/collector.ad.md) | Active Directory Domain Services |
[adcs](docs/collector.adcs.md) | Active Directory Certificate Services |
[adfs](docs/collector.adfs.md) | Active Directory Federation Services |
[cache](docs/collector.cache.md) | Cache metrics |
[cpu](docs/collector.cpu.md) | CPU usage | &#10003;
[cpu_info](docs/collector.cpu_info.md) | CPU Information |
[cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) | &#10003;
[container](docs/collector.container.md) | Container metrics |
[dfsr](docs/collector.dfsr.md) | DFSR metrics |
[dhcp](docs/collector.dhcp.md) | DHCP Server |
[dns](docs/collector.dns.md) | DNS Server |
[exchange](docs/collector.exchange.md) | Exchange metrics |
[fsrmquota](docs/collector.fsrmquota.md) | Microsoft File Server Resource Manager (FSRM) Quotas collector |
[hyperv](docs/collector.hyperv.md) | Hyper-V hosts |
[iis](docs/collector.iis.md) | IIS sites and applications |
[logical_disk](docs/collector.logical_disk.md) | Logical disks, disk I/O | &#10003;
@@ -36,8 +42,10 @@ Name | Description | Enabled by default
[process](docs/collector.process.md) | Per-process metrics |
[remote_fx](docs/collector.remote_fx.md) | RemoteFX protocol (RDP) metrics |
[service](docs/collector.service.md) | Service state metrics | &#10003;
[smtp](docs/collector.smtp.md) | IIS SMTP Server |
[system](docs/collector.system.md) | System calls | &#10003;
[tcp](docs/collector.tcp.md) | TCP connections |
[time](docs/collector.time.md) | Windows Time Service |
[thermalzone](docs/collector.thermalzone.md) | Thermal information
[terminal_services](docs/collector.terminal_services.md) | Terminal services (RDS)
[textfile](docs/collector.textfile.md) | Read prometheus metrics from a text file | &#10003;
@@ -45,6 +53,35 @@ Name | Description | Enabled by default
See the linked documentation on each collector for more information on reported metrics, configuration settings and usage examples.
### Filtering enabled collectors
The `windows_exporter` will expose all metrics from enabled collectors by default. This is the recommended way to collect metrics to avoid errors when comparing metrics of different families.
For advanced use the `windows_exporter` can be passed an optional list of collectors to filter metrics. The `collect[]` parameter may be used multiple times. In Prometheus configuration you can use this syntax under the [scrape config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#<scrape_config>).
```
params:
collect[]:
- foo
- bar
```
This can be useful for having different Prometheus servers collect specific metrics from nodes.
## Flags
windows_exporter accepts flags to configure certain behaviours. The ones configuring the global behaviour of the exporter are listed below, while collector-specific ones are documented in the respective collector documentation above.
Flag | Description | Default value
---------|-------------|--------------------
`--telemetry.addr` | host:port for exporter. | `:9182`
`--telemetry.path` | URL path for surfacing collected metrics. | `/metrics`
`--telemetry.max-requests` | Maximum number of concurrent requests. 0 to disable. | `5`
`--collectors.enabled` | Comma-separated list of collectors to use. Use `[defaults]` as a placeholder which gets expanded containing all the collectors enabled by default." | `[defaults]`
`--collectors.print` | If true, print available collectors and exit. |
`--scrape.timeout-margin` | Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads. | `0.5`
`--web.config.file` | A [web config][web_config] for setting up TLS and Auth | None
## Installation
The latest release can be downloaded from the [releases page](https://github.com/prometheus-community/windows_exporter/releases).
@@ -59,6 +96,7 @@ Name | Description
`LISTEN_PORT` | The port to bind to. Defaults to 9182.
`METRICS_PATH` | The path at which to serve metrics. Defaults to `/metrics`
`TEXTFILE_DIR` | As the `--collector.textfile.directory` flag, provide a directory to read text files with metrics from
`REMOTE_ADDR` | Allows setting comma separated remote IP addresses for the Windows Firewall exception (whitelist). Defaults to an empty string (any remote address).
`EXTRA_FLAGS` | Allows passing full CLI flags. Defaults to an empty string.
Parameters are sent to the installer via `msiexec`. Example invocations:
@@ -77,17 +115,16 @@ On some older versions of Windows you may need to surround parameter values with
msiexec /i C:\Users\Administrator\Downloads\windows_exporter.msi ENABLED_COLLECTORS="ad,iis,logon,memory,process,tcp,thermalzone" TEXTFILE_DIR="C:\custom_metrics\"
```
## Roadmap
See [open issues](https://github.com/prometheus-community/windows_exporter/issues)
## Supported versions
windows_exporter supports Windows Server versions 2008R2 and later, and desktop Windows version 7 and later.
## Usage
go get -u github.com/prometheus/promu
go get -u github.com/prometheus-community/windows_exporter
cd $env:GOPATH/src/github.com/prometheus-community/windows_exporter
promu build -v .
promu build -v
.\windows_exporter.exe
The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182)
@@ -104,7 +141,45 @@ The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182
When there are multiple processes with the same name, WMI represents those after the first instance as `process-name#index`. So to get them all, rather than just the first one, the [regular expression](https://en.wikipedia.org/wiki/Regular_expression) must use `.+`. See [process](docs/collector.process.md) for more information.
### Using [defaults] with `--collectors.enabled` argument
Using `[defaults]` with `--collectors.enabled` argument which gets expanded with all default collectors.
.\windows_exporter.exe --collectors.enabled "[defaults],process,container"
This enables the additional process and container collectors on top of the defaults.
### Using a configuration file
YAML configuration files can be specified with the `--config.file` flag. E.G. `.\windows_exporter.exe --config.file=config.yml`
```yaml
collectors:
enabled: cpu,cs,net,service
collector:
service:
services-where: "Name='windows_exporter'"
log:
level: warn
```
An example configuration file can be found [here](docs/example_config.yml).
#### Configuration file notes
Configuration file values can be mixed with CLI flags. E.G.
`.\windows_exporter.exe --collectors.enabled=cpu,logon`
```yaml
log:
level: debug
```
CLI flags enjoy a higher priority over values specified in the configuration file.
## License
Under [MIT](LICENSE)
[web_config]: https://github.com/prometheus/exporter-toolkit/blob/master/docs/web-configuration.md

6
SECURITY.md Normal file
View File

@@ -0,0 +1,6 @@
# Reporting a security issue
The Prometheus security policy, including how to report vulnerabilities, can be
found here:
https://prometheus.io/docs/operating/security/

View File

@@ -1,78 +0,0 @@
version: "{build}"
os: Visual Studio 2017
build: off
stack: go 1.13
environment:
GOPATH: c:\gopath
GO111MODULE: on
clone_folder: c:\gopath\src\github.com\prometheus-community\windows_exporter
install:
- mkdir %GOPATH%\bin
- set PATH=%GOPATH%\bin;%PATH%
- set PATH=%PATH%;C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin
- choco install gitversion.portable make -y
- ps: |
appveyor DownloadFile https://github.com/golangci/golangci-lint/releases/download/v1.21.0/golangci-lint-1.21.0-windows-amd64.zip
Expand-Archive golangci-lint-1.21.0-windows-amd64.zip
Move-Item golangci-lint-1.21.0-windows-amd64\golangci-lint-1.21.0-windows-amd64\golangci-lint.exe $env:GOPATH\bin\golangci-lint.exe
- ps: |
$env:GO111MODULE="off"
go get -u github.com/prometheus/promu
$env:GO111MODULE="on"
test_script:
- make test
after_test:
- make lint
build_script:
- ps: |
# go mod download (or, if we don't call it, go build) will write every dependent package name to
# stderr, which will be interpreted as an error and abort the build if ErrorActionPreference is Stop,
# so we need to run it before setting the preference.
go mod download
$ErrorActionPreference = "Stop"
gitversion /output json /showvariable FullSemVer | Set-Content VERSION -PassThru
$Version = Get-Content VERSION
make crossbuild
# GH requires all files to have different names, so add version/arch to differentiate
foreach($Arch in "amd64","386") {
Rename-Item output\$Arch\windows_exporter.exe -NewName windows_exporter-$Version-$Arch.exe
}
after_build:
- ps: |
# Build installer packages only on tagged releases
if($env:APPVEYOR_REPO_TAG -ne "True") {
return
}
$ErrorActionPreference = "Stop"
$BuildVersion = Get-Content VERSION
# The MSI version is not semver compliant, so just take the numerical parts
$MSIVersion = $env:APPVEYOR_REPO_TAG_NAME -replace '^v?([0-9\.]+).*$','$1'
foreach($Arch in "amd64","386") {
Write-Verbose "Building windows_exporter $MSIVersion msi for $Arch"
.\installer\build.ps1 -PathToExecutable .\output\$Arch\windows_exporter-$BuildVersion-$Arch.exe -Version $MSIVersion -Arch "$Arch"
Move-Item installer\Output\windows_exporter-$MSIVersion-$Arch.msi output\$Arch\
}
- promu checksum output\
artifacts:
- name: Artifacts
path: output\**\*
deploy:
- provider: GitHub
description: windows_exporter version $(appveyor_build_version)
artifact: Artifacts
auth_token:
secure: 'hFR7Ymxt/Rb25p4BweFvMNhX03lHD9kXJXrRlC/KbThazHuLD5NTx2ibMI6LYRsr'
draft: false
prerelease: false
on:
appveyor_repo_tag: true

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

9
collector/ad_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkADCollector(b *testing.B) {
benchmarkCollector(b, "ad", NewADCollector)
}

242
collector/adcs.go Normal file
View File

@@ -0,0 +1,242 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"strings"
)
func init() {
registerCollector("adcs", adcsCollectorMethod, "Certification Authority")
}
type adcsCollector struct {
RequestsPerSecond *prometheus.Desc
RequestProcessingTime *prometheus.Desc
RetrievalsPerSecond *prometheus.Desc
RetrievalProcessingTime *prometheus.Desc
FailedRequestsPerSecond *prometheus.Desc
IssuedRequestsPerSecond *prometheus.Desc
PendingRequestsPerSecond *prometheus.Desc
RequestCryptographicSigningTime *prometheus.Desc
RequestPolicyModuleProcessingTime *prometheus.Desc
ChallengeResponsesPerSecond *prometheus.Desc
ChallengeResponseProcessingTime *prometheus.Desc
SignedCertificateTimestampListsPerSecond *prometheus.Desc
SignedCertificateTimestampListProcessingTime *prometheus.Desc
}
// ADCSCollectorMethod ...
func adcsCollectorMethod() (Collector, error) {
const subsystem = "adcs"
return &adcsCollector{
RequestsPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "requests_total"),
"Total certificate requests processed",
[]string{"cert_template"},
nil,
),
RequestProcessingTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "request_processing_time_seconds"),
"Last time elapsed for certificate requests",
[]string{"cert_template"},
nil,
),
RetrievalsPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "retrievals_total"),
"Total certificate retrieval requests processed",
[]string{"cert_template"},
nil,
),
RetrievalProcessingTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "retrievals_processing_time_seconds"),
"Last time elapsed for certificate retrieval request",
[]string{"cert_template"},
nil,
),
FailedRequestsPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "failed_requests_total"),
"Total failed certificate requests processed",
[]string{"cert_template"},
nil,
),
IssuedRequestsPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "issued_requests_total"),
"Total issued certificate requests processed",
[]string{"cert_template"},
nil,
),
PendingRequestsPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "pending_requests_total"),
"Total pending certificate requests processed",
[]string{"cert_template"},
nil,
),
RequestCryptographicSigningTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "request_cryptographic_signing_time_seconds"),
"Last time elapsed for signing operation request",
[]string{"cert_template"},
nil,
),
RequestPolicyModuleProcessingTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "request_policy_module_processing_time_seconds"),
"Last time elapsed for policy module processing request",
[]string{"cert_template"},
nil,
),
ChallengeResponsesPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "challenge_responses_total"),
"Total certificate challenge responses processed",
[]string{"cert_template"},
nil,
),
ChallengeResponseProcessingTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "challenge_response_processing_time_seconds"),
"Last time elapsed for challenge response",
[]string{"cert_template"},
nil,
),
SignedCertificateTimestampListsPerSecond: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "signed_certificate_timestamp_lists_total"),
"Total Signed Certificate Timestamp Lists processed",
[]string{"cert_template"},
nil,
),
SignedCertificateTimestampListProcessingTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "signed_certificate_timestamp_list_processing_time_seconds"),
"Last time elapsed for Signed Certificate Timestamp List",
[]string{"cert_template"},
nil,
),
}, nil
}
func (c *adcsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collectADCSCounters(ctx, ch); err != nil {
log.Error("Failed collecting ADCS Metrics:", desc, err)
return err
}
return nil
}
type perflibADCS struct {
Name string
RequestsPerSecond float64 `perflib:"Requests/sec"`
RequestProcessingTime float64 `perflib:"Request processing time (ms)"`
RetrievalsPerSecond float64 `perflib:"Retrievals/sec"`
RetrievalProcessingTime float64 `perflib:"Retrieval processing time (ms)"`
FailedRequestsPerSecond float64 `perflib:"Failed Requests/sec"`
IssuedRequestsPerSecond float64 `perflib:"Issued Requests/sec"`
PendingRequestsPerSecond float64 `perflib:"Pending Requests/sec"`
RequestCryptographicSigningTime float64 `perflib:"Request cryptographic signing time (ms)"`
RequestPolicyModuleProcessingTime float64 `perflib:"Request policy module processing time (ms)"`
ChallengeResponsesPerSecond float64 `perflib:"Challenge Responses/sec"`
ChallengeResponseProcessingTime float64 `perflib:"Challenge Response processing time (ms)"`
SignedCertificateTimestampListsPerSecond float64 `perflib:"Signed Certificate Timestamp Lists/sec"`
SignedCertificateTimestampListProcessingTime float64 `perflib:"Signed Certificate Timestamp List processing time (ms)"`
}
func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
dst := make([]perflibADCS, 0)
if _, ok := ctx.perfObjects["Certification Authority"]; !ok {
return nil, errors.New("Perflib did not contain an entry for Certification Authority")
}
err := unmarshalObject(ctx.perfObjects["Certification Authority"], &dst)
if err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("Perflib query for Certification Authority (ADCS) returned empty result set")
}
for _, d := range dst {
n := strings.ToLower(d.Name)
if n == "" {
continue
}
ch <- prometheus.MustNewConstMetric(
c.RequestsPerSecond,
prometheus.CounterValue,
d.RequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RequestProcessingTime,
prometheus.GaugeValue,
milliSecToSec(d.RequestProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RetrievalsPerSecond,
prometheus.CounterValue,
d.RetrievalsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RetrievalProcessingTime,
prometheus.GaugeValue,
milliSecToSec(d.RetrievalProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FailedRequestsPerSecond,
prometheus.CounterValue,
d.FailedRequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.IssuedRequestsPerSecond,
prometheus.CounterValue,
d.IssuedRequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.PendingRequestsPerSecond,
prometheus.CounterValue,
d.PendingRequestsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RequestCryptographicSigningTime,
prometheus.GaugeValue,
milliSecToSec(d.RequestCryptographicSigningTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RequestPolicyModuleProcessingTime,
prometheus.GaugeValue,
milliSecToSec(d.RequestPolicyModuleProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ChallengeResponsesPerSecond,
prometheus.CounterValue,
d.ChallengeResponsesPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ChallengeResponseProcessingTime,
prometheus.GaugeValue,
milliSecToSec(d.ChallengeResponseProcessingTime),
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.SignedCertificateTimestampListsPerSecond,
prometheus.CounterValue,
d.SignedCertificateTimestampListsPerSecond,
d.Name,
)
ch <- prometheus.MustNewConstMetric(
c.SignedCertificateTimestampListProcessingTime,
prometheus.GaugeValue,
milliSecToSec(d.SignedCertificateTimestampListProcessingTime),
d.Name,
)
}
return nil, nil
}

9
collector/adcs_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkADCSCollector(b *testing.B) {
benchmarkCollector(b, "adcs", adcsCollectorMethod)
}

View File

@@ -1,9 +1,11 @@
//go:build windows
// +build windows
package collector
import (
"github.com/prometheus/client_golang/prometheus"
"math"
)
func init() {
@@ -11,17 +13,49 @@ func init() {
}
type adfsCollector struct {
adLoginConnectionFailures *prometheus.Desc
certificateAuthentications *prometheus.Desc
deviceAuthentications *prometheus.Desc
extranetAccountLockouts *prometheus.Desc
federatedAuthentications *prometheus.Desc
passportAuthentications *prometheus.Desc
passiveRequests *prometheus.Desc
passwordChangeFailed *prometheus.Desc
passwordChangeSucceeded *prometheus.Desc
tokenRequests *prometheus.Desc
windowsIntegratedAuthentications *prometheus.Desc
adLoginConnectionFailures *prometheus.Desc
certificateAuthentications *prometheus.Desc
deviceAuthentications *prometheus.Desc
extranetAccountLockouts *prometheus.Desc
federatedAuthentications *prometheus.Desc
passportAuthentications *prometheus.Desc
passiveRequests *prometheus.Desc
passwordChangeFailed *prometheus.Desc
passwordChangeSucceeded *prometheus.Desc
tokenRequests *prometheus.Desc
windowsIntegratedAuthentications *prometheus.Desc
oAuthAuthZRequests *prometheus.Desc
oAuthClientAuthentications *prometheus.Desc
oAuthClientAuthenticationsFailures *prometheus.Desc
oAuthClientCredentialsRequestFailures *prometheus.Desc
oAuthClientCredentialsRequests *prometheus.Desc
oAuthClientPrivateKeyJwtAuthenticationFailures *prometheus.Desc
oAuthClientPrivateKeyJwtAuthentications *prometheus.Desc
oAuthClientSecretBasicAuthenticationFailures *prometheus.Desc
oAuthClientSecretBasicAuthentications *prometheus.Desc
oAuthClientSecretPostAuthenticationFailures *prometheus.Desc
oAuthClientSecretPostAuthentications *prometheus.Desc
oAuthClientWindowsIntegratedAuthenticationFailures *prometheus.Desc
oAuthClientWindowsIntegratedAuthentications *prometheus.Desc
oAuthLogonCertificateRequestFailures *prometheus.Desc
oAuthLogonCertificateTokenRequests *prometheus.Desc
oAuthPasswordGrantRequestFailures *prometheus.Desc
oAuthPasswordGrantRequests *prometheus.Desc
oAuthTokenRequests *prometheus.Desc
samlPTokenRequests *prometheus.Desc
ssoAuthenticationFailures *prometheus.Desc
ssoAuthentications *prometheus.Desc
wsfedTokenRequests *prometheus.Desc
wstrustTokenRequests *prometheus.Desc
upAuthenticationFailures *prometheus.Desc
upAuthentications *prometheus.Desc
externalAuthenticationFailures *prometheus.Desc
externalAuthentications *prometheus.Desc
artifactDBFailures *prometheus.Desc
avgArtifactDBQueryTime *prometheus.Desc
configDBFailures *prometheus.Desc
avgConfigDBQueryTime *prometheus.Desc
federationMetadataRequests *prometheus.Desc
}
// newADFSCollector constructs a new adfsCollector
@@ -30,86 +64,310 @@ func newADFSCollector() (Collector, error) {
return &adfsCollector{
adLoginConnectionFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ad_login_connection_failures"),
prometheus.BuildFQName(Namespace, subsystem, "ad_login_connection_failures_total"),
"Total number of connection failures to an Active Directory domain controller",
nil,
nil,
),
certificateAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "certificate_authentications"),
prometheus.BuildFQName(Namespace, subsystem, "certificate_authentications_total"),
"Total number of User Certificate authentications",
nil,
nil,
),
deviceAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "device_authentications"),
prometheus.BuildFQName(Namespace, subsystem, "device_authentications_total"),
"Total number of Device authentications",
nil,
nil,
),
extranetAccountLockouts: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "extranet_account_lockouts"),
prometheus.BuildFQName(Namespace, subsystem, "extranet_account_lockouts_total"),
"Total number of Extranet Account Lockouts",
nil,
nil,
),
federatedAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "federated_authentications"),
prometheus.BuildFQName(Namespace, subsystem, "federated_authentications_total"),
"Total number of authentications from a federated source",
nil,
nil,
),
passportAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "passport_authentications"),
prometheus.BuildFQName(Namespace, subsystem, "passport_authentications_total"),
"Total number of Microsoft Passport SSO authentications",
nil,
nil,
),
passiveRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "passive_requests"),
prometheus.BuildFQName(Namespace, subsystem, "passive_requests_total"),
"Total number of passive (browser-based) requests",
nil,
nil,
),
passwordChangeFailed: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "password_change_failed"),
prometheus.BuildFQName(Namespace, subsystem, "password_change_failed_total"),
"Total number of failed password changes",
nil,
nil,
),
passwordChangeSucceeded: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "password_change_succeeded"),
prometheus.BuildFQName(Namespace, subsystem, "password_change_succeeded_total"),
"Total number of successful password changes",
nil,
nil,
),
tokenRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "token_requests"),
prometheus.BuildFQName(Namespace, subsystem, "token_requests_total"),
"Total number of token requests",
nil,
nil,
),
windowsIntegratedAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "windows_integrated_authentications"),
prometheus.BuildFQName(Namespace, subsystem, "windows_integrated_authentications_total"),
"Total number of Windows integrated authentications (Kerberos/NTLM)",
nil,
nil,
),
oAuthAuthZRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_authorization_requests_total"),
"Total number of incoming requests to the OAuth Authorization endpoint",
nil,
nil,
),
oAuthClientAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_authentication_success_total"),
"Total number of successful OAuth client Authentications",
nil,
nil,
),
oAuthClientAuthenticationsFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_authentication_failure_total"),
"Total number of failed OAuth client Authentications",
nil,
nil,
),
oAuthClientCredentialsRequestFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_credentials_failure_total"),
"Total number of failed OAuth Client Credentials Requests",
nil,
nil,
),
oAuthClientCredentialsRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_credentials_success_total"),
"Total number of successful RP tokens issued for OAuth Client Credentials Requests",
nil,
nil,
),
oAuthClientPrivateKeyJwtAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jtw_authentication_failure_total"),
"Total number of failed OAuth Client Private Key Jwt Authentications",
nil,
nil,
),
oAuthClientPrivateKeyJwtAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jwt_authentications_success_total"),
"Total number of successful OAuth Client Private Key Jwt Authentications",
nil,
nil,
),
oAuthClientSecretBasicAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_basic_authentications_failure_total"),
"Total number of failed OAuth Client Secret Basic Authentications",
nil,
nil,
),
oAuthClientSecretBasicAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_basic_authentications_success_total"),
"Total number of successful OAuth Client Secret Basic Authentications",
nil,
nil,
),
oAuthClientSecretPostAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_post_authentications_failure_total"),
"Total number of failed OAuth Client Secret Post Authentications",
nil,
nil,
),
oAuthClientSecretPostAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_post_authentications_success_total"),
"Total number of successful OAuth Client Secret Post Authentications",
nil,
nil,
),
oAuthClientWindowsIntegratedAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_windows_authentications_failure_total"),
"Total number of failed OAuth Client Windows Integrated Authentications",
nil,
nil,
),
oAuthClientWindowsIntegratedAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_client_windows_authentications_success_total"),
"Total number of successful OAuth Client Windows Integrated Authentications",
nil,
nil,
),
oAuthLogonCertificateRequestFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_logon_certificate_requests_failure_total"),
"Total number of failed OAuth Logon Certificate Requests",
nil,
nil,
),
oAuthLogonCertificateTokenRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_logon_certificate_token_requests_success_total"),
"Total number of successful RP tokens issued for OAuth Logon Certificate Requests",
nil,
nil,
),
oAuthPasswordGrantRequestFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_password_grant_requests_failure_total"),
"Total number of failed OAuth Password Grant Requests",
nil,
nil,
),
oAuthPasswordGrantRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_password_grant_requests_success_total"),
"Total number of successful OAuth Password Grant Requests",
nil,
nil,
),
oAuthTokenRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "oauth_token_requests_success_total"),
"Total number of successful RP tokens issued over OAuth protocol",
nil,
nil,
),
samlPTokenRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "samlp_token_requests_success_total"),
"Total number of successful RP tokens issued over SAML-P protocol",
nil,
nil,
),
ssoAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "sso_authentications_failure_total"),
"Total number of failed SSO authentications",
nil,
nil,
),
ssoAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "sso_authentications_success_total"),
"Total number of successful SSO authentications",
nil,
nil,
),
wsfedTokenRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "wsfed_token_requests_success_total"),
"Total number of successful RP tokens issued over WS-Fed protocol",
nil,
nil,
),
wstrustTokenRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "wstrust_token_requests_success_total"),
"Total number of successful RP tokens issued over WS-Trust protocol",
nil,
nil,
),
upAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "userpassword_authentications_failure_total"),
"Total number of failed AD U/P authentications",
nil,
nil,
),
upAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "userpassword_authentications_success_total"),
"Total number of successful AD U/P authentications",
nil,
nil,
),
externalAuthenticationFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "external_authentications_failure_total"),
"Total number of failed authentications from external MFA providers",
nil,
nil,
),
externalAuthentications: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "external_authentications_success_total"),
"Total number of successful authentications from external MFA providers",
nil,
nil,
),
artifactDBFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "db_artifact_failure_total"),
"Total number of failures connecting to the artifact database",
nil,
nil,
),
avgArtifactDBQueryTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "db_artifact_query_time_seconds_total"),
"Accumulator of time taken for an artifact database query",
nil,
nil,
),
configDBFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "db_config_failure_total"),
"Total number of failures connecting to the configuration database",
nil,
nil,
),
avgConfigDBQueryTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "db_config_query_time_seconds_total"),
"Accumulator of time taken for a configuration database query",
nil,
nil,
),
federationMetadataRequests: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "federation_metadata_requests_total"),
"Total number of Federation Metadata requests",
nil,
nil,
),
}, nil
}
type perflibADFS struct {
AdLoginConnectionFailures float64 `perflib:"AD login Connection Failures"`
CertificateAuthentications float64 `perflib:"Certificate Authentications"`
DeviceAuthentications float64 `perflib:"Device Authentications"`
ExtranetAccountLockouts float64 `perflib:"Extranet Account Lockouts"`
FederatedAuthentications float64 `perflib:"Federated Authentications"`
PassportAuthentications float64 `perflib:"Microsoft Passport Authentications"`
PassiveRequests float64 `perflib:"Passive Requests"`
PasswordChangeFailed float64 `perflib:"Password Change Failed Requests"`
PasswordChangeSucceeded float64 `perflib:"Password Change Successful Requests"`
TokenRequests float64 `perflib:"Token Requests"`
WindowsIntegratedAuthentications float64 `perflib:"Windows Integrated Authentications"`
AdLoginConnectionFailures float64 `perflib:"AD Login Connection Failures"`
CertificateAuthentications float64 `perflib:"Certificate Authentications"`
DeviceAuthentications float64 `perflib:"Device Authentications"`
ExtranetAccountLockouts float64 `perflib:"Extranet Account Lockouts"`
FederatedAuthentications float64 `perflib:"Federated Authentications"`
PassportAuthentications float64 `perflib:"Microsoft Passport Authentications"`
PassiveRequests float64 `perflib:"Passive Requests"`
PasswordChangeFailed float64 `perflib:"Password Change Failed Requests"`
PasswordChangeSucceeded float64 `perflib:"Password Change Successful Requests"`
TokenRequests float64 `perflib:"Token Requests"`
WindowsIntegratedAuthentications float64 `perflib:"Windows Integrated Authentications"`
OAuthAuthZRequests float64 `perflib:"OAuth AuthZ Requests"`
OAuthClientAuthentications float64 `perflib:"OAuth Client Authentications"`
OAuthClientAuthenticationFailures float64 `perflib:"OAuth Client Authentications Failures"`
OAuthClientCredentialRequestFailures float64 `perflib:"OAuth Client Credentials Request Failures"`
OAuthClientCredentialRequests float64 `perflib:"OAuth Client Credentials Requests"`
OAuthClientPrivKeyJWTAuthnFailures float64 `perflib:"OAuth Client Private Key Jwt Authentication Failures"`
OAuthClientPrivKeyJWTAuthentications float64 `perflib:"OAuth Client Private Key Jwt Authentications"`
OAuthClientBasicAuthnFailures float64 `perflib:"OAuth Client Secret Basic Authentication Failures"`
OAuthClientBasicAuthentications float64 `perflib:"OAuth Client Secret Basic Authentication Requests"`
OAuthClientSecretPostAuthnFailures float64 `perflib:"OAuth Client Secret Post Authentication Failures"`
OAuthClientSecretPostAuthentications float64 `perflib:"OAuth Client Secret Post Authentications"`
OAuthClientWindowsAuthnFailures float64 `perflib:"OAuth Client Windows Integrated Authentication Failures"`
OAuthClientWindowsAuthentications float64 `perflib:"OAuth Client Windows Integrated Authentications"`
OAuthLogonCertRequestFailures float64 `perflib:"OAuth Logon Certificate Request Failures"`
OAuthLogonCertTokenRequests float64 `perflib:"OAuth Logon Certificate Token Requests"`
OAuthPasswordGrantRequestFailures float64 `perflib:"OAuth Password Grant Request Failures"`
OAuthPasswordGrantRequests float64 `perflib:"OAuth Password Grant Requests"`
OAuthTokenRequests float64 `perflib:"OAuth Token Requests"`
SAMLPTokenRequests float64 `perflib:"SAML-P Token Requests"`
SSOAuthenticationFailures float64 `perflib:"SSO Authentication Failures"`
SSOAuthentications float64 `perflib:"SSO Authentications"`
WSFedTokenRequests float64 `perflib:"WS-Fed Token Requests"`
WSTrustTokenRequests float64 `perflib:"WS-Trust Token Requests"`
UsernamePasswordAuthnFailures float64 `perflib:"U/P Authentication Failures"`
UsernamePasswordAuthentications float64 `perflib:"U/P Authentications"`
ExternalAuthentications float64 `perflib:"External Authentications"`
ExternalAuthNFailures float64 `perflib:"External Authentication Failures"`
ArtifactDBFailures float64 `perflib:"Artifact Database Connection Failures"`
AvgArtifactDBQueryTime float64 `perflib:"Average Artifact Database Query Time"`
ConfigDBFailures float64 `perflib:"Configuration Database Connection Failures"`
AvgConfigDBQueryTime float64 `perflib:"Average Config Database Query Time"`
FederationMetadataRequests float64 `perflib:"Federation Metadata Requests"`
}
func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
@@ -184,5 +442,197 @@ func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
prometheus.CounterValue,
adfsData[0].WindowsIntegratedAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthAuthZRequests,
prometheus.CounterValue,
adfsData[0].OAuthAuthZRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientAuthenticationsFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientAuthenticationFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientCredentialsRequestFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientCredentialRequestFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientCredentialsRequests,
prometheus.CounterValue,
adfsData[0].OAuthClientCredentialRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientPrivateKeyJwtAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientPrivKeyJWTAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientPrivateKeyJwtAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientPrivKeyJWTAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretBasicAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientBasicAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretBasicAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientBasicAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretPostAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientSecretPostAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientSecretPostAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientSecretPostAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientWindowsIntegratedAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].OAuthClientWindowsAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthClientWindowsIntegratedAuthentications,
prometheus.CounterValue,
adfsData[0].OAuthClientWindowsAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthLogonCertificateRequestFailures,
prometheus.CounterValue,
adfsData[0].OAuthLogonCertRequestFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthLogonCertificateTokenRequests,
prometheus.CounterValue,
adfsData[0].OAuthLogonCertTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthPasswordGrantRequestFailures,
prometheus.CounterValue,
adfsData[0].OAuthPasswordGrantRequestFailures,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthPasswordGrantRequests,
prometheus.CounterValue,
adfsData[0].OAuthPasswordGrantRequests,
)
ch <- prometheus.MustNewConstMetric(
c.oAuthTokenRequests,
prometheus.CounterValue,
adfsData[0].OAuthTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.samlPTokenRequests,
prometheus.CounterValue,
adfsData[0].SAMLPTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.ssoAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].SSOAuthenticationFailures,
)
ch <- prometheus.MustNewConstMetric(
c.ssoAuthentications,
prometheus.CounterValue,
adfsData[0].SSOAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.wsfedTokenRequests,
prometheus.CounterValue,
adfsData[0].WSFedTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.wstrustTokenRequests,
prometheus.CounterValue,
adfsData[0].WSTrustTokenRequests,
)
ch <- prometheus.MustNewConstMetric(
c.upAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].UsernamePasswordAuthnFailures,
)
ch <- prometheus.MustNewConstMetric(
c.upAuthentications,
prometheus.CounterValue,
adfsData[0].UsernamePasswordAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.externalAuthenticationFailures,
prometheus.CounterValue,
adfsData[0].ExternalAuthNFailures,
)
ch <- prometheus.MustNewConstMetric(
c.externalAuthentications,
prometheus.CounterValue,
adfsData[0].ExternalAuthentications,
)
ch <- prometheus.MustNewConstMetric(
c.artifactDBFailures,
prometheus.CounterValue,
adfsData[0].ArtifactDBFailures,
)
ch <- prometheus.MustNewConstMetric(
c.avgArtifactDBQueryTime,
prometheus.CounterValue,
adfsData[0].AvgArtifactDBQueryTime*math.Pow(10, -8),
)
ch <- prometheus.MustNewConstMetric(
c.configDBFailures,
prometheus.CounterValue,
adfsData[0].ConfigDBFailures,
)
ch <- prometheus.MustNewConstMetric(
c.avgConfigDBQueryTime,
prometheus.CounterValue,
adfsData[0].AvgConfigDBQueryTime*math.Pow(10, -8),
)
ch <- prometheus.MustNewConstMetric(
c.federationMetadataRequests,
prometheus.CounterValue,
adfsData[0].FederationMetadataRequests,
)
return nil
}

9
collector/adfs_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkADFSCollector(b *testing.B) {
benchmarkCollector(b, "adfs", newADFSCollector)
}

453
collector/cache.go Normal file
View File

@@ -0,0 +1,453 @@
//go:build windows
// +build windows
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("cache", newCacheCollector, "Cache")
}
// A CacheCollector is a Prometheus collector for Perflib Cache metrics
type CacheCollector struct {
AsyncCopyReadsTotal *prometheus.Desc
AsyncDataMapsTotal *prometheus.Desc
AsyncFastReadsTotal *prometheus.Desc
AsyncMDLReadsTotal *prometheus.Desc
AsyncPinReadsTotal *prometheus.Desc
CopyReadHitsTotal *prometheus.Desc
CopyReadsTotal *prometheus.Desc
DataFlushesTotal *prometheus.Desc
DataFlushPagesTotal *prometheus.Desc
DataMapHitsPercent *prometheus.Desc
DataMapPinsTotal *prometheus.Desc
DataMapsTotal *prometheus.Desc
DirtyPages *prometheus.Desc
DirtyPageThreshold *prometheus.Desc
FastReadNotPossiblesTotal *prometheus.Desc
FastReadResourceMissesTotal *prometheus.Desc
FastReadsTotal *prometheus.Desc
LazyWriteFlushesTotal *prometheus.Desc
LazyWritePagesTotal *prometheus.Desc
MDLReadHitsTotal *prometheus.Desc
MDLReadsTotal *prometheus.Desc
PinReadHitsTotal *prometheus.Desc
PinReadsTotal *prometheus.Desc
ReadAheadsTotal *prometheus.Desc
SyncCopyReadsTotal *prometheus.Desc
SyncDataMapsTotal *prometheus.Desc
SyncFastReadsTotal *prometheus.Desc
SyncMDLReadsTotal *prometheus.Desc
SyncPinReadsTotal *prometheus.Desc
}
// NewCacheCollector ...
func newCacheCollector() (Collector, error) {
const subsystem = "cache"
return &CacheCollector{
AsyncCopyReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "async_copy_reads_total"),
"(AsyncCopyReadsTotal)",
nil,
nil,
),
AsyncDataMapsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "async_data_maps_total"),
"(AsyncDataMapsTotal)",
nil,
nil,
),
AsyncFastReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "async_fast_reads_total"),
"(AsyncFastReadsTotal)",
nil,
nil,
),
AsyncMDLReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "async_mdl_reads_total"),
"(AsyncMDLReadsTotal)",
nil,
nil,
),
AsyncPinReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "async_pin_reads_total"),
"(AsyncPinReadsTotal)",
nil,
nil,
),
CopyReadHitsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "copy_read_hits_total"),
"(CopyReadHitsTotal)",
nil,
nil,
),
CopyReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "copy_reads_total"),
"(CopyReadsTotal)",
nil,
nil,
),
DataFlushesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "data_flushes_total"),
"(DataFlushesTotal)",
nil,
nil,
),
DataFlushPagesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "data_flush_pages_total"),
"(DataFlushPagesTotal)",
nil,
nil,
),
DataMapHitsPercent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "data_map_hits_percent"),
"(DataMapHitsPercent)",
nil,
nil,
),
DataMapPinsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "data_map_pins_total"),
"(DataMapPinsTotal)",
nil,
nil,
),
DataMapsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "data_maps_total"),
"(DataMapsTotal)",
nil,
nil,
),
DirtyPages: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dirty_pages"),
"(DirtyPages)",
nil,
nil,
),
DirtyPageThreshold: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dirty_page_threshold"),
"(DirtyPageThreshold)",
nil,
nil,
),
FastReadNotPossiblesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "fast_read_not_possibles_total"),
"(FastReadNotPossiblesTotal)",
nil,
nil,
),
FastReadResourceMissesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "fast_read_resource_misses_total"),
"(FastReadResourceMissesTotal)",
nil,
nil,
),
FastReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "fast_reads_total"),
"(FastReadsTotal)",
nil,
nil,
),
LazyWriteFlushesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "lazy_write_flushes_total"),
"(LazyWriteFlushesTotal)",
nil,
nil,
),
LazyWritePagesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "lazy_write_pages_total"),
"(LazyWritePagesTotal)",
nil,
nil,
),
MDLReadHitsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mdl_read_hits_total"),
"(MDLReadHitsTotal)",
nil,
nil,
),
MDLReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mdl_reads_total"),
"(MDLReadsTotal)",
nil,
nil,
),
PinReadHitsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "pin_read_hits_total"),
"(PinReadHitsTotal)",
nil,
nil,
),
PinReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "pin_reads_total"),
"(PinReadsTotal)",
nil,
nil,
),
ReadAheadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_aheads_total"),
"(ReadAheadsTotal)",
nil,
nil,
),
SyncCopyReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "sync_copy_reads_total"),
"(SyncCopyReadsTotal)",
nil,
nil,
),
SyncDataMapsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "sync_data_maps_total"),
"(SyncDataMapsTotal)",
nil,
nil,
),
SyncFastReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "sync_fast_reads_total"),
"(SyncFastReadsTotal)",
nil,
nil,
),
SyncMDLReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "sync_mdl_reads_total"),
"(SyncMDLReadsTotal)",
nil,
nil,
),
SyncPinReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "sync_pin_reads_total"),
"(SyncPinReadsTotal)",
nil,
nil,
),
}, nil
}
// Collect implements the Collector interface
func (c *CacheCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting cache metrics:", desc, err)
return err
}
return nil
}
// Perflib "Cache":
// - https://docs.microsoft.com/en-us/previous-versions/aa394267(v=vs.85)
type perflibCache struct {
AsyncCopyReadsTotal float64 `perflib:"Async Copy Reads/sec"`
AsyncDataMapsTotal float64 `perflib:"Async Data Maps/sec"`
AsyncFastReadsTotal float64 `perflib:"Async Fast Reads/sec"`
AsyncMDLReadsTotal float64 `perflib:"Async MDL Reads/sec"`
AsyncPinReadsTotal float64 `perflib:"Async Pin Reads/sec"`
CopyReadHitsTotal float64 `perflib:"Copy Read Hits %"`
CopyReadsTotal float64 `perflib:"Copy Reads/sec"`
DataFlushesTotal float64 `perflib:"Data Flushes/sec"`
DataFlushPagesTotal float64 `perflib:"Data Flush Pages/sec"`
DataMapHitsPercent float64 `perflib:"Data Map Hits %"`
DataMapPinsTotal float64 `perflib:"Data Map Pins/sec"`
DataMapsTotal float64 `perflib:"Data Maps/sec"`
DirtyPages float64 `perflib:"Dirty Pages"`
DirtyPageThreshold float64 `perflib:"Dirty Page Threshold"`
FastReadNotPossiblesTotal float64 `perflib:"Fast Read Not Possibles/sec"`
FastReadResourceMissesTotal float64 `perflib:"Fast Read Resource Misses/sec"`
FastReadsTotal float64 `perflib:"Fast Reads/sec"`
LazyWriteFlushesTotal float64 `perflib:"Lazy Write Flushes/sec"`
LazyWritePagesTotal float64 `perflib:"Lazy Write Pages/sec"`
MDLReadHitsTotal float64 `perflib:"MDL Read Hits %"`
MDLReadsTotal float64 `perflib:"MDL Reads/sec"`
PinReadHitsTotal float64 `perflib:"Pin Read Hits %"`
PinReadsTotal float64 `perflib:"Pin Reads/sec"`
ReadAheadsTotal float64 `perflib:"Read Aheads/sec"`
SyncCopyReadsTotal float64 `perflib:"Sync Copy Reads/sec"`
SyncDataMapsTotal float64 `perflib:"Sync Data Maps/sec"`
SyncFastReadsTotal float64 `perflib:"Sync Fast Reads/sec"`
SyncMDLReadsTotal float64 `perflib:"Sync MDL Reads/sec"`
SyncPinReadsTotal float64 `perflib:"Sync Pin Reads/sec"`
}
func (c *CacheCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []perflibCache // Single-instance class, array is required but will have single entry.
if err := unmarshalObject(ctx.perfObjects["Cache"], &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.AsyncCopyReadsTotal,
prometheus.CounterValue,
dst[0].AsyncCopyReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.AsyncDataMapsTotal,
prometheus.CounterValue,
dst[0].AsyncDataMapsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.AsyncFastReadsTotal,
prometheus.CounterValue,
dst[0].AsyncFastReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.AsyncMDLReadsTotal,
prometheus.CounterValue,
dst[0].AsyncMDLReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.AsyncPinReadsTotal,
prometheus.CounterValue,
dst[0].AsyncPinReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.CopyReadHitsTotal,
prometheus.GaugeValue,
dst[0].CopyReadHitsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.CopyReadsTotal,
prometheus.CounterValue,
dst[0].CopyReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.DataFlushesTotal,
prometheus.CounterValue,
dst[0].DataFlushesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.DataFlushPagesTotal,
prometheus.CounterValue,
dst[0].DataFlushPagesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.DataMapHitsPercent,
prometheus.GaugeValue,
dst[0].DataMapHitsPercent,
)
ch <- prometheus.MustNewConstMetric(
c.DataMapPinsTotal,
prometheus.CounterValue,
dst[0].DataMapPinsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.DataMapsTotal,
prometheus.CounterValue,
dst[0].DataMapsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.DirtyPages,
prometheus.GaugeValue,
dst[0].DirtyPages,
)
ch <- prometheus.MustNewConstMetric(
c.DirtyPageThreshold,
prometheus.GaugeValue,
dst[0].DirtyPageThreshold,
)
ch <- prometheus.MustNewConstMetric(
c.FastReadNotPossiblesTotal,
prometheus.CounterValue,
dst[0].FastReadNotPossiblesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.FastReadResourceMissesTotal,
prometheus.CounterValue,
dst[0].FastReadResourceMissesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.FastReadsTotal,
prometheus.CounterValue,
dst[0].FastReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.LazyWriteFlushesTotal,
prometheus.CounterValue,
dst[0].LazyWriteFlushesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.LazyWritePagesTotal,
prometheus.CounterValue,
dst[0].LazyWritePagesTotal,
)
ch <- prometheus.MustNewConstMetric(
c.MDLReadHitsTotal,
prometheus.CounterValue,
dst[0].MDLReadHitsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.MDLReadsTotal,
prometheus.CounterValue,
dst[0].MDLReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.PinReadHitsTotal,
prometheus.CounterValue,
dst[0].PinReadHitsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.PinReadsTotal,
prometheus.CounterValue,
dst[0].PinReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.ReadAheadsTotal,
prometheus.CounterValue,
dst[0].ReadAheadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.SyncCopyReadsTotal,
prometheus.CounterValue,
dst[0].SyncCopyReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.SyncDataMapsTotal,
prometheus.CounterValue,
dst[0].SyncDataMapsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.SyncFastReadsTotal,
prometheus.CounterValue,
dst[0].SyncFastReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.SyncMDLReadsTotal,
prometheus.CounterValue,
dst[0].SyncMDLReadsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.SyncPinReadsTotal,
prometheus.CounterValue,
dst[0].SyncPinReadsTotal,
)
return nil, nil
}

View File

@@ -2,12 +2,13 @@ package collector
import (
"fmt"
"sort"
"strconv"
"strings"
"github.com/leoluk/perflib_exporter/perflib"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"golang.org/x/sys/windows/registry"
)
@@ -58,6 +59,10 @@ var (
func registerCollector(name string, builder collectorBuilder, perfCounterNames ...string) {
builders[name] = builder
addPerfCounterDependencies(name, perfCounterNames)
}
func addPerfCounterDependencies(name string, perfCounterNames []string) {
perfIndicies := make([]string, 0, len(perfCounterNames))
for _, cn := range perfCounterNames {
perfIndicies = append(perfIndicies, MapCounterToIndex(cn))
@@ -109,3 +114,41 @@ func PrepareScrapeContext(collectors []string) (*ScrapeContext, error) {
return &ScrapeContext{objs}, nil
}
func boolToFloat(b bool) float64 {
if b {
return 1.0
}
return 0.0
}
func find(slice []string, val string) bool {
for _, item := range slice {
if item == val {
return true
}
}
return false
}
// Used by more complex collectors where user input specifies enabled child collectors.
// Splits provided child collectors and deduplicate.
func expandEnabledChildCollectors(enabled string) []string {
separated := strings.Split(enabled, ",")
unique := map[string]bool{}
for _, s := range separated {
if s != "" {
unique[s] = true
}
}
result := make([]string, 0, len(unique))
for s := range unique {
result = append(result, s)
}
// Ensure result is ordered, to prevent test failure
sort.Strings(result)
return result
}
func milliSecToSec(t float64) float64 {
return t / 1000
}

View File

@@ -0,0 +1,60 @@
package collector
import (
"reflect"
"testing"
"github.com/prometheus/client_golang/prometheus"
)
func TestExpandChildCollectors(t *testing.T) {
cases := []struct {
name string
input string
expectedOutput []string
}{
{
name: "simple",
input: "testing1,testing2,testing3",
expectedOutput: []string{"testing1", "testing2", "testing3"},
},
{
name: "duplicate",
input: "testing1,testing2,testing2,testing3",
expectedOutput: []string{"testing1", "testing2", "testing3"},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
output := expandEnabledChildCollectors(c.input)
if !reflect.DeepEqual(output, c.expectedOutput) {
t.Errorf("Output mismatch, expected %+v, got %+v", c.expectedOutput, output)
}
})
}
}
func benchmarkCollector(b *testing.B, name string, collectFunc func() (Collector, error)) {
// Create perflib scrape context. Some perflib collectors required a correct context,
// or will fail during benchmark.
scrapeContext, err := PrepareScrapeContext([]string{name})
if err != nil {
b.Error(err)
}
c, err := collectFunc()
if err != nil {
b.Error(err)
}
metrics := make(chan prometheus.Metric)
go func() {
for {
<-metrics
}
}()
for i := 0; i < b.N; i++ {
c.Collect(scrapeContext, metrics) //nolint:errcheck
}
}

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/Microsoft/hcsshim"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
@@ -168,70 +169,67 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
}
for _, containerDetails := range containers {
containerId := containerDetails.ID
container, err := hcsshim.OpenContainer(containerId)
container, err := hcsshim.OpenContainer(containerDetails.ID)
if container != nil {
defer containerClose(container)
}
if err != nil {
log.Error("err in opening container: ", containerId, err)
log.Error("err in opening container: ", containerDetails.ID, err)
continue
}
cstats, err := container.Statistics()
if err != nil {
log.Error("err in fetching container Statistics: ", containerId, err)
log.Error("err in fetching container Statistics: ", containerDetails.ID, err)
continue
}
// HCS V1 is for docker runtime. Add the docker:// prefix on container_id
containerId = "docker://" + containerId
containerIdWithPrefix := getContainerIdWithPrefix(containerDetails)
ch <- prometheus.MustNewConstMetric(
c.ContainerAvailable,
prometheus.CounterValue,
1,
containerId,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.UsageCommitBytes,
prometheus.GaugeValue,
float64(cstats.Memory.UsageCommitBytes),
containerId,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.UsageCommitPeakBytes,
prometheus.GaugeValue,
float64(cstats.Memory.UsageCommitPeakBytes),
containerId,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.UsagePrivateWorkingSetBytes,
prometheus.GaugeValue,
float64(cstats.Memory.UsagePrivateWorkingSetBytes),
containerId,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.RuntimeTotal,
prometheus.CounterValue,
float64(cstats.Processor.TotalRuntime100ns)*ticksToSecondsScaleFactor,
containerId,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.RuntimeUser,
prometheus.CounterValue,
float64(cstats.Processor.RuntimeUser100ns)*ticksToSecondsScaleFactor,
containerId,
containerIdWithPrefix,
)
ch <- prometheus.MustNewConstMetric(
c.RuntimeKernel,
prometheus.CounterValue,
float64(cstats.Processor.RuntimeKernel100ns)*ticksToSecondsScaleFactor,
containerId,
containerIdWithPrefix,
)
if len(cstats.Network) == 0 {
log.Info("No Network Stats for container: ", containerId)
log.Info("No Network Stats for container: ", containerDetails.ID)
continue
}
@@ -242,37 +240,37 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
c.BytesReceived,
prometheus.CounterValue,
float64(networkInterface.BytesReceived),
containerId, networkInterface.EndpointId,
containerIdWithPrefix, networkInterface.EndpointId,
)
ch <- prometheus.MustNewConstMetric(
c.BytesSent,
prometheus.CounterValue,
float64(networkInterface.BytesSent),
containerId, networkInterface.EndpointId,
containerIdWithPrefix, networkInterface.EndpointId,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsReceived,
prometheus.CounterValue,
float64(networkInterface.PacketsReceived),
containerId, networkInterface.EndpointId,
containerIdWithPrefix, networkInterface.EndpointId,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsSent,
prometheus.CounterValue,
float64(networkInterface.PacketsSent),
containerId, networkInterface.EndpointId,
containerIdWithPrefix, networkInterface.EndpointId,
)
ch <- prometheus.MustNewConstMetric(
c.DroppedPacketsIncoming,
prometheus.CounterValue,
float64(networkInterface.DroppedPacketsIncoming),
containerId, networkInterface.EndpointId,
containerIdWithPrefix, networkInterface.EndpointId,
)
ch <- prometheus.MustNewConstMetric(
c.DroppedPacketsOutgoing,
prometheus.CounterValue,
float64(networkInterface.DroppedPacketsOutgoing),
containerId, networkInterface.EndpointId,
containerIdWithPrefix, networkInterface.EndpointId,
)
break
}
@@ -280,3 +278,13 @@ func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prome
return nil, nil
}
func getContainerIdWithPrefix(containerDetails hcsshim.ContainerProperties) string {
switch containerDetails.Owner {
case "containerd-shim-runhcs-v1.exe":
return "containerd://" + containerDetails.ID
default:
// default to docker or if owner is not set
return "docker://" + containerDetails.ID
}
}

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkContainerCollector(b *testing.B) {
benchmarkCollector(b, "container", NewContainerMetricsCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector

97
collector/cpu_info.go Normal file
View File

@@ -0,0 +1,97 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"strconv"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("cpu_info", newCpuInfoCollector)
}
// If you are adding additional labels to the metric, make sure that they get added in here as well. See below for explanation.
const (
win32ProcessorQuery = "SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name FROM Win32_Processor"
)
// A CpuInfoCollector is a Prometheus collector for a few WMI metrics in Win32_Processor
type CpuInfoCollector struct {
CpuInfo *prometheus.Desc
}
func newCpuInfoCollector() (Collector, error) {
return &CpuInfoCollector{
CpuInfo: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "", "cpu_info"),
"Labeled CPU information as provided provided by Win32_Processor",
[]string{
"architecture",
"device_id",
"description",
"family",
"l2_cache_size",
"l3_cache_size",
"name"},
nil,
),
}, nil
}
type win32_Processor struct {
Architecture uint32
DeviceID string
Description string
Family uint16
L2CacheSize uint32
L3CacheSize uint32
Name string
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *CpuInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting cpu_info metrics:", desc, err)
return err
}
return nil
}
func (c *CpuInfoCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []win32_Processor
// We use a static query here because the provided methods in wmi.go all issue a SELECT *;
// This results in the time consuming LoadPercentage field being read which seems to measure each CPU
// serially over a 1 second interval, so the scrape time is at least 1s * num_sockets
if err := wmi.Query(win32ProcessorQuery, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
// Some CPUs end up exposing trailing spaces for certain strings, so clean them up
for _, processor := range dst {
ch <- prometheus.MustNewConstMetric(
c.CpuInfo,
prometheus.GaugeValue,
1.0,
strconv.Itoa(int(processor.Architecture)),
strings.TrimRight(processor.DeviceID, " "),
strings.TrimRight(processor.Description, " "),
strconv.Itoa(int(processor.Family)),
strconv.Itoa(int(processor.L2CacheSize)),
strconv.Itoa(int(processor.L3CacheSize)),
strings.TrimRight(processor.Name, " "),
)
}
return nil, nil
}

9
collector/cpu_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkCPUCollector(b *testing.B) {
benchmarkCollector(b, "cpu", newCPUCollector)
}

View File

@@ -1,13 +1,13 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"github.com/prometheus-community/windows_exporter/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
@@ -60,51 +60,47 @@ func (c *CSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) e
return nil
}
// Win32_ComputerSystem docs:
// - https://msdn.microsoft.com/en-us/library/aa394102
type Win32_ComputerSystem struct {
NumberOfLogicalProcessors uint32
TotalPhysicalMemory uint64
DNSHostname string
Domain string
Workgroup *string
}
func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_ComputerSystem
q := queryAll(&dst)
if err := wmi.Query(q, &dst); err != nil {
// Get systeminfo for number of processors
systemInfo := sysinfoapi.GetSystemInfo()
// Get memory status for physical memory
mem, err := sysinfoapi.GlobalMemoryStatusEx()
if err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric(
c.LogicalProcessors,
prometheus.GaugeValue,
float64(dst[0].NumberOfLogicalProcessors),
float64(systemInfo.NumberOfProcessors),
)
ch <- prometheus.MustNewConstMetric(
c.PhysicalMemoryBytes,
prometheus.GaugeValue,
float64(dst[0].TotalPhysicalMemory),
float64(mem.TotalPhys),
)
var fqdn string
if dst[0].Workgroup == nil || dst[0].Domain != *dst[0].Workgroup {
fqdn = dst[0].DNSHostname + "." + dst[0].Domain
} else {
fqdn = dst[0].DNSHostname
hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname)
if err != nil {
return nil, err
}
domain, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSDomain)
if err != nil {
return nil, err
}
fqdn, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSFullyQualified)
if err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.Hostname,
prometheus.GaugeValue,
1.0,
dst[0].DNSHostname,
dst[0].Domain,
hostname,
domain,
fqdn,
)

9
collector/cs_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkCsCollector(b *testing.B) {
benchmarkCollector(b, "cs", NewCSCollector)
}

810
collector/dfsr.go Normal file
View File

@@ -0,0 +1,810 @@
//go:build windows
// +build windows
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
)
var dfsrEnabledCollectors = kingpin.Flag("collectors.dfsr.sources-enabled", "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String()
func init() {
// Perflib sources are dynamic, depending on the enabled child collectors
var perflibDependencies []string
for _, source := range expandEnabledChildCollectors(*dfsrEnabledCollectors) {
perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source))
}
registerCollector("dfsr", NewDFSRCollector, perflibDependencies...)
}
// DFSRCollector contains the metric and state data of the DFSR collectors.
type DFSRCollector struct {
// Connection source
ConnectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc
ConnectionBytesReceivedTotal *prometheus.Desc
ConnectionCompressedSizeOfFilesReceivedTotal *prometheus.Desc
ConnectionFilesReceivedTotal *prometheus.Desc
ConnectionRDCBytesReceivedTotal *prometheus.Desc
ConnectionRDCCompressedSizeOfFilesReceivedTotal *prometheus.Desc
ConnectionRDCSizeOfFilesReceivedTotal *prometheus.Desc
ConnectionRDCNumberofFilesReceivedTotal *prometheus.Desc
ConnectionSizeOfFilesReceivedTotal *prometheus.Desc
// Folder source
FolderBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc
FolderCompressedSizeOfFilesReceivedTotal *prometheus.Desc
FolderConflictBytesCleanedupTotal *prometheus.Desc
FolderConflictBytesGeneratedTotal *prometheus.Desc
FolderConflictFilesCleanedUpTotal *prometheus.Desc
FolderConflictFilesGeneratedTotal *prometheus.Desc
FolderConflictFolderCleanupsCompletedTotal *prometheus.Desc
FolderConflictSpaceInUse *prometheus.Desc
FolderDeletedSpaceInUse *prometheus.Desc
FolderDeletedBytesCleanedUpTotal *prometheus.Desc
FolderDeletedBytesGeneratedTotal *prometheus.Desc
FolderDeletedFilesCleanedUpTotal *prometheus.Desc
FolderDeletedFilesGeneratedTotal *prometheus.Desc
FolderFileInstallsRetriedTotal *prometheus.Desc
FolderFileInstallsSucceededTotal *prometheus.Desc
FolderFilesReceivedTotal *prometheus.Desc
FolderRDCBytesReceivedTotal *prometheus.Desc
FolderRDCCompressedSizeOfFilesReceivedTotal *prometheus.Desc
FolderRDCNumberofFilesReceivedTotal *prometheus.Desc
FolderRDCSizeOfFilesReceivedTotal *prometheus.Desc
FolderSizeOfFilesReceivedTotal *prometheus.Desc
FolderStagingSpaceInUse *prometheus.Desc
FolderStagingBytesCleanedUpTotal *prometheus.Desc
FolderStagingBytesGeneratedTotal *prometheus.Desc
FolderStagingFilesCleanedUpTotal *prometheus.Desc
FolderStagingFilesGeneratedTotal *prometheus.Desc
FolderUpdatesDroppedTotal *prometheus.Desc
// Volume source
VolumeDatabaseLookupsTotal *prometheus.Desc
VolumeDatabaseCommitsTotal *prometheus.Desc
VolumeUSNJournalUnreadPercentage *prometheus.Desc
VolumeUSNJournalRecordsAcceptedTotal *prometheus.Desc
VolumeUSNJournalRecordsReadTotal *prometheus.Desc
// Map of child collector functions used during collection
dfsrChildCollectors []dfsrCollectorFunc
}
type dfsrCollectorFunc func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error
// Map Perflib sources to DFSR collector names
// E.G. volume -> DFS Replication Service Volumes
func dfsrGetPerfObjectName(collector string) string {
prefix := "DFS "
suffix := ""
switch collector {
case "connection":
suffix = "Replication Connections"
case "folder":
suffix = "Replicated Folders"
case "volume":
suffix = "Replication Service Volumes"
}
return (prefix + suffix)
}
// NewDFSRCollector is registered
func NewDFSRCollector() (Collector, error) {
log.Info("dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
const subsystem = "dfsr"
enabled := expandEnabledChildCollectors(*dfsrEnabledCollectors)
perfCounters := make([]string, 0, len(enabled))
for _, c := range enabled {
perfCounters = append(perfCounters, dfsrGetPerfObjectName(c))
}
addPerfCounterDependencies(subsystem, perfCounters)
dfsrCollector := DFSRCollector{
// Connection
ConnectionBandwidthSavingsUsingDFSReplicationTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_bandwidth_savings_using_dfs_replication_bytes_total"),
"Total bytes of bandwidth saved using DFS Replication for this connection",
[]string{"name"},
nil,
),
ConnectionBytesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_bytes_received_total"),
"Total bytes received for connection",
[]string{"name"},
nil,
),
ConnectionCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_compressed_size_of_files_received_bytes_total"),
"Total compressed size of files received on the connection, in bytes",
[]string{"name"},
nil,
),
ConnectionFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_received_files_total"),
"Total number of files received for connection",
[]string{"name"},
nil,
),
ConnectionRDCBytesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_received_bytes_total"),
"Total bytes received on the connection while replicating files using Remote Differential Compression",
[]string{"name"},
nil,
),
ConnectionRDCCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_compressed_size_of_received_files_bytes_total"),
"Total uncompressed size of files received with Remote Differential Compression for connection",
[]string{"name"},
nil,
),
ConnectionRDCNumberofFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_received_files_total"),
"Total number of files received using remote differential compression",
[]string{"name"},
nil,
),
ConnectionRDCSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_size_of_received_files_bytes_total"),
"Total size of received Remote Differential Compression files, in bytes.",
[]string{"name"},
nil,
),
ConnectionSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_files_received_bytes_total"),
"Total size of files received, in bytes",
[]string{"name"},
nil,
),
// Folder
FolderBandwidthSavingsUsingDFSReplicationTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_bandwidth_savings_using_dfs_replication_bytes_total"),
"Total bytes of bandwidth saved using DFS Replication for this folder",
[]string{"name"},
nil,
),
FolderCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_compressed_size_of_received_files_bytes_total"),
"Total compressed size of files received on the folder, in bytes",
[]string{"name"},
nil,
),
FolderConflictBytesCleanedupTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_cleaned_up_bytes_total"),
"Total size of conflict loser files and folders deleted from the Conflict and Deleted folder, in bytes",
[]string{"name"},
nil,
),
FolderConflictBytesGeneratedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_generated_bytes_total"),
"Total size of conflict loser files and folders moved to the Conflict and Deleted folder, in bytes",
[]string{"name"},
nil,
),
FolderConflictFilesCleanedUpTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_cleaned_up_files_total"),
"Number of conflict loser files deleted from the Conflict and Deleted folder",
[]string{"name"},
nil,
),
FolderConflictFilesGeneratedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_generated_files_total"),
"Number of files and folders moved to the Conflict and Deleted folder",
[]string{"name"},
nil,
),
FolderConflictFolderCleanupsCompletedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_folder_cleanups_total"),
"Number of deletions of conflict loser files and folders in the Conflict and Deleted",
[]string{"name"},
nil,
),
FolderConflictSpaceInUse: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_space_in_use_bytes"),
"Total size of the conflict loser files and folders currently in the Conflict and Deleted folder",
[]string{"name"},
nil,
),
FolderDeletedSpaceInUse: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_space_in_use_bytes"),
"Total size (in bytes) of the deleted files and folders currently in the Conflict and Deleted folder",
[]string{"name"},
nil,
),
FolderDeletedBytesCleanedUpTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_cleaned_up_bytes_total"),
"Total size (in bytes) of replicating deleted files and folders that were cleaned up from the Conflict and Deleted folder",
[]string{"name"},
nil,
),
FolderDeletedBytesGeneratedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_generated_bytes_total"),
"Total size (in bytes) of replicated deleted files and folders that were moved to the Conflict and Deleted folder after they were deleted from a replicated folder on a sending member",
[]string{"name"},
nil,
),
FolderDeletedFilesCleanedUpTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_cleaned_up_files_total"),
"Number of files and folders that were cleaned up from the Conflict and Deleted folder",
[]string{"name"},
nil,
),
FolderDeletedFilesGeneratedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_generated_files_total"),
"Number of deleted files and folders that were moved to the Conflict and Deleted folder",
[]string{"name"},
nil,
),
FolderFileInstallsRetriedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_file_installs_retried_total"),
"Total number of file installs that are being retried due to sharing violations or other errors encountered when installing the files",
[]string{"name"},
nil,
),
FolderFileInstallsSucceededTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_file_installs_succeeded_total"),
"Total number of files that were successfully received from sending members and installed locally on this server",
[]string{"name"},
nil,
),
FolderFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_received_files_total"),
"Total number of files received",
[]string{"name"},
nil,
),
FolderRDCBytesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_received_bytes_total"),
"Total number of bytes received in replicating files using Remote Differential Compression",
[]string{"name"},
nil,
),
FolderRDCCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_compressed_size_of_received_files_bytes_total"),
"Total compressed size (in bytes) of the files received with Remote Differential Compression",
[]string{"name"},
nil,
),
FolderRDCNumberofFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_received_files_total"),
"Total number of files received with Remote Differential Compression",
[]string{"name"},
nil,
),
FolderRDCSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_files_received_bytes_total"),
"Total uncompressed size (in bytes) of the files received with Remote Differential Compression",
[]string{"name"},
nil,
),
FolderSizeOfFilesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_files_received_bytes_total"),
"Total uncompressed size (in bytes) of the files received",
[]string{"name"},
nil,
),
FolderStagingSpaceInUse: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_staging_space_in_use_bytes"),
"Total size of files and folders currently in the staging folder.",
[]string{"name"},
nil,
),
FolderStagingBytesCleanedUpTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_staging_cleaned_up_bytes_total"),
"Total size (in bytes) of the files and folders that have been cleaned up from the staging folder",
[]string{"name"},
nil,
),
FolderStagingBytesGeneratedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_staging_generated_bytes_total"),
"Total size (in bytes) of replicated files and folders in the staging folder created by the DFS Replication service since last restart",
[]string{"name"},
nil,
),
FolderStagingFilesCleanedUpTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_staging_cleaned_up_files_total"),
"Total number of files and folders that have been cleaned up from the staging folder",
[]string{"name"},
nil,
),
FolderStagingFilesGeneratedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_staging_generated_files_total"),
"Total number of times replicated files and folders have been staged by the DFS Replication service",
[]string{"name"},
nil,
),
FolderUpdatesDroppedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "folder_dropped_updates_total"),
"Total number of redundant file replication update records that have been ignored by the DFS Replication service because they did not change the replicated file or folder",
[]string{"name"},
nil,
),
// Volume
VolumeDatabaseCommitsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "volume_database_commits_total"),
"Total number of DFSR Volume database commits",
[]string{"name"},
nil,
),
VolumeDatabaseLookupsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "volume_database_lookups_total"),
"Total number of DFSR Volume database lookups",
[]string{"name"},
nil,
),
VolumeUSNJournalUnreadPercentage: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "volume_usn_journal_unread_percentage"),
"Percentage of DFSR Volume USN journal records that are unread",
[]string{"name"},
nil,
),
VolumeUSNJournalRecordsAcceptedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "volume_usn_journal_accepted_records_total"),
"Total number of USN journal records accepted",
[]string{"name"},
nil,
),
VolumeUSNJournalRecordsReadTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "volume_usn_journal_read_records_total"),
"Total number of DFSR Volume USN journal records read",
[]string{"name"},
nil,
),
}
dfsrCollector.dfsrChildCollectors = dfsrCollector.getDFSRChildCollectors(enabled)
return &dfsrCollector, nil
}
// Maps enabled child collectors names to their relevant collection function,
// for use in DFSRCollector.Collect()
func (c *DFSRCollector) getDFSRChildCollectors(enabledCollectors []string) []dfsrCollectorFunc {
var dfsrCollectors []dfsrCollectorFunc
for _, collector := range enabledCollectors {
switch collector {
case "connection":
dfsrCollectors = append(dfsrCollectors, c.collectConnection)
case "folder":
dfsrCollectors = append(dfsrCollectors, c.collectFolder)
case "volume":
dfsrCollectors = append(dfsrCollectors, c.collectVolume)
}
}
return dfsrCollectors
}
// Collect implements the Collector interface.
// Sends metric values for each metric to the provided prometheus Metric channel.
func (c *DFSRCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
for _, fn := range c.dfsrChildCollectors {
err := fn(ctx, ch)
if err != nil {
return err
}
}
return nil
}
// Perflib: "DFS Replication Service Connections"
type PerflibDFSRConnection struct {
Name string
BandwidthSavingsUsingDFSReplicationTotal float64 `perflib:"Bandwidth Savings Using DFS Replication"`
BytesReceivedTotal float64 `perflib:"Total Bytes Received"`
CompressedSizeOfFilesReceivedTotal float64 `perflib:"Compressed Size of Files Received"`
FilesReceivedTotal float64 `perflib:"Total Files Received"`
RDCBytesReceivedTotal float64 `perflib:"RDC Bytes Received"`
RDCCompressedSizeOfFilesReceivedTotal float64 `perflib:"RDC Compressed Size of Files Received"`
RDCNumberofFilesReceivedTotal float64 `perflib:"RDC Number of Files Received"`
RDCSizeOfFilesReceivedTotal float64 `perflib:"RDC Size of Files Received"`
SizeOfFilesReceivedTotal float64 `perflib:"Size of Files Received"`
}
func (c *DFSRCollector) collectConnection(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []PerflibDFSRConnection
if err := unmarshalObject(ctx.perfObjects["DFS Replication Connections"], &dst); err != nil {
return err
}
for _, connection := range dst {
ch <- prometheus.MustNewConstMetric(
c.ConnectionBandwidthSavingsUsingDFSReplicationTotal,
prometheus.CounterValue,
connection.BandwidthSavingsUsingDFSReplicationTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionBytesReceivedTotal,
prometheus.CounterValue,
connection.BytesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.CompressedSizeOfFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionFilesReceivedTotal,
prometheus.CounterValue,
connection.FilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionRDCBytesReceivedTotal,
prometheus.CounterValue,
connection.RDCBytesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionRDCCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.RDCCompressedSizeOfFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionRDCSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.RDCSizeOfFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionRDCNumberofFilesReceivedTotal,
prometheus.CounterValue,
connection.RDCNumberofFilesReceivedTotal,
connection.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionSizeOfFilesReceivedTotal,
prometheus.CounterValue,
connection.SizeOfFilesReceivedTotal,
connection.Name,
)
}
return nil
}
// Perflib: "DFS Replicated Folder"
type PerflibDFSRFolder struct {
Name string
BandwidthSavingsUsingDFSReplicationTotal float64 `perflib:"Bandwidth Savings Using DFS Replication"`
CompressedSizeOfFilesReceivedTotal float64 `perflib:"Compressed Size of Files Received"`
ConflictBytesCleanedupTotal float64 `perflib:"Conflict Bytes Cleaned Up"`
ConflictBytesGeneratedTotal float64 `perflib:"Conflict Bytes Generated"`
ConflictFilesCleanedUpTotal float64 `perflib:"Conflict Files Cleaned Up"`
ConflictFilesGeneratedTotal float64 `perflib:"Conflict Files Generated"`
ConflictFolderCleanupsCompletedTotal float64 `perflib:"Conflict Folder Cleanups Completed"`
ConflictSpaceInUse float64 `perflib:"Conflict Space In Use"`
DeletedSpaceInUse float64 `perflib:"Deleted Space In Use"`
DeletedBytesCleanedUpTotal float64 `perflib:"Deleted Bytes Cleaned Up"`
DeletedBytesGeneratedTotal float64 `perflib:"Deleted Bytes Generated"`
DeletedFilesCleanedUpTotal float64 `perflib:"Deleted Files Cleaned Up"`
DeletedFilesGeneratedTotal float64 `perflib:"Deleted Files Generated"`
FileInstallsRetriedTotal float64 `perflib:"File Installs Retried"`
FileInstallsSucceededTotal float64 `perflib:"File Installs Succeeded"`
FilesReceivedTotal float64 `perflib:"Total Files Received"`
RDCBytesReceivedTotal float64 `perflib:"RDC Bytes Received"`
RDCCompressedSizeOfFilesReceivedTotal float64 `perflib:"RDC Compressed Size of Files Received"`
RDCNumberofFilesReceivedTotal float64 `perflib:"RDC Number of Files Received"`
RDCSizeOfFilesReceivedTotal float64 `perflib:"RDC Size of Files Received"`
SizeOfFilesReceivedTotal float64 `perflib:"Size of Files Received"`
StagingSpaceInUse float64 `perflib:"Staging Space In Use"`
StagingBytesCleanedUpTotal float64 `perflib:"Staging Bytes Cleaned Up"`
StagingBytesGeneratedTotal float64 `perflib:"Staging Bytes Generated"`
StagingFilesCleanedUpTotal float64 `perflib:"Staging Files Cleaned Up"`
StagingFilesGeneratedTotal float64 `perflib:"Staging Files Generated"`
UpdatesDroppedTotal float64 `perflib:"Updates Dropped"`
}
func (c *DFSRCollector) collectFolder(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []PerflibDFSRFolder
if err := unmarshalObject(ctx.perfObjects["DFS Replicated Folders"], &dst); err != nil {
return err
}
for _, folder := range dst {
ch <- prometheus.MustNewConstMetric(
c.FolderBandwidthSavingsUsingDFSReplicationTotal,
prometheus.CounterValue,
folder.BandwidthSavingsUsingDFSReplicationTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.CompressedSizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderConflictBytesCleanedupTotal,
prometheus.CounterValue,
folder.ConflictBytesCleanedupTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderConflictBytesGeneratedTotal,
prometheus.CounterValue,
folder.ConflictBytesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderConflictFilesCleanedUpTotal,
prometheus.CounterValue,
folder.ConflictFilesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderConflictFilesGeneratedTotal,
prometheus.CounterValue,
folder.ConflictFilesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderConflictFolderCleanupsCompletedTotal,
prometheus.CounterValue,
folder.ConflictFolderCleanupsCompletedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderConflictSpaceInUse,
prometheus.GaugeValue,
folder.ConflictSpaceInUse,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderDeletedSpaceInUse,
prometheus.GaugeValue,
folder.DeletedSpaceInUse,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderDeletedBytesCleanedUpTotal,
prometheus.CounterValue,
folder.DeletedBytesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderDeletedBytesGeneratedTotal,
prometheus.CounterValue,
folder.DeletedBytesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderDeletedFilesCleanedUpTotal,
prometheus.CounterValue,
folder.DeletedFilesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderDeletedFilesGeneratedTotal,
prometheus.CounterValue,
folder.DeletedFilesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderFileInstallsRetriedTotal,
prometheus.CounterValue,
folder.FileInstallsRetriedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderFileInstallsSucceededTotal,
prometheus.CounterValue,
folder.FileInstallsSucceededTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderFilesReceivedTotal,
prometheus.CounterValue,
folder.FilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderRDCBytesReceivedTotal,
prometheus.CounterValue,
folder.RDCBytesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderRDCCompressedSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.RDCCompressedSizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderRDCNumberofFilesReceivedTotal,
prometheus.CounterValue,
folder.RDCNumberofFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderRDCSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.RDCSizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderSizeOfFilesReceivedTotal,
prometheus.CounterValue,
folder.SizeOfFilesReceivedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderStagingSpaceInUse,
prometheus.GaugeValue,
folder.StagingSpaceInUse,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderStagingBytesCleanedUpTotal,
prometheus.CounterValue,
folder.StagingBytesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderStagingBytesGeneratedTotal,
prometheus.CounterValue,
folder.StagingBytesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderStagingFilesCleanedUpTotal,
prometheus.CounterValue,
folder.StagingFilesCleanedUpTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderStagingFilesGeneratedTotal,
prometheus.CounterValue,
folder.StagingFilesGeneratedTotal,
folder.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FolderUpdatesDroppedTotal,
prometheus.CounterValue,
folder.UpdatesDroppedTotal,
folder.Name,
)
}
return nil
}
// Perflib: "DFS Replication Service Volumes"
type PerflibDFSRVolume struct {
Name string
DatabaseCommitsTotal float64 `perflib:"Database Commits"`
DatabaseLookupsTotal float64 `perflib:"Database Lookups"`
USNJournalRecordsReadTotal float64 `perflib:"USN Journal Records Read"`
USNJournalRecordsAcceptedTotal float64 `perflib:"USN Journal Records Accepted"`
USNJournalUnreadPercentage float64 `perflib:"USN Journal Records Unread Percentage"`
}
func (c *DFSRCollector) collectVolume(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
var dst []PerflibDFSRVolume
if err := unmarshalObject(ctx.perfObjects["DFS Replication Service Volumes"], &dst); err != nil {
return err
}
for _, volume := range dst {
ch <- prometheus.MustNewConstMetric(
c.VolumeDatabaseLookupsTotal,
prometheus.CounterValue,
volume.DatabaseLookupsTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VolumeDatabaseCommitsTotal,
prometheus.CounterValue,
volume.DatabaseCommitsTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VolumeUSNJournalRecordsAcceptedTotal,
prometheus.CounterValue,
volume.USNJournalRecordsAcceptedTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VolumeUSNJournalRecordsReadTotal,
prometheus.CounterValue,
volume.USNJournalRecordsReadTotal,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VolumeUSNJournalUnreadPercentage,
prometheus.GaugeValue,
volume.USNJournalUnreadPercentage,
volume.Name,
)
}
return nil
}

9
collector/dfsr_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkDFSRCollector(b *testing.B) {
benchmarkCollector(b, "dfsr", NewDFSRCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -134,7 +135,7 @@ func NewDhcpCollector() (Collector, error) {
nil,
),
DeniedDueToNonMatch: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_match_total"),
prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_nonmatch_total"),
"Total number of DHCP requests denied, based on non-matches from the Allow list (DeniedDueToNonMatch)",
nil,
nil,

9
collector/dhcp_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkDHCPCollector(b *testing.B) {
benchmarkCollector(b, "dhcp", NewDhcpCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
@@ -81,8 +82,8 @@ func NewDNSCollector() (Collector, error) {
nil,
),
MemoryUsedBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "memory_used_bytes_total"),
"Total memory used by DNS server",
prometheus.BuildFQName(Namespace, subsystem, "memory_used_bytes"),
"Current memory used by DNS server",
[]string{"area"},
nil,
),
@@ -136,7 +137,7 @@ func NewDNSCollector() (Collector, error) {
),
Responses: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "responses_total"),
"Number of reponses sent by DNS server",
"Number of responses sent by DNS server",
[]string{"protocol"},
nil,
),

9
collector/dns_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkDNSCollector(b *testing.B) {
benchmarkCollector(b, "dns", NewDNSCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -7,8 +8,8 @@ import (
"os"
"strings"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"gopkg.in/alecthomas/kingpin.v2"
)
@@ -65,7 +66,7 @@ type exchangeCollector struct {
RPCOperationsPerSec *prometheus.Desc
UserCount *prometheus.Desc
ActiveCollFuncs []func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error
enabledCollectors []string
}
var (
@@ -86,6 +87,11 @@ var (
"collectors.exchange.list",
"List the collectors along with their perflib object name/ids",
).Bool()
argExchangeCollectorsEnabled = kingpin.Flag(
"collectors.exchange.enabled",
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
).Default("").String()
)
// newExchangeCollector returns a new Collector
@@ -139,6 +145,8 @@ func newExchangeCollector() (Collector, error) {
MailboxServerProxyFailureRate: desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name"),
PingCommandsPending: desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue"),
SyncCommandsPerSec: desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder"),
enabledCollectors: make([]string, 0, len(exchangeAllCollectorNames)),
}
collectorDesc := map[string]string{
@@ -161,12 +169,27 @@ func newExchangeCollector() (Collector, error) {
os.Exit(0)
}
if *argExchangeCollectorsEnabled == "" {
for _, collectorName := range exchangeAllCollectorNames {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
}
} else {
for _, collectorName := range strings.Split(*argExchangeCollectorsEnabled, ",") {
if find(exchangeAllCollectorNames, collectorName) {
c.enabledCollectors = append(c.enabledCollectors, collectorName)
} else {
return nil, fmt.Errorf("Unknown exchange collector: %s", collectorName)
}
}
}
return &c, nil
}
// Collect collects exchange metrics and sends them to prometheus
func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
for collectorName, collectorFunc := range map[string]func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error{
collectorFuncs := map[string]func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error{
"ADAccessProcesses": c.collectADAccessProcesses,
"TransportQueues": c.collectTransportQueues,
"HttpProxy": c.collectHTTPProxy,
@@ -176,8 +199,10 @@ func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Met
"Autodiscover": c.collectAutoDiscover,
"WorkloadManagement": c.collectWorkloadManagementWorkloads,
"RpcClientAccess": c.collectRPC,
} {
if err := collectorFunc(ctx, ch); err != nil {
}
for _, collectorName := range c.enabledCollectors {
if err := collectorFuncs[collectorName](ctx, ch); err != nil {
log.Errorf("Error in %s: %s", collectorName, err)
return err
}
@@ -210,7 +235,7 @@ func (c *exchangeCollector) collectADAccessProcesses(ctx *ScrapeContext, ch chan
}
// since we're not including the PID suffix from the instance names in the label names,
// we get an occational duplicate. This seems to affect about 4 instances only on this object.
// we get an occasional duplicate. This seems to affect about 4 instances only on this object.
labelUseCount[labelName]++
if labelUseCount[labelName] > 1 {
labelName = fmt.Sprintf("%s_%d", labelName, labelUseCount[labelName])

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkExchangeCollector(b *testing.B) {
benchmarkCollector(b, "exchange", newExchangeCollector)
}

187
collector/fsrmquota.go Normal file
View File

@@ -0,0 +1,187 @@
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("fsrmquota", newFSRMQuotaCollector)
}
type FSRMQuotaCollector struct {
QuotasCount *prometheus.Desc
Path *prometheus.Desc
PeakUsage *prometheus.Desc
Size *prometheus.Desc
Usage *prometheus.Desc
Description *prometheus.Desc
Disabled *prometheus.Desc
MatchesTemplate *prometheus.Desc
SoftLimit *prometheus.Desc
Template *prometheus.Desc
}
func newFSRMQuotaCollector() (Collector, error) {
const subsystem = "fsrmquota"
return &FSRMQuotaCollector{
QuotasCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "count"),
"Number of Quotas",
nil,
nil,
),
PeakUsage: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "peak_usage_bytes"),
"The highest amount of disk space usage charged to this quota. (PeakUsage)",
[]string{"path", "template"},
nil,
),
Size: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "size_bytes"),
"The size of the quota. (Size)",
[]string{"path", "template"},
nil,
),
Usage: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "usage_bytes"),
"The current amount of disk space usage charged to this quota. (Usage)",
[]string{"path", "template"},
nil,
),
Description: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "description"),
"Description of the quota (Description)",
[]string{"path", "template", "description"},
nil,
),
Disabled: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "disabled"),
"If 1, the quota is disabled. The default value is 0. (Disabled)",
[]string{"path", "template"},
nil,
),
SoftLimit: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "softlimit"),
"If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)",
[]string{"path", "template"},
nil,
),
Template: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "template"),
"Quota template name. (Template)",
[]string{"path", "template"},
nil,
),
MatchesTemplate: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "matchestemplate"),
"If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)",
[]string{"path", "template"},
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *FSRMQuotaCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting fsrmquota metrics:", desc, err)
return err
}
return nil
}
// MSFT_FSRMQuota docs:
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
type MSFT_FSRMQuota struct {
Name string
Path string
PeakUsage uint64
Size uint64
Usage uint64
Description string
Template string
//Threshold string
Disabled bool
MatchesTemplate bool
SoftLimit bool
}
func (c *FSRMQuotaCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []MSFT_FSRMQuota
q := queryAll(&dst)
var count int
if err := wmi.QueryNamespace(q, &dst, "root/microsoft/windows/fsrm"); err != nil {
return nil, err
}
for _, quota := range dst {
count++
path := quota.Path
template := quota.Template
Description := quota.Description
ch <- prometheus.MustNewConstMetric(
c.PeakUsage,
prometheus.GaugeValue,
float64(quota.PeakUsage),
path,
template,
)
ch <- prometheus.MustNewConstMetric(
c.Size,
prometheus.GaugeValue,
float64(quota.Size),
path,
template,
)
ch <- prometheus.MustNewConstMetric(
c.Usage,
prometheus.GaugeValue,
float64(quota.Usage),
path,
template,
)
ch <- prometheus.MustNewConstMetric(
c.Description,
prometheus.GaugeValue,
1.0,
path, template, Description,
)
ch <- prometheus.MustNewConstMetric(
c.Disabled,
prometheus.GaugeValue,
boolToFloat(quota.Disabled),
path,
template,
)
ch <- prometheus.MustNewConstMetric(
c.MatchesTemplate,
prometheus.GaugeValue,
boolToFloat(quota.MatchesTemplate),
path,
template,
)
ch <- prometheus.MustNewConstMetric(
c.SoftLimit,
prometheus.GaugeValue,
boolToFloat(quota.SoftLimit),
path,
template,
)
}
ch <- prometheus.MustNewConstMetric(
c.QuotasCount,
prometheus.GaugeValue,
float64(count),
)
return nil, nil
}

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkFsrmQuotaCollector(b *testing.B) {
benchmarkCollector(b, "fsrmquota", newFSRMQuotaCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
@@ -1001,8 +1002,17 @@ func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prome
}
// The name format is <VM Name>:Hv VP <vcore id>
parts := strings.Split(obj.Name, ":")
if len(parts) != 2 {
log.Warnf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, "<VM Name>:Hv VP <vcore id>")
continue
}
coreParts := strings.Split(parts[1], " ")
if len(coreParts) != 3 {
log.Warnf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP <vcore id>")
continue
}
vmName := parts[0]
coreId := strings.Split(parts[1], " ")[2]
coreId := coreParts[2]
ch <- prometheus.MustNewConstMetric(
c.VMGuestRunTime,

9
collector/hyperv_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkHypervCollector(b *testing.B) {
benchmarkCollector(b, "hyperv", NewHyperVCollector)
}

File diff suppressed because it is too large Load Diff

9
collector/iis_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkIISCollector(b *testing.B) {
benchmarkCollector(b, "iis", NewIISCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"fmt"
"regexp"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"gopkg.in/alecthomas/kingpin.v2"
)
@@ -103,14 +104,14 @@ func NewLogicalDiskCollector() (Collector, error) {
FreeSpace: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "free_bytes"),
"Free space in bytes (LogicalDisk.PercentFreeSpace)",
"Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)",
[]string{"volume"},
nil,
),
TotalSpace: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "size_bytes"),
"Total space in bytes (LogicalDisk.PercentFreeSpace_Base)",
"Total space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)",
[]string{"volume"},
nil,
),

View File

@@ -0,0 +1,13 @@
package collector
import (
"testing"
)
func BenchmarkLogicalDiskCollector(b *testing.B) {
// Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all disks.
localVolumeWhitelist := ".+"
volumeWhitelist = &localVolumeWhitelist
benchmarkCollector(b, "logical_disk", NewLogicalDiskCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

10
collector/logon_test.go Normal file
View File

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

View File

@@ -1,13 +1,14 @@
// returns data points from Win32_PerfRawData_PerfOS_Memory
// <add link to documentation here> - Win32_PerfRawData_PerfOS_Memory class
//go:build windows
// +build windows
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

9
collector/memory_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkMemoryCollector(b *testing.B) {
benchmarkCollector(b, "memory", NewMemoryCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"gopkg.in/alecthomas/kingpin.v2"
)
@@ -93,29 +94,27 @@ func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) collect(ch chan<- prometheus
}
for _, msmq := range dst {
if msmq.Name == "Computer Queues" {
continue
}
ch <- prometheus.MustNewConstMetric(
c.BytesinJournalQueue,
prometheus.GaugeValue,
float64(msmq.BytesinJournalQueue),
strings.ToLower(msmq.Name),
)
ch <- prometheus.MustNewConstMetric(
c.BytesinQueue,
prometheus.GaugeValue,
float64(msmq.BytesinQueue),
strings.ToLower(msmq.Name),
)
ch <- prometheus.MustNewConstMetric(
c.MessagesinJournalQueue,
prometheus.GaugeValue,
float64(msmq.MessagesinJournalQueue),
strings.ToLower(msmq.Name),
)
ch <- prometheus.MustNewConstMetric(
c.MessagesinQueue,
prometheus.GaugeValue,

10
collector/msmq_test.go Normal file
View File

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

File diff suppressed because it is too large Load Diff

9
collector/mssql_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkMSSQLCollector(b *testing.B) {
benchmarkCollector(b, "mssql", NewMSSQLCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"fmt"
"regexp"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"gopkg.in/alecthomas/kingpin.v2"
)
@@ -70,25 +71,25 @@ func NewNetworkCollector() (Collector, error) {
nil,
),
PacketsOutboundDiscarded: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded"),
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded_total"),
"(Network.PacketsOutboundDiscarded)",
[]string{"nic"},
nil,
),
PacketsOutboundErrors: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_errors"),
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_errors_total"),
"(Network.PacketsOutboundErrors)",
[]string{"nic"},
nil,
),
PacketsReceivedDiscarded: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_discarded"),
prometheus.BuildFQName(Namespace, subsystem, "packets_received_discarded_total"),
"(Network.PacketsReceivedDiscarded)",
[]string{"nic"},
nil,
),
PacketsReceivedErrors: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_errors"),
prometheus.BuildFQName(Namespace, subsystem, "packets_received_errors_total"),
"(Network.PacketsReceivedErrors)",
[]string{"nic"},
nil,
@@ -100,7 +101,7 @@ func NewNetworkCollector() (Collector, error) {
nil,
),
PacketsReceivedUnknown: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_unknown"),
prometheus.BuildFQName(Namespace, subsystem, "packets_received_unknown_total"),
"(Network.PacketsReceivedUnknown)",
[]string{"nic"},
nil,
@@ -118,7 +119,7 @@ func NewNetworkCollector() (Collector, error) {
nil,
),
CurrentBandwidth: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "current_bandwidth"),
prometheus.BuildFQName(Namespace, subsystem, "current_bandwidth_bytes"),
"(Network.CurrentBandwidth)",
[]string{"nic"},
nil,
@@ -251,7 +252,7 @@ func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
ch <- prometheus.MustNewConstMetric(
c.CurrentBandwidth,
prometheus.GaugeValue,
nic.CurrentBandwidth,
nic.CurrentBandwidth/8,
name,
)
}

View File

@@ -1,8 +1,11 @@
//go:build windows
// +build windows
package collector
import "testing"
import (
"testing"
)
func TestNetworkToInstanceName(t *testing.T) {
data := map[string]string{
@@ -15,3 +18,10 @@ func TestNetworkToInstanceName(t *testing.T) {
}
}
}
func BenchmarkNetCollector(b *testing.B) {
// Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces.
localNicWhitelist := ".+"
nicWhitelist = &localNicWhitelist
benchmarkCollector(b, "net", NewNetworkCollector)
}

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,11 +1,12 @@
//go:build windows
// +build windows
package collector
import (
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

View File

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

View File

@@ -1,18 +1,24 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"fmt"
"os"
"strings"
"time"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/headers/netapi32"
"github.com/prometheus-community/windows_exporter/headers/psapi"
"github.com/prometheus-community/windows_exporter/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"golang.org/x/sys/windows/registry"
)
func init() {
registerCollector("os", NewOSCollector)
registerCollector("os", NewOSCollector, "Paging File")
}
// A OSCollector is a Prometheus collector for WMI metrics
@@ -32,6 +38,12 @@ type OSCollector struct {
Timezone *prometheus.Desc
}
type pagingFileCounter struct {
Name string
Usage float64 `perflib:"% Usage"`
UsagePeak float64 `perflib:"% Usage Peak"`
}
// NewOSCollector ...
func NewOSCollector() (Collector, error) {
const subsystem = "os"
@@ -86,7 +98,7 @@ func NewOSCollector() (Collector, error) {
nil,
),
ProcessMemoryLimitBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "process_memory_limix_bytes"),
prometheus.BuildFQName(Namespace, subsystem, "process_memory_limit_bytes"),
"OperatingSystem.MaxProcessMemorySize",
nil,
nil,
@@ -121,7 +133,7 @@ func NewOSCollector() (Collector, error) {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *OSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting os metrics:", desc, err)
return err
}
@@ -146,41 +158,102 @@ type Win32_OperatingSystem struct {
Version string
}
func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_OperatingSystem
q := queryAll(&dst)
if err := wmi.Query(q, &dst); err != nil {
func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
nwgi, err := netapi32.GetWorkstationInfo()
if err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
gmse, err := sysinfoapi.GlobalMemoryStatusEx()
if err != nil {
return nil, err
}
currentTime := time.Now()
timezoneName, _ := currentTime.Zone()
// Get total allocation of paging files across all disks.
memManKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management`, registry.QUERY_VALUE)
defer memManKey.Close()
if err != nil {
return nil, err
}
pagingFiles, _, err := memManKey.GetStringsValue("ExistingPageFiles")
if err != nil {
return nil, err
}
// Get build number and product name from registry
ntKey, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
defer ntKey.Close()
if err != nil {
return nil, err
}
pn, _, err := ntKey.GetStringValue("ProductName")
if err != nil {
return nil, err
}
bn, _, err := ntKey.GetStringValue("CurrentBuildNumber")
if err != nil {
return nil, err
}
var fsipf float64
for _, pagingFile := range pagingFiles {
fileString := strings.ReplaceAll(pagingFile, `\??\`, "")
file, err := os.Stat(fileString)
if err != nil {
return nil, err
}
fsipf += float64(file.Size())
}
gpi, err := psapi.GetPerformanceInfo()
if err != nil {
return nil, err
}
var pfc = make([]pagingFileCounter, 0)
if err := unmarshalObject(ctx.perfObjects["Paging File"], &pfc); err != nil {
return nil, err
}
// Get current page file usage.
var pfbRaw float64
for _, pageFile := range pfc {
if strings.Contains(strings.ToLower(pageFile.Name), "_total") {
continue
}
pfbRaw += pageFile.Usage
}
// Subtract from total page file allocation on disk.
pfb := fsipf - (pfbRaw * float64(gpi.PageSize))
ch <- prometheus.MustNewConstMetric(
c.OSInformation,
prometheus.GaugeValue,
1.0,
dst[0].Caption,
dst[0].Version,
fmt.Sprintf("Microsoft %s", pn), // Caption
fmt.Sprintf("%d.%d.%s", nwgi.VersionMajor, nwgi.VersionMinor, bn), // Version
)
ch <- prometheus.MustNewConstMetric(
c.PhysicalMemoryFreeBytes,
prometheus.GaugeValue,
float64(dst[0].FreePhysicalMemory*1024), // KiB -> bytes
float64(gmse.AvailPhys),
)
time := dst[0].LocalDateTime
ch <- prometheus.MustNewConstMetric(
c.Time,
prometheus.GaugeValue,
float64(time.Unix()),
float64(currentTime.Unix()),
)
timezoneName, _ := time.Zone()
ch <- prometheus.MustNewConstMetric(
c.Timezone,
prometheus.GaugeValue,
@@ -191,55 +264,58 @@ func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
ch <- prometheus.MustNewConstMetric(
c.PagingFreeBytes,
prometheus.GaugeValue,
float64(dst[0].FreeSpaceInPagingFiles*1024), // KiB -> bytes
pfb,
)
ch <- prometheus.MustNewConstMetric(
c.VirtualMemoryFreeBytes,
prometheus.GaugeValue,
float64(dst[0].FreeVirtualMemory*1024), // KiB -> bytes
float64(gmse.AvailPageFile),
)
// Windows has no defined limit, and is based off available resources. This currently isn't calculated by WMI and is set to default value.
// https://techcommunity.microsoft.com/t5/windows-blog-archive/pushing-the-limits-of-windows-processes-and-threads/ba-p/723824
// https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem
ch <- prometheus.MustNewConstMetric(
c.ProcessesLimit,
prometheus.GaugeValue,
float64(dst[0].MaxNumberOfProcesses),
float64(4294967295),
)
ch <- prometheus.MustNewConstMetric(
c.ProcessMemoryLimitBytes,
prometheus.GaugeValue,
float64(dst[0].MaxProcessMemorySize*1024), // KiB -> bytes
float64(gmse.TotalVirtual),
)
ch <- prometheus.MustNewConstMetric(
c.Processes,
prometheus.GaugeValue,
float64(dst[0].NumberOfProcesses),
float64(gpi.ProcessCount),
)
ch <- prometheus.MustNewConstMetric(
c.Users,
prometheus.GaugeValue,
float64(dst[0].NumberOfUsers),
float64(nwgi.LoggedOnUsers),
)
ch <- prometheus.MustNewConstMetric(
c.PagingLimitBytes,
prometheus.GaugeValue,
float64(dst[0].SizeStoredInPagingFiles*1024), // KiB -> bytes
fsipf,
)
ch <- prometheus.MustNewConstMetric(
c.VirtualMemoryBytes,
prometheus.GaugeValue,
float64(dst[0].TotalVirtualMemorySize*1024), // KiB -> bytes
float64(gmse.TotalPageFile),
)
ch <- prometheus.MustNewConstMetric(
c.VisibleMemoryBytes,
prometheus.GaugeValue,
float64(dst[0].TotalVisibleMemorySize*1024), // KiB -> bytes
float64(gmse.TotalPhys),
)
return nil, nil

9
collector/os_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkOSCollector(b *testing.B) {
benchmarkCollector(b, "os", NewOSCollector)
}

View File

@@ -7,7 +7,7 @@ import (
perflibCollector "github.com/leoluk/perflib_exporter/collector"
"github.com/leoluk/perflib_exporter/perflib"
"github.com/prometheus/common/log"
"github.com/prometheus-community/windows_exporter/log"
)
var nametable = perflib.QueryNameTable("Counter 009") // Reads the names in English TODO: validate that the English names are always present

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -9,8 +10,8 @@ import (
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"gopkg.in/alecthomas/kingpin.v2"
)
@@ -42,6 +43,8 @@ type processCollector struct {
PrivateBytes *prometheus.Desc
ThreadCount *prometheus.Desc
VirtualBytes *prometheus.Desc
WorkingSetPrivate *prometheus.Desc
WorkingSetPeak *prometheus.Desc
WorkingSet *prometheus.Desc
processWhitelistPattern *regexp.Regexp
@@ -65,43 +68,43 @@ func newProcessCollector() (Collector, error) {
),
CPUTimeTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cpu_time_total"),
"Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user). An instruction is the basic unit of execution in a computer, a thread is the object that executes instructions, and a process is the object created when a program is run. Code executed to handle some hardware interrupts and trap conditions is included in this count.",
"Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user).",
[]string{"process", "process_id", "creating_process_id", "mode"},
nil,
),
HandleCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "handle_count"),
prometheus.BuildFQName(Namespace, subsystem, "handles"),
"Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
IOBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "io_bytes_total"),
"Bytes issued to I/O operations in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ",
"Bytes issued to I/O operations in different modes (read, write, other).",
[]string{"process", "process_id", "creating_process_id", "mode"},
nil,
),
IOOperationsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "io_operations_total"),
"I/O operations issued in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ",
"I/O operations issued in different modes (read, write, other).",
[]string{"process", "process_id", "creating_process_id", "mode"},
nil,
),
PageFaultsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"),
"Page faults by the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. This can cause the page not to be fetched from disk if it is on the standby list and hence already in main memory, or if it is in use by another process with which the page is shared.",
"Page faults by the threads executing in this process.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
PageFileBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes"),
"Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.",
"Current number of bytes this process has used in the paging file(s).",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
PoolBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "pool_bytes"),
"Pool Bytes is the last observed number of bytes in the paged or nonpaged pool. The nonpaged pool is an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. The paged pool is an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. Nonpaged pool bytes is calculated differently than paged pool bytes, so it might not equal the total of paged pool bytes.",
"Pool Bytes is the last observed number of bytes in the paged or nonpaged pool.",
[]string{"process", "process_id", "creating_process_id", "pool"},
nil,
),
@@ -118,20 +121,32 @@ func newProcessCollector() (Collector, error) {
nil,
),
ThreadCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "thread_count"),
"Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.",
prometheus.BuildFQName(Namespace, subsystem, "threads"),
"Number of threads currently active in this process.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
VirtualBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"),
"Current size, in bytes, of the virtual address space that the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.",
"Current size, in bytes, of the virtual address space that the process is using.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
WorkingSetPrivate: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "working_set_private_bytes"),
"Size of the working set, in bytes, that is use for this process only and not shared nor shareable by other processes.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
WorkingSetPeak: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "working_set_peak_bytes"),
"Maximum size, in bytes, of the Working Set of this process at any point in time. The Working Set is the set of memory pages touched recently by the threads in the process.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
WorkingSet: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "working_set"),
"Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.",
prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes"),
"Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
@@ -380,6 +395,24 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.WorkingSetPrivate,
prometheus.GaugeValue,
process.WorkingSetPrivate,
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.WorkingSetPeak,
prometheus.GaugeValue,
process.WorkingSetPeak,
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.WorkingSet,
prometheus.GaugeValue,

14
collector/process_test.go Normal file
View File

@@ -0,0 +1,14 @@
package collector
import (
"testing"
)
func BenchmarkProcessCollector(b *testing.B) {
// Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all processes.
localProcessWhitelist := ".+"
processWhitelist = &localProcessWhitelist
// No context name required as collector source is WMI
benchmarkCollector(b, "", newProcessCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -5,8 +6,8 @@ package collector
import (
"strings"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
@@ -60,7 +61,7 @@ func NewRemoteFx() (Collector, error) {
),
CurrentTCPBandwidth: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_bandwidth"),
"TCP Bandwidth detected in bytes per seccond.",
"TCP Bandwidth detected in bytes per second.",
[]string{"session_name"},
nil,
),
@@ -345,7 +346,3 @@ func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext,
return nil, nil
}
func milliSecToSec(t float64) float64 {
return t / 1000
}

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkRemoteFXCollector(b *testing.B) {
benchmarkCollector(b, "remote_fx", NewRemoteFx)
}

View File

@@ -1,14 +1,17 @@
//go:build windows
// +build windows
package collector
import (
"strconv"
"fmt"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc/mgr"
"gopkg.in/alecthomas/kingpin.v2"
)
@@ -21,6 +24,10 @@ var (
"collector.service.services-where",
"WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.",
).Default("").String()
useAPI = kingpin.Flag(
"collector.service.use-api",
"Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.",
).Default("false").Bool()
)
// A serviceCollector is a Prometheus collector for WMI Win32_Service metrics
@@ -40,12 +47,15 @@ func NewserviceCollector() (Collector, error) {
if *serviceWhereClause == "" {
log.Warn("No where-clause specified for service collector. This will generate a very large number of metrics!")
}
if *useAPI {
log.Warn("API collection is enabled.")
}
return &serviceCollector{
Information: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "info"),
"A metric with a constant '1' value labeled with service information",
[]string{"name", "display_name", "process_id"},
[]string{"name", "display_name", "process_id", "run_as"},
nil,
),
State: prometheus.NewDesc(
@@ -73,9 +83,16 @@ func NewserviceCollector() (Collector, error) {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *serviceCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Error("failed collecting service metrics:", desc, err)
return err
if *useAPI {
if err := c.collectAPI(ch); err != nil {
log.Error("failed collecting API service metrics:", err)
return err
}
} else {
if err := c.collectWMI(ch); err != nil {
log.Error("failed collecting WMI service metrics:", err)
return err
}
}
return nil
}
@@ -89,6 +106,7 @@ type Win32_Service struct {
State string
Status string
StartMode string
StartName *string
}
var (
@@ -102,6 +120,15 @@ var (
"paused",
"unknown",
}
apiStateValues = map[uint]string{
windows.SERVICE_CONTINUE_PENDING: "continue pending",
windows.SERVICE_PAUSE_PENDING: "pause pending",
windows.SERVICE_PAUSED: "paused",
windows.SERVICE_RUNNING: "running",
windows.SERVICE_START_PENDING: "start pending",
windows.SERVICE_STOP_PENDING: "stop pending",
windows.SERVICE_STOPPED: "stopped",
}
allStartModes = []string{
"boot",
"system",
@@ -109,6 +136,13 @@ var (
"manual",
"disabled",
}
apiStartModeValues = map[uint32]string{
windows.SERVICE_AUTO_START: "auto",
windows.SERVICE_BOOT_START: "boot",
windows.SERVICE_DEMAND_START: "manual",
windows.SERVICE_DISABLED: "disabled",
windows.SERVICE_SYSTEM_START: "system",
}
allStatuses = []string{
"ok",
"error",
@@ -125,15 +159,19 @@ var (
}
)
func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
func (c *serviceCollector) collectWMI(ch chan<- prometheus.Metric) error {
var dst []Win32_Service
q := queryAllWhere(&dst, c.queryWhereClause)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
return err
}
for _, service := range dst {
pid := strconv.FormatUint(uint64(service.ProcessId), 10)
pid := fmt.Sprintf("%d", uint64(service.ProcessId))
runAs := ""
if service.StartName != nil {
runAs = *service.StartName
}
ch <- prometheus.MustNewConstMetric(
c.Information,
prometheus.GaugeValue,
@@ -141,6 +179,7 @@ func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Des
strings.ToLower(service.Name),
service.DisplayName,
pid,
runAs,
)
for _, state := range allStates {
@@ -185,5 +224,82 @@ func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Des
)
}
}
return nil, nil
return nil
}
func (c *serviceCollector) collectAPI(ch chan<- prometheus.Metric) error {
svcmgrConnection, err := mgr.Connect()
if err != nil {
return err
}
defer svcmgrConnection.Disconnect() //nolint:errcheck
// List All Services from the Services Manager
serviceList, err := svcmgrConnection.ListServices()
if err != nil {
return err
}
// Iterate through the Services List
for _, service := range serviceList {
// Retrieve handle for each service
serviceHandle, err := svcmgrConnection.OpenService(service)
if err != nil {
continue
}
defer serviceHandle.Close()
// Get Service Configuration
serviceConfig, err := serviceHandle.Config()
if err != nil {
continue
}
// Get Service Current Status
serviceStatus, err := serviceHandle.Query()
if err != nil {
continue
}
pid := fmt.Sprintf("%d", uint64(serviceStatus.ProcessId))
ch <- prometheus.MustNewConstMetric(
c.Information,
prometheus.GaugeValue,
1.0,
strings.ToLower(service),
serviceConfig.DisplayName,
pid,
serviceConfig.ServiceStartName,
)
for _, state := range apiStateValues {
isCurrentState := 0.0
if state == apiStateValues[uint(serviceStatus.State)] {
isCurrentState = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.State,
prometheus.GaugeValue,
isCurrentState,
strings.ToLower(service),
state,
)
}
for _, startMode := range apiStartModeValues {
isCurrentStartMode := 0.0
if startMode == apiStartModeValues[serviceConfig.StartType] {
isCurrentStartMode = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.StartMode,
prometheus.GaugeValue,
isCurrentStartMode,
strings.ToLower(service),
startMode,
)
}
}
return nil
}

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkServiceCollector(b *testing.B) {
benchmarkCollector(b, "service", NewserviceCollector)
}

694
collector/smtp.go Normal file
View File

@@ -0,0 +1,694 @@
//go:build windows
// +build windows
package collector
import (
"fmt"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/alecthomas/kingpin.v2"
"regexp"
)
func init() {
registerCollector("smtp", NewSMTPCollector, "SMTP Server")
}
var (
serverWhitelist = kingpin.Flag("collector.smtp.server-whitelist", "Regexp of virtual servers to whitelist. Server name must both match whitelist and not match blacklist to be included.").Default(".+").String()
serverBlacklist = kingpin.Flag("collector.smtp.server-blacklist", "Regexp of virtual servers to blacklist. Server name must both match whitelist and not match blacklist to be included.").String()
)
type SMTPCollector struct {
BadmailedMessagesBadPickupFileTotal *prometheus.Desc
BadmailedMessagesGeneralFailureTotal *prometheus.Desc
BadmailedMessagesHopCountExceededTotal *prometheus.Desc
BadmailedMessagesNDROfDSNTotal *prometheus.Desc
BadmailedMessagesNoRecipientsTotal *prometheus.Desc
BadmailedMessagesTriggeredViaEventTotal *prometheus.Desc
BytesSentTotal *prometheus.Desc
BytesReceivedTotal *prometheus.Desc
CategorizerQueueLength *prometheus.Desc
ConnectionErrorsTotal *prometheus.Desc
CurrentMessagesInLocalDelivery *prometheus.Desc
DirectoryDropsTotal *prometheus.Desc
DNSQueriesTotal *prometheus.Desc
DSNFailuresTotal *prometheus.Desc
ETRNMessagesTotal *prometheus.Desc
InboundConnectionsCurrent *prometheus.Desc
InboundConnectionsTotal *prometheus.Desc
LocalQueueLength *prometheus.Desc
LocalRetryQueueLength *prometheus.Desc
MailFilesOpen *prometheus.Desc
MessageBytesReceivedTotal *prometheus.Desc
MessageBytesSentTotal *prometheus.Desc
MessageDeliveryRetriesTotal *prometheus.Desc
MessageSendRetriesTotal *prometheus.Desc
MessagesCurrentlyUndeliverable *prometheus.Desc
MessagesDeliveredTotal *prometheus.Desc
MessagesPendingRouting *prometheus.Desc
MessagesReceivedTotal *prometheus.Desc
MessagesRefusedForAddressObjectsTotal *prometheus.Desc
MessagesRefusedForMailObjectsTotal *prometheus.Desc
MessagesRefusedForSizeTotal *prometheus.Desc
MessagesSentTotal *prometheus.Desc
MessagesSubmittedTotal *prometheus.Desc
NDRsGeneratedTotal *prometheus.Desc
OutboundConnectionsCurrent *prometheus.Desc
OutboundConnectionsRefusedTotal *prometheus.Desc
OutboundConnectionsTotal *prometheus.Desc
QueueFilesOpen *prometheus.Desc
PickupDirectoryMessagesRetrievedTotal *prometheus.Desc
RemoteQueueLength *prometheus.Desc
RemoteRetryQueueLength *prometheus.Desc
RoutingTableLookupsTotal *prometheus.Desc
serverWhitelistPattern *regexp.Regexp
serverBlacklistPattern *regexp.Regexp
}
func NewSMTPCollector() (Collector, error) {
log.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.")
const subsystem = "smtp"
return &SMTPCollector{
BadmailedMessagesBadPickupFileTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_bad_pickup_file_total"),
"Total number of malformed pickup messages sent to badmail",
[]string{"site"},
nil,
),
BadmailedMessagesGeneralFailureTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_general_failure_total"),
"Total number of messages sent to badmail for reasons not associated with a specific counter",
[]string{"site"},
nil,
),
BadmailedMessagesHopCountExceededTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_hop_count_exceeded_total"),
"Total number of messages sent to badmail because they had exceeded the maximum hop count",
[]string{"site"},
nil,
),
BadmailedMessagesNDROfDSNTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_ndr_of_dns_total"),
"Total number of Delivery Status Notifications sent to badmail because they could not be delivered",
[]string{"site"},
nil,
),
BadmailedMessagesNoRecipientsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_no_recipients_total"),
"Total number of messages sent to badmail because they had no recipients",
[]string{"site"},
nil,
),
BadmailedMessagesTriggeredViaEventTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_triggered_via_event_total"),
"Total number of messages sent to badmail at the request of a server event sink",
[]string{"site"},
nil,
),
BytesSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"),
"Total number of bytes sent",
[]string{"site"},
nil,
),
BytesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"),
"Total number of bytes received",
[]string{"site"},
nil,
),
CategorizerQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "categorizer_queue_length"),
"Number of messages in the categorizer queue",
[]string{"site"},
nil,
),
ConnectionErrorsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_errors_total"),
"Total number of connection errors",
[]string{"site"},
nil,
),
CurrentMessagesInLocalDelivery: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "current_messages_in_local_delivery"),
"Number of messages that are currently being processed by a server event sink for local delivery",
[]string{"site"},
nil,
),
DirectoryDropsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "directory_drops_total"),
"Total number of messages placed in a drop directory",
[]string{"site"},
nil,
),
DSNFailuresTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dsn_failures_total"),
"Total number of failed DSN generation attempts",
[]string{"site"},
nil,
),
DNSQueriesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dns_queries_total"),
"Total number of DNS lookups",
[]string{"site"},
nil,
),
ETRNMessagesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "etrn_messages_total"),
"Total number of ETRN messages received by the server",
[]string{"site"},
nil,
),
InboundConnectionsCurrent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "inbound_connections_current"),
"Total number of connections currently inbound",
[]string{"site"},
nil,
),
InboundConnectionsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "inbound_connections_total"),
"Total number of inbound connections received",
[]string{"site"},
nil,
),
LocalQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "local_queue_length"),
"Number of messages in the local queue",
[]string{"site"},
nil,
),
LocalRetryQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "local_retry_queue_length"),
"Number of messages in the local retry queue",
[]string{"site"},
nil,
),
MailFilesOpen: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mail_files_open"),
"Number of handles to open mail files",
[]string{"site"},
nil,
),
MessageBytesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "message_bytes_received_total"),
"Total number of bytes received in messages",
[]string{"site"},
nil,
),
MessageBytesSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "message_bytes_sent_total"),
"Total number of bytes sent in messages",
[]string{"site"},
nil,
),
MessageDeliveryRetriesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "message_delivery_retries_total"),
"Total number of local deliveries that were retried",
[]string{"site"},
nil,
),
MessageSendRetriesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "message_send_retries_total"),
"Total number of outbound message sends that were retried",
[]string{"site"},
nil,
),
MessagesCurrentlyUndeliverable: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_currently_undeliverable"),
"Number of messages that have been reported as currently undeliverable by routing",
[]string{"site"},
nil,
),
MessagesDeliveredTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_delivered_total"),
"Total number of messages delivered to local mailboxes",
[]string{"site"},
nil,
),
MessagesPendingRouting: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_pending_routing"),
"Number of messages that have been categorized but not routed",
[]string{"site"},
nil,
),
MessagesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_received_total"),
"Total number of inbound messages accepted",
[]string{"site"},
nil,
),
MessagesRefusedForAddressObjectsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_address_objects_total"),
"Total number of messages refused due to no address objects",
[]string{"site"},
nil,
),
MessagesRefusedForMailObjectsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_mail_objects_total"),
"Total number of messages refused due to no mail objects",
[]string{"site"},
nil,
),
MessagesRefusedForSizeTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_size_total"),
"Total number of messages rejected because they were too big",
[]string{"site"},
nil,
),
MessagesSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_sent_total"),
"Total number of outbound messages sent",
[]string{"site"},
nil,
),
MessagesSubmittedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "messages_submitted_total"),
"Total number of messages submitted to queuing for delivery",
[]string{"site"},
nil,
),
NDRsGeneratedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ndrs_generated_total"),
"Total number of non-delivery reports that have been generated",
[]string{"site"},
nil,
),
OutboundConnectionsCurrent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_current"),
"Number of connections currently outbound",
[]string{"site"},
nil,
),
OutboundConnectionsRefusedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_refused_total"),
"Total number of connection attempts refused by remote sites",
[]string{"site"},
nil,
),
OutboundConnectionsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_total"),
"Total number of outbound connections attempted",
[]string{"site"},
nil,
),
PickupDirectoryMessagesRetrievedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "pickup_directory_messages_retrieved_total"),
"Total number of messages retrieved from the mail pick-up directory",
[]string{"site"},
nil,
),
QueueFilesOpen: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "queue_files_open"),
"Number of handles to open queue files",
[]string{"site"},
nil,
),
RemoteQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "remote_queue_length"),
"Number of messages in the remote queue",
[]string{"site"},
nil,
),
RemoteRetryQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "remote_retry_queue_length"),
"Number of messages in the retry queue for remote delivery",
[]string{"site"},
nil,
),
RoutingTableLookupsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "routing_table_lookups_total"),
"Total number of routing table lookups",
[]string{"site"},
nil,
),
serverWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverWhitelist)),
serverBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverBlacklist)),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *SMTPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting smtp metrics:", desc, err)
return err
}
return nil
}
// Perflib: "SMTP Server"
type PerflibSMTPServer struct {
Name string
BadmailedMessagesBadPickupFileTotal float64 `perflib:"Badmailed Messages (Bad Pickup File)"`
BadmailedMessagesGeneralFailureTotal float64 `perflib:"Badmailed Messages (General Failure)"`
BadmailedMessagesHopCountExceededTotal float64 `perflib:"Badmailed Messages (Hop Count Exceeded)"`
BadmailedMessagesNDROfDSNTotal float64 `perflib:"Badmailed Messages (NDR of DSN)"`
BadmailedMessagesNoRecipientsTotal float64 `perflib:"Badmailed Messages (No Recipients)"`
BadmailedMessagesTriggeredViaEventTotal float64 `perflib:"Badmailed Messages (Triggered via Event)"`
BytesSentTotal float64 `perflib:"Bytes Sent Total"`
BytesReceivedTotal float64 `perflib:"Bytes Received Total"`
CategorizerQueueLength float64 `perflib:"Categorizer Queue Length"`
ConnectionErrorsTotal float64 `perflib:"Total Connection Errors"`
CurrentMessagesInLocalDelivery float64 `perflib:"Current Messages in Local Delivery"`
DirectoryDropsTotal float64 `perflib:"Directory Drops Total"`
DNSQueriesTotal float64 `perflib:"DNS Queries Total"`
DSNFailuresTotal float64 `perflib:"Total DSN Failures"`
ETRNMessagesTotal float64 `perflib:"ETRN Messages Total"`
InboundConnectionsCurrent float64 `perflib:"Inbound Connections Current"`
InboundConnectionsTotal float64 `perflib:"Inbound Connections Total"`
LocalQueueLength float64 `perflib:"Local Queue Length"`
LocalRetryQueueLength float64 `perflib:"Local Retry Queue Length"`
MailFilesOpen float64 `perflib:"Number of MailFiles Open"`
MessageBytesReceivedTotal float64 `perflib:"Message Bytes Received Total"`
MessageBytesSentTotal float64 `perflib:"Message Bytes Sent Total"`
MessageDeliveryRetriesTotal float64 `perflib:"Message Delivery Retries"`
MessageSendRetriesTotal float64 `perflib:"Message Send Retries"`
MessagesCurrentlyUndeliverable float64 `perflib:"Messages Currently Undeliverable"`
MessagesDeliveredTotal float64 `perflib:"Messages Delivered Total"`
MessagesPendingRouting float64 `perflib:"Messages Pending Routing"`
MessagesReceivedTotal float64 `perflib:"Messages Received Total"`
MessagesRefusedForAddressObjectsTotal float64 `perflib:"Messages Refused for Address Objects"`
MessagesRefusedForMailObjectsTotal float64 `perflib:"Messages Refused for Mail Objects"`
MessagesRefusedForSizeTotal float64 `perflib:"Messages Refused for Size"`
MessagesSentTotal float64 `perflib:"Messages Sent Total"`
MessagesSubmittedTotal float64 `perflib:"Total messages submitted"`
NDRsGeneratedTotal float64 `perflib:"NDRs Generated"`
OutboundConnectionsCurrent float64 `perflib:"Outbound Connections Current"`
OutboundConnectionsRefusedTotal float64 `perflib:"Outbound Connections Refused"`
OutboundConnectionsTotal float64 `perflib:"Outbound Connections Total"`
QueueFilesOpen float64 `perflib:"Number of QueueFiles Open"`
PickupDirectoryMessagesRetrievedTotal float64 `perflib:"Pickup Directory Messages Retrieved Total"`
RemoteQueueLength float64 `perflib:"Remote Queue Length"`
RemoteRetryQueueLength float64 `perflib:"Remote Retry Queue Length"`
RoutingTableLookupsTotal float64 `perflib:"Routing Table Lookups Total"`
}
func (c *SMTPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []PerflibSMTPServer
if err := unmarshalObject(ctx.perfObjects["SMTP Server"], &dst); err != nil {
return nil, err
}
for _, server := range dst {
if server.Name == "_Total" ||
c.serverBlacklistPattern.MatchString(server.Name) ||
!c.serverWhitelistPattern.MatchString(server.Name) {
continue
}
ch <- prometheus.MustNewConstMetric(
c.BadmailedMessagesBadPickupFileTotal,
prometheus.CounterValue,
server.BadmailedMessagesBadPickupFileTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.BadmailedMessagesHopCountExceededTotal,
prometheus.CounterValue,
server.BadmailedMessagesHopCountExceededTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.BadmailedMessagesNDROfDSNTotal,
prometheus.CounterValue,
server.BadmailedMessagesNDROfDSNTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.BadmailedMessagesNoRecipientsTotal,
prometheus.CounterValue,
server.BadmailedMessagesNoRecipientsTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.BadmailedMessagesTriggeredViaEventTotal,
prometheus.CounterValue,
server.BadmailedMessagesTriggeredViaEventTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.BytesSentTotal,
prometheus.CounterValue,
server.BytesSentTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.BytesReceivedTotal,
prometheus.CounterValue,
server.BytesReceivedTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.CategorizerQueueLength,
prometheus.GaugeValue,
server.CategorizerQueueLength,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionErrorsTotal,
prometheus.CounterValue,
server.ConnectionErrorsTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.CurrentMessagesInLocalDelivery,
prometheus.GaugeValue,
server.CurrentMessagesInLocalDelivery,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.DirectoryDropsTotal,
prometheus.CounterValue,
server.DirectoryDropsTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.DSNFailuresTotal,
prometheus.CounterValue,
server.DSNFailuresTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.DNSQueriesTotal,
prometheus.CounterValue,
server.DNSQueriesTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ETRNMessagesTotal,
prometheus.CounterValue,
server.ETRNMessagesTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.InboundConnectionsTotal,
prometheus.CounterValue,
server.InboundConnectionsTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.InboundConnectionsCurrent,
prometheus.GaugeValue,
server.InboundConnectionsCurrent,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.LocalQueueLength,
prometheus.GaugeValue,
server.LocalQueueLength,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.LocalRetryQueueLength,
prometheus.GaugeValue,
server.LocalRetryQueueLength,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MailFilesOpen,
prometheus.GaugeValue,
server.MailFilesOpen,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessageBytesReceivedTotal,
prometheus.CounterValue,
server.MessageBytesReceivedTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessageBytesSentTotal,
prometheus.CounterValue,
server.MessageBytesSentTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessageDeliveryRetriesTotal,
prometheus.CounterValue,
server.MessageDeliveryRetriesTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessageSendRetriesTotal,
prometheus.CounterValue,
server.MessageSendRetriesTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesCurrentlyUndeliverable,
prometheus.GaugeValue,
server.MessagesCurrentlyUndeliverable,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesDeliveredTotal,
prometheus.CounterValue,
server.MessagesDeliveredTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesPendingRouting,
prometheus.GaugeValue,
server.MessagesPendingRouting,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesReceivedTotal,
prometheus.CounterValue,
server.MessagesReceivedTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesRefusedForAddressObjectsTotal,
prometheus.CounterValue,
server.MessagesRefusedForAddressObjectsTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesRefusedForMailObjectsTotal,
prometheus.CounterValue,
server.MessagesRefusedForMailObjectsTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesRefusedForSizeTotal,
prometheus.CounterValue,
server.MessagesRefusedForSizeTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesSentTotal,
prometheus.CounterValue,
server.MessagesSentTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.MessagesSubmittedTotal,
prometheus.CounterValue,
server.MessagesSubmittedTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.NDRsGeneratedTotal,
prometheus.CounterValue,
server.NDRsGeneratedTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.OutboundConnectionsCurrent,
prometheus.GaugeValue,
server.OutboundConnectionsCurrent,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.OutboundConnectionsRefusedTotal,
prometheus.CounterValue,
server.OutboundConnectionsRefusedTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.OutboundConnectionsTotal,
prometheus.CounterValue,
server.OutboundConnectionsTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.QueueFilesOpen,
prometheus.GaugeValue,
server.QueueFilesOpen,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.PickupDirectoryMessagesRetrievedTotal,
prometheus.CounterValue,
server.PickupDirectoryMessagesRetrievedTotal,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RemoteQueueLength,
prometheus.GaugeValue,
server.RemoteQueueLength,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RemoteRetryQueueLength,
prometheus.GaugeValue,
server.RemoteRetryQueueLength,
server.Name,
)
ch <- prometheus.MustNewConstMetric(
c.RoutingTableLookupsTotal,
prometheus.CounterValue,
server.RoutingTableLookupsTotal,
server.Name,
)
}
return nil, nil
}

9
collector/smtp_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkSmtpCollector(b *testing.B) {
benchmarkCollector(b, "smtp", NewSMTPCollector)
}

View File

@@ -1,10 +1,11 @@
//go:build windows
// +build windows
package collector
import (
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

9
collector/system_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkSystemCollector(b *testing.B) {
benchmarkCollector(b, "system", NewSystemCollector)
}

View File

@@ -1,19 +1,18 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
registerCollector("tcp", NewTCPCollector)
registerCollector("tcp", NewTCPCollector, "TCPv4", "TCPv6")
}
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv4 metrics
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics
type TCPCollector struct {
ConnectionFailures *prometheus.Desc
ConnectionsActive *prometheus.Desc
@@ -32,57 +31,57 @@ func NewTCPCollector() (Collector, error) {
return &TCPCollector{
ConnectionFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_failures"),
prometheus.BuildFQName(Namespace, subsystem, "connection_failures_total"),
"(TCP.ConnectionFailures)",
nil,
[]string{"af"},
nil,
),
ConnectionsActive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_active"),
prometheus.BuildFQName(Namespace, subsystem, "connections_active_total"),
"(TCP.ConnectionsActive)",
nil,
[]string{"af"},
nil,
),
ConnectionsEstablished: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_established"),
"(TCP.ConnectionsEstablished)",
nil,
[]string{"af"},
nil,
),
ConnectionsPassive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_passive"),
prometheus.BuildFQName(Namespace, subsystem, "connections_passive_total"),
"(TCP.ConnectionsPassive)",
nil,
[]string{"af"},
nil,
),
ConnectionsReset: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_reset"),
prometheus.BuildFQName(Namespace, subsystem, "connections_reset_total"),
"(TCP.ConnectionsReset)",
nil,
[]string{"af"},
nil,
),
SegmentsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_total"),
"(TCP.SegmentsTotal)",
nil,
[]string{"af"},
nil,
),
SegmentsReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_received_total"),
"(TCP.SegmentsReceivedTotal)",
nil,
[]string{"af"},
nil,
),
SegmentsRetransmittedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_retransmitted_total"),
"(TCP.SegmentsRetransmittedTotal)",
nil,
[]string{"af"},
nil,
),
SegmentsSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_sent_total"),
"(TCP.SegmentsSentTotal)",
nil,
[]string{"af"},
nil,
),
}, nil
@@ -91,7 +90,7 @@ func NewTCPCollector() (Collector, error) {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting tcp metrics:", desc, err)
return err
}
@@ -100,75 +99,94 @@ func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
// Win32_PerfRawData_Tcpip_TCPv4 docs
// - https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx
type Win32_PerfRawData_Tcpip_TCPv4 struct {
ConnectionFailures uint64
ConnectionsActive uint64
ConnectionsEstablished uint64
ConnectionsPassive uint64
ConnectionsReset uint64
SegmentsPersec uint64
SegmentsReceivedPersec uint64
SegmentsRetransmittedPersec uint64
SegmentsSentPersec uint64
// The TCPv6 performance object uses the same fields.
type tcp struct {
ConnectionFailures float64 `perflib:"Connection Failures"`
ConnectionsActive float64 `perflib:"Connections Active"`
ConnectionsEstablished float64 `perflib:"Connections Established"`
ConnectionsPassive float64 `perflib:"Connections Passive"`
ConnectionsReset float64 `perflib:"Connections Reset"`
SegmentsPersec float64 `perflib:"Segments/sec"`
SegmentsReceivedPersec float64 `perflib:"Segments Received/sec"`
SegmentsRetransmittedPersec float64 `perflib:"Segments Retransmitted/sec"`
SegmentsSentPersec float64 `perflib:"Segments Sent/sec"`
}
func (c *TCPCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_Tcpip_TCPv4
q := queryAll(&dst)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
// Counters
func writeTCPCounters(metrics tcp, labels []string, c *TCPCollector, ch chan<- prometheus.Metric) {
ch <- prometheus.MustNewConstMetric(
c.ConnectionFailures,
prometheus.CounterValue,
float64(dst[0].ConnectionFailures),
metrics.ConnectionFailures,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsActive,
prometheus.CounterValue,
float64(dst[0].ConnectionsActive),
metrics.ConnectionsActive,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsEstablished,
prometheus.GaugeValue,
float64(dst[0].ConnectionsEstablished),
metrics.ConnectionsEstablished,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsPassive,
prometheus.CounterValue,
float64(dst[0].ConnectionsPassive),
metrics.ConnectionsPassive,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsReset,
prometheus.CounterValue,
float64(dst[0].ConnectionsReset),
metrics.ConnectionsReset,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsPersec),
metrics.SegmentsPersec,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsReceivedTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsReceivedPersec),
metrics.SegmentsReceivedPersec,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsRetransmittedTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsRetransmittedPersec),
metrics.SegmentsRetransmittedPersec,
labels...,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsSentTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsSentPersec),
metrics.SegmentsSentPersec,
labels...,
)
}
func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []tcp
// TCPv4 counters
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil {
return nil, err
}
if len(dst) != 0 {
writeTCPCounters(dst[0], []string{"ipv4"}, c, ch)
}
// TCPv6 counters
if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst); err != nil {
return nil, err
}
if len(dst) != 0 {
writeTCPCounters(dst[0], []string{"ipv6"}, c, ch)
}
return nil, nil
}

9
collector/tcp_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkTCPCollector(b *testing.B) {
benchmarkCollector(b, "tcp", NewTCPCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -7,8 +8,8 @@ import (
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
const ConnectionBrokerFeatureID uint32 = 133
@@ -81,7 +82,7 @@ func NewTerminalServicesCollector() (Collector, error) {
nil,
),
HandleCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "handle_count"),
prometheus.BuildFQName(Namespace, subsystem, "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.",
[]string{"session_name"},
nil,
@@ -141,7 +142,7 @@ func NewTerminalServicesCollector() (Collector, error) {
nil,
),
ThreadCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "thread_count"),
prometheus.BuildFQName(Namespace, subsystem, "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.",
[]string{"session_name"},
nil,

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkTerminalServicesCollector(b *testing.B) {
benchmarkCollector(b, "terminal_services", NewTerminalServicesCollector)
}

View File

@@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !notextfile
// +build !notextfile
package collector
@@ -21,15 +22,16 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"time"
"github.com/dimchansky/utfbom"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/log"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
@@ -37,7 +39,7 @@ var (
textFileDirectory = kingpin.Flag(
"collector.textfile.directory",
"Directory to read text files with metrics from.",
).Default("C:\\Program Files\\windows_exporter\\textfile_inputs").String()
).Default(getDefaultPath()).String()
mtimeDesc = prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "textfile", "mtime_seconds"),
@@ -65,6 +67,31 @@ func NewTextFileCollector() (Collector, error) {
}, nil
}
// Given a slice of metric families, determine if any two entries are duplicates.
// Duplicates will be detected where the metric name, labels and label values are identical.
func duplicateMetricEntry(metricFamilies []*dto.MetricFamily) bool {
uniqueMetrics := make(map[string]map[string]string)
for _, metricFamily := range metricFamilies {
metric_name := *metricFamily.Name
for _, metric := range metricFamily.Metric {
metric_labels := metric.GetLabel()
labels := make(map[string]string)
for _, label := range metric_labels {
labels[label.GetName()] = label.GetValue()
}
// Check if key is present before appending
_, mapContainsKey := uniqueMetrics[metric_name]
// Duplicate metric found with identical labels & label values
if mapContainsKey == true && reflect.DeepEqual(uniqueMetrics[metric_name], labels) {
return true
}
uniqueMetrics[metric_name] = labels
}
}
return false
}
func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric) {
var valType prometheus.ValueType
var val float64
@@ -223,6 +250,10 @@ func (c *textFileCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Met
error = 1.0
}
// Create empty metricFamily slice here and append parsedFamilies to it inside the loop.
// Once loop is complete, raise error if any duplicates are present.
// This will ensure that duplicate metrics are correctly detected between multiple .prom files.
var metricFamilies = []*dto.MetricFamily{}
fileLoop:
for _, f := range files {
if !strings.HasSuffix(f.Name(), ".prom") {
@@ -271,7 +302,16 @@ fileLoop:
// a failure does not appear fresh.
mtimes[f.Name()] = f.ModTime()
for _, mf := range parsedFamilies {
for _, metricFamily := range parsedFamilies {
metricFamilies = append(metricFamilies, metricFamily)
}
}
if duplicateMetricEntry(metricFamilies) {
log.Errorf("Duplicate metrics detected in files")
error = 1.0
} else {
for _, mf := range metricFamilies {
convertMetricFamily(mf, ch)
}
}
@@ -297,3 +337,8 @@ func checkBOM(encoding utfbom.Encoding) error {
return fmt.Errorf(encoding.String())
}
func getDefaultPath() string {
execPath, _ := os.Executable()
return filepath.Join(filepath.Dir(execPath), "textfile_inputs")
}

View File

@@ -5,6 +5,8 @@ import (
"io/ioutil"
"strings"
"testing"
dto "github.com/prometheus/client_model/go"
)
func TestCRFilter(t *testing.T) {
@@ -45,3 +47,108 @@ func TestCheckBOM(t *testing.T) {
}
}
}
func TestDuplicateMetricEntry(t *testing.T) {
metric_name := "windows_sometest"
metric_help := "This is a Test."
metric_type := dto.MetricType_GAUGE
gauge_value := 1.0
gauge := dto.Gauge{
Value: &gauge_value,
}
label1_name := "display_name"
label1_value := "foobar"
label1 := dto.LabelPair{
Name: &label1_name,
Value: &label1_value,
}
label2_name := "display_version"
label2_value := "13.4.0"
label2 := dto.LabelPair{
Name: &label2_name,
Value: &label2_value,
}
metric1 := dto.Metric{
Label: []*dto.LabelPair{&label1, &label2},
Gauge: &gauge,
}
metric2 := dto.Metric{
Label: []*dto.LabelPair{&label1, &label2},
Gauge: &gauge,
}
duplicate := dto.MetricFamily{
Name: &metric_name,
Help: &metric_help,
Type: &metric_type,
Metric: []*dto.Metric{&metric1, &metric2},
}
duplicateFamily := []*dto.MetricFamily{}
duplicateFamily = append(duplicateFamily, &duplicate)
// Ensure detection for duplicate metrics
if !duplicateMetricEntry(duplicateFamily) {
t.Errorf("Duplicate not found in duplicateFamily")
}
label3_name := "test"
label3_value := "1.0"
label3 := dto.LabelPair{
Name: &label3_name,
Value: &label3_value,
}
metric3 := dto.Metric{
Label: []*dto.LabelPair{&label1, &label2, &label3},
Gauge: &gauge,
}
differentLabels := dto.MetricFamily{
Name: &metric_name,
Help: &metric_help,
Type: &metric_type,
Metric: []*dto.Metric{&metric1, &metric3},
}
duplicateFamily = []*dto.MetricFamily{}
duplicateFamily = append(duplicateFamily, &differentLabels)
// Additional label on second metric should not be cause for duplicate detection
if duplicateMetricEntry(duplicateFamily) {
t.Errorf("Unexpected duplicate found in differentLabels")
}
label4_value := "2.0"
label4 := dto.LabelPair{
Name: &label3_name,
Value: &label4_value,
}
metric4 := dto.Metric{
Label: []*dto.LabelPair{&label1, &label2, &label4},
Gauge: &gauge,
}
differentValues := dto.MetricFamily{
Name: &metric_name,
Help: &metric_help,
Type: &metric_type,
Metric: []*dto.Metric{&metric3, &metric4},
}
duplicateFamily = []*dto.MetricFamily{}
duplicateFamily = append(duplicateFamily, &differentValues)
// Additional label with different values metric should not be cause for duplicate detection
if duplicateMetricEntry(duplicateFamily) {
t.Errorf("Unexpected duplicate found in differentValues")
}
}

View File

@@ -1,9 +1,11 @@
package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
@@ -75,6 +77,11 @@ func (c *thermalZoneCollector) collect(ch chan<- prometheus.Metric) (*prometheus
return nil, err
}
// ThermalZone collector has been known to 'successfully' return an empty result.
if len(dst) == 0 {
return nil, errors.New("Empty results set for collector")
}
for _, info := range dst {
//Divide by 10 and subtract 273.15 to convert decikelvin to celsius
ch <- prometheus.MustNewConstMetric(

View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkThermalZoneCollector(b *testing.B) {
benchmarkCollector(b, "thermalzone", NewThermalZoneCollector)
}

131
collector/time.go Normal file
View File

@@ -0,0 +1,131 @@
//go:build windows
// +build windows
package collector
import (
"errors"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
registerCollector("time", newTimeCollector, "Windows Time Service")
}
// TimeCollector is a Prometheus collector for Perflib counter metrics
type TimeCollector struct {
ClockFrequencyAdjustmentPPBTotal *prometheus.Desc
ComputedTimeOffset *prometheus.Desc
NTPClientTimeSourceCount *prometheus.Desc
NTPRoundtripDelay *prometheus.Desc
NTPServerIncomingRequestsTotal *prometheus.Desc
NTPServerOutgoingResponsesTotal *prometheus.Desc
}
func newTimeCollector() (Collector, error) {
if getWindowsVersion() <= 6.1 {
return nil, errors.New("Windows version older than Server 2016 detected. The time collector will not run and should be disabled via CLI flags or configuration file")
}
const subsystem = "time"
return &TimeCollector{
ClockFrequencyAdjustmentPPBTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "clock_frequency_adjustment_ppb_total"),
"Total adjustment made to the local system clock frequency by W32Time in Parts Per Billion (PPB) units.",
nil,
nil,
),
ComputedTimeOffset: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "computed_time_offset_seconds"),
"Absolute time offset between the system clock and the chosen time source, in seconds",
nil,
nil,
),
NTPClientTimeSourceCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_client_time_sources"),
"Active number of NTP Time sources being used by the client",
nil,
nil,
),
NTPRoundtripDelay: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_round_trip_delay_seconds"),
"Roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds",
nil,
nil,
),
NTPServerOutgoingResponsesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_server_outgoing_responses_total"),
"Total number of requests responded to by NTP server",
nil,
nil,
),
NTPServerIncomingRequestsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ntp_server_incoming_requests_total"),
"Total number of requests received by NTP server",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *TimeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting time metrics:", desc, err)
return err
}
return nil
}
// Perflib "Windows Time Service"
type windowsTime struct {
ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"`
ComputedTimeOffset float64 `perflib:"Computed Time Offset"`
NTPClientTimeSourceCount float64 `perflib:"NTP Client Time Source Count"`
NTPRoundtripDelay float64 `perflib:"NTP Roundtrip Delay"`
NTPServerIncomingRequestsTotal float64 `perflib:"NTP Server Incoming Requests"`
NTPServerOutgoingResponsesTotal float64 `perflib:"NTP Server Outgoing Responses"`
}
func (c *TimeCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []windowsTime // Single-instance class, array is required but will have single entry.
if err := unmarshalObject(ctx.perfObjects["Windows Time Service"], &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.ClockFrequencyAdjustmentPPBTotal,
prometheus.CounterValue,
dst[0].ClockFrequencyAdjustmentPPBTotal,
)
ch <- prometheus.MustNewConstMetric(
c.ComputedTimeOffset,
prometheus.GaugeValue,
dst[0].ComputedTimeOffset/1000000, // microseconds -> seconds
)
ch <- prometheus.MustNewConstMetric(
c.NTPClientTimeSourceCount,
prometheus.GaugeValue,
dst[0].NTPClientTimeSourceCount,
)
ch <- prometheus.MustNewConstMetric(
c.NTPRoundtripDelay,
prometheus.GaugeValue,
dst[0].NTPRoundtripDelay/1000000, // microseconds -> seconds
)
ch <- prometheus.MustNewConstMetric(
c.NTPServerIncomingRequestsTotal,
prometheus.CounterValue,
dst[0].NTPServerIncomingRequestsTotal,
)
ch <- prometheus.MustNewConstMetric(
c.NTPServerOutgoingResponsesTotal,
prometheus.CounterValue,
dst[0].NTPServerOutgoingResponsesTotal,
)
return nil, nil
}

9
collector/time_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkTimeCollector(b *testing.B) {
benchmarkCollector(b, "time", newTimeCollector)
}

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package collector
@@ -6,8 +7,8 @@ import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {

9
collector/vmware_test.go Normal file
View File

@@ -0,0 +1,9 @@
package collector
import (
"testing"
)
func BenchmarkVmwareCollector(b *testing.B) {
benchmarkCollector(b, "vmware", NewVmwareCollector)
}

View File

@@ -4,7 +4,7 @@ import (
"bytes"
"reflect"
"github.com/prometheus/common/log"
"github.com/prometheus-community/windows_exporter/log"
)
func className(src interface{}) string {

84
config/config.go Normal file
View File

@@ -0,0 +1,84 @@
// Copyright 2018 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"io/ioutil"
"os"
"github.com/prometheus-community/windows_exporter/log"
"gopkg.in/alecthomas/kingpin.v2"
"gopkg.in/yaml.v2"
)
type getFlagger interface {
GetFlag(name string) *kingpin.FlagClause
}
// Resolver represents a configuration file resolver for kingpin.
type Resolver struct {
flags map[string]string
}
// NewResolver returns a Resolver structure.
func NewResolver(file string) (*Resolver, error) {
flags := map[string]string{}
log.Infof("Loading configuration file: %v", file)
if _, err := os.Stat(file); err != nil {
return nil, err
}
b, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
var rawValues map[string]interface{}
err = yaml.Unmarshal(b, &rawValues)
if err != nil {
return nil, err
}
// Flatten nested YAML values
flattenedValues := flatten(rawValues)
for k, v := range flattenedValues {
if _, ok := flags[k]; !ok {
flags[k] = v
}
}
return &Resolver{flags: flags}, nil
}
func (c *Resolver) setDefault(v getFlagger) {
for name, value := range c.flags {
f := v.GetFlag(name)
if f != nil {
f.Default(value)
}
}
}
// Bind sets active flags with their default values from the configuration file(s).
func (c *Resolver) Bind(app *kingpin.Application, args []string) error {
// Parse the command line arguments to get the selected command.
pc, err := app.ParseContext(args)
if err != nil {
return err
}
c.setDefault(app)
if pc.SelectedCommand != nil {
c.setDefault(pc.SelectedCommand)
}
return nil
}

61
config/flatten.go Normal file
View File

@@ -0,0 +1,61 @@
package config
import "fmt"
// flatten flattens the nested struct.
//
// All keys will be joined by dot
// e.g. {"a": {"b":"c"}} => {"a.b":"c"}
// or {"a": {"b":[1,2]}} => {"a.b.0":1, "a.b.1": 2}
func flatten(data map[string]interface{}) map[string]string {
ret := make(map[string]string)
for k, v := range data {
switch typed := v.(type) {
case map[interface{}]interface{}:
for fk, fv := range flatten(convertMap(typed)) {
ret[fmt.Sprintf("%s.%s", k, fk)] = fv
}
case map[string]interface{}:
for fk, fv := range flatten(typed) {
ret[fmt.Sprintf("%s.%s", k, fk)] = fv
}
case []interface{}:
for fk, fv := range flattenSlice(typed) {
ret[fmt.Sprintf("%s.%s", k, fk)] = fv
}
default:
ret[k] = fmt.Sprint(typed)
}
}
return ret
}
func flattenSlice(data []interface{}) map[string]string {
ret := make(map[string]string)
for idx, v := range data {
switch typed := v.(type) {
case map[interface{}]interface{}:
for fk, fv := range flatten(convertMap(typed)) {
ret[fmt.Sprintf("%d,%s", idx, fk)] = fv
}
case map[string]interface{}:
for fk, fv := range flatten(typed) {
ret[fmt.Sprintf("%d,%s", idx, fk)] = fv
}
case []interface{}:
for fk, fv := range flattenSlice(typed) {
ret[fmt.Sprintf("%d,%s", idx, fk)] = fv
}
default:
ret[fmt.Sprint(idx)] = fmt.Sprint(typed)
}
}
return ret
}
func convertMap(originalMap map[interface{}]interface{}) map[string]interface{} {
convertedMap := map[string]interface{}{}
for key, value := range originalMap {
convertedMap[key.(string)] = value
}
return convertedMap
}

33
config/flatten_test.go Normal file
View File

@@ -0,0 +1,33 @@
package config
import (
"gopkg.in/yaml.v2"
"reflect"
"testing"
)
// Unmarshal good configuration file and confirm data is flattened correctly
func TestConfigFlattening(t *testing.T) {
goodYamlConfig := []byte(`---
collectors:
enabled: cpu,net,service
log:
level: debug`)
var data map[string]interface{}
err := yaml.Unmarshal(goodYamlConfig, &data)
if err != nil {
t.Error(err)
}
expectedResult := map[string]string{
"collectors.enabled": "cpu,net,service",
"log.level": "debug",
}
flattenedValues := flatten(data)
if !reflect.DeepEqual(expectedResult, flattenedValues) {
t.Errorf("Flattened values do not match!\nExpected result: %s\nActual result: %s", expectedResult, flattenedValues)
}
}

View File

@@ -6,6 +6,7 @@ This directory contains documentation of the collectors in the windows_exporter,
- [`adfs`](collector.adfs.md)
- [`cpu`](collector.cpu.md)
- [`cs`](collector.cs.md)
- [`dfsr`](collector.dfsr.md)
- [`dhcp`](collector.dhcp.md)
- [`dns`](collector.dns.md)
- [`hyperv`](collector.hyperv.md)
@@ -28,8 +29,10 @@ This directory contains documentation of the collectors in the windows_exporter,
- [`process`](collector.process.md)
- [`remote_fx`](collector.remote_fx.md)
- [`service`](collector.service.md)
- [`smtp`](collector.smtp.md)
- [`system`](collector.system.md)
- [`tcp`](collector.tcp.md)
- [`terminal_services`](collector.terminal_services.md)
- [`textfile`](collector.textfile.md)
- [`time`](collector.time.md)
- [`vmware`](collector.vmware.md)

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