Compare commits

...

50 Commits

Author SHA1 Message Date
Ben Reedy
5e7462a70e Merge pull request #1292 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.11.1
chore(deps): bump github.com/Microsoft/hcsshim from 0.10.0 to 0.11.1
2023-09-26 18:47:33 +10:00
dependabot[bot]
e8864c766e chore(deps): bump github.com/Microsoft/hcsshim from 0.10.0 to 0.11.1
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.10.0 to 0.11.1.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.10.0...v0.11.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>
2023-09-25 12:00:50 +00:00
rob-scheepens
07fff6afc2 First implementation of physical_disk collector (#803)
* Added physical_disk collector.

Signed-off-by: Rob Scheepens <rob.scheepens@nutanix.com>
Signed-off-by: Brantley West <brantley@nutanix.com>

* exporter.go: Added physical_disk to defaultCollectors

Signed-off-by: Rob Scheepens <rob.scheepens@nutanix.com>
Signed-off-by: Brantley West <brantley@nutanix.com>

* Fix test cases for physicaldisk metrics

Signed-off-by: Rob Scheepens <rob.scheepens@nutanix.com>
Signed-off-by: Brantley West <brantley@nutanix.com>

* physical_disk.go: cleanup gofmt error

Signed-off-by: Brantley West <brantley@nutanix.com>

* physical_disk.go: populate physical disk 'number' label

Signed-off-by: Brantley West <brantley@nutanix.com>

* Added docs/collector.physical_disk.md.

Signed-off-by: Rob Scheepens <rob.scheepens@nutanix.com>

* physical_disk.go: change 'number' label to 'disk' to match node_exporter label

Signed-off-by: Brantley West <brantley@nutanix.com>

* physical_disk.go: adopt github.com/go-kit/log

Signed-off-by: Brantley West <brantley@nutanix.com>

* physical_disk.go: adopt include/exclude disk list

Signed-off-by: Brantley West <brantley@nutanix.com>

* fix: Add init config for physical_disk collector

Signed-off-by: Ben Reedy <breed808@breed808.com>

* chore: gofmt physical_disk collector

Signed-off-by: Ben Reedy <breed808@breed808.com>

---------

Signed-off-by: Rob Scheepens <rob.scheepens@nutanix.com>
Signed-off-by: Brantley West <brantley@nutanix.com>
Signed-off-by: Ben Reedy <breed808@breed808.com>
Co-authored-by: Brantley West <brantley@nutanix.com>
Co-authored-by: Ben Reedy <breed808@breed808.com>
2023-09-22 16:45:22 +10:00
Ben Reedy
083537a96a Merge pull request #1262 from DiniFarb/textfile_collector
Textfile collector: collect files from multiple paths
2023-09-22 06:36:23 +10:00
Ben Reedy
6aa0ac5706 Merge pull request #1283 from breed808/go_version_bump
chore(deps): Bump Go version to v1.21.1
2023-09-11 20:31:10 +10:00
Ben Reedy
7d2d7f3d1c chore(deps): Bump Go version to v1.21.1
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-09-11 20:25:58 +10:00
Ben Reedy
f8c298e038 Merge pull request #1279 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.12.0
chore(deps): bump golang.org/x/sys from 0.11.0 to 0.12.0
2023-09-05 06:14:28 +10:00
Ben Reedy
4e9fa4fd8e Merge pull request #1278 from MarkDordoy/md/add-new-counter
Add new counter LDAP Client Sessions
2023-09-05 06:13:58 +10:00
dependabot[bot]
d8524c505b chore(deps): bump golang.org/x/sys from 0.11.0 to 0.12.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.11.0 to 0.12.0.
- [Commits](https://github.com/golang/sys/compare/v0.11.0...v0.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 11:09:55 +00:00
Mark Dordoy
ca6eb75685 add recommendation to prefix with ldap
Signed-off-by: Mark Dordoy <mdordoy@palantir.com>
2023-09-04 09:49:52 +01:00
Mark Dordoy
5631166075 Add description in docs
Signed-off-by: Mark Dordoy <mdordoy@palantir.com>
2023-09-04 09:49:52 +01:00
Mark Dordoy
1d027579d2 Add description, fix typo on type
Signed-off-by: Mark Dordoy <mdordoy@palantir.com>
2023-09-04 09:49:52 +01:00
Mark Dordoy
23e1a86aa7 Fix docs
Signed-off-by: Mark Dordoy <mdordoy@palantir.com>
2023-09-04 09:49:51 +01:00
Mark Dordoy
f8b8b2c546 Added docs, updated to gague. Signed-off-by: Mark Dordoy <mdordoy@palantir.com>
Signed-off-by: Mark Dordoy <mdordoy@palantir.com>
2023-09-04 09:49:51 +01:00
Mark Dordoy
d78230f67b Add new counter
Signed-off-by: Mark Dordoy <mdordoy@palantir.com>
2023-09-04 09:49:47 +01:00
Ben Reedy
f7426e9fad Merge pull request #1276 from DiniFarb/win_srv_stop_error
fix: Windows service can't stop without an error
2023-08-26 08:34:04 +10:00
Dinifarb
fdec95bc99 tie all loggers to global var
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-25 20:04:57 +02:00
Ben Reedy
75ae769b6e Merge pull request #1274 from prometheus-community/dependabot/go_modules/github.com/go-ole/go-ole-1.3.0
chore(deps): bump github.com/go-ole/go-ole from 1.2.6 to 1.3.0
2023-08-23 20:28:49 +10:00
Dinifarb
4add010b8d fix: Windows service can't stop without an error #1258
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-22 16:53:43 +02:00
Dinifarb
7530e7b400 fix: .hidden() for deprecated directory flag
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-21 19:29:19 +02:00
Dinifarb
9473265ffa readme & text changes
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-21 19:29:19 +02:00
Dinifarb
0ec4e9d90f fix: typo
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-21 19:29:19 +02:00
Dinifarb
7876a465ca fix: linter issue
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-21 19:29:19 +02:00
Dinifarb
f9361bb684 (#1236) textfile: more tests added
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-21 19:29:19 +02:00
Dinifarb
f5b9ba35d0 feat: (#1236) textfile: collect files from multiple path
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-21 19:29:19 +02:00
dependabot[bot]
7c178e5ced chore(deps): bump github.com/go-ole/go-ole from 1.2.6 to 1.3.0
Bumps [github.com/go-ole/go-ole](https://github.com/go-ole/go-ole) from 1.2.6 to 1.3.0.
- [Release notes](https://github.com/go-ole/go-ole/releases)
- [Changelog](https://github.com/go-ole/go-ole/blob/master/ChangeLog.md)
- [Commits](https://github.com/go-ole/go-ole/compare/v1.2.6...v1.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 11:56:35 +00:00
Ben Reedy
134bae514d Merge pull request #1273 from breed808/tcp_reset_description
fix(docs): Set correct TCP reset description
2023-08-20 13:34:30 +10:00
Ben Reedy
a4beb4c187 fix(docs): Set correct TCP reset description
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-08-20 13:31:44 +10:00
Ben Reedy
884cac808a Merge pull request #1272 from breed808/adfs_documentation
fix(docs): Remove duplicate ADFS metrics
2023-08-20 11:07:36 +10:00
Ben Reedy
117ba941df fix(docs): Remove duplicate ADFS metrics
Remaining metrics had the correct prefix (windows_adfs_) added.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-08-20 11:05:16 +10:00
Ben Reedy
8d61595607 Merge pull request #1267 from prometheus-community/dependabot/go_modules/golang.org/x/sys-0.11.0
chore(deps): bump golang.org/x/sys from 0.10.0 to 0.11.0
2023-08-09 07:06:34 +10:00
Ben Reedy
68f5c61de8 Merge pull request #1220 from yuriyostapenko/hyperv-waittime
Add Hyper-V CPUWaitTimePerDispatch metrics
2023-08-09 06:30:52 +10:00
Yuriy Ostapenko
ca5124fdf9 Add _total suffix for counters
Signed-off-by: Yuriy Ostapenko <yuo@scalepoint.com>
2023-08-08 09:58:06 +02:00
Yuriy Ostapenko
e2b48497f4 Add Hyper-V CPUWaitTimePerDispatch collection
Signed-off-by: Yuriy Ostapenko <yuo@scalepoint.com>
2023-08-08 09:54:10 +02:00
dependabot[bot]
b1eaf00e74 chore(deps): bump golang.org/x/sys from 0.10.0 to 0.11.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/sys/compare/v0.10.0...v0.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-07 11:05:12 +00:00
Ben Reedy
34da140f87 Merge pull request #1266 from bragi92/patch-1
fix: Create a monitoring namespace if it does not exist in windows exporter daemonset
2023-08-06 08:16:55 +10:00
Ben Reedy
7a3a978d79 Merge pull request #1264 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.10.0
chore(deps): bump github.com/Microsoft/hcsshim from 0.9.10 to 0.10.0
2023-08-06 08:12:36 +10:00
bragi92
e9b8f82b2c fix: Create a monitoring namespace if it does not exist in windows exporter daemonset
Signed-off-by: bragi92 <kadubey@microsoft.com>
2023-08-01 12:09:01 -07:00
Ben Reedy
b0a1a38829 Merge pull request #1265 from DiniFarb/fix_configfile
fix: config file CLI argument for relative paths -> v0.23.1
2023-08-01 20:56:52 +10:00
Dinifarb
f77bdcfa09 fix: include :// for better http/s recogitation
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-08-01 12:36:30 +02:00
Dinifarb
2fb5b89d92 fix: #1263
Signed-off-by: Dinifarb <andreas.vogt89@bluewin.ch>
2023-07-31 18:22:07 +02:00
dependabot[bot]
65c8fa4304 chore(deps): bump github.com/Microsoft/hcsshim from 0.9.10 to 0.10.0
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.9.10 to 0.10.0.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.9.10...v0.10.0)

---
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>
2023-07-31 11:22:33 +00:00
Ben Reedy
8f7031861a Merge pull request #1260 from prometheus-community/dependabot/go_modules/github.com/Microsoft/hcsshim-0.9.10
chore(deps): bump github.com/Microsoft/hcsshim from 0.9.8 to 0.9.10
2023-07-26 05:57:38 +10:00
dependabot[bot]
a78c707f47 chore(deps): bump github.com/Microsoft/hcsshim from 0.9.8 to 0.9.10
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.9.8 to 0.9.10.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.9.8...v0.9.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 11:02:40 +00:00
Ben Reedy
eb1b1ccb54 Merge pull request #1257 from breed808/fix_iis_site_include
fix: Remove default value from deprecated IIS flag
2023-07-22 09:29:12 +10:00
Ben Reedy
8447758db5 fix: Remove default value from deprecated IIS flag
Default value prevented use of the new `collector.iis.site-include`
flag.

Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-07-22 09:23:44 +10:00
Ben Reedy
05091643c6 Merge pull request #1256 from breed808/fix_msi_flag
fix: Set correct eventlog flag for MSI installer
2023-07-22 08:42:41 +10:00
Ben Reedy
76e73487e4 fix: Set correct eventlog flag for MSI installer
Signed-off-by: Ben Reedy <breed808@breed808.com>
2023-07-22 08:38:09 +10:00
Ben Reedy
9a2ec21278 Merge pull request #1255 from jkroepke/fix-eventlog
Fix panic with log.file=eventlog
2023-07-22 08:31:11 +10:00
Jan-Otto Kröpke
44b435e7d4 Fix panic with log.file=eventlog
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-07-21 20:18:15 +02:00
32 changed files with 785 additions and 1060 deletions

View File

@@ -23,6 +23,7 @@ on:
- master
env:
GO_VER: '^1.21.1'
PROMU_VER: '0.14.0'
PROMTOOL_VER: '2.43.0'
@@ -33,7 +34,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.20.2'
go-version: ${{ env.GO_VER }}
- name: Test
run: make test
@@ -57,7 +58,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.20.2'
go-version: ${{ env.GO_VER }}
- name: Install promtool
run: |
@@ -89,7 +90,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.20.2'
go-version: ${{ env.GO_VER }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v3

View File

@@ -25,7 +25,7 @@ jobs:
- uses: actions/setup-go@v3
with:
go-version: '^1.20.2'
go-version: '^1.21.1'
- name: Install Build deps
run: |

View File

@@ -20,7 +20,7 @@ test:
go test -v ./...
bench:
go test -v -bench='benchmark(cpu|logicaldisk|logon|memory|net|process|service|system|tcp|time)collector' ./...
go test -v -bench='benchmark(cpu|logicaldisk|physicaldisk|logon|memory|net|process|service|system|tcp|time)collector' ./...
lint:
golangci-lint -c .golangci.yaml run

View File

@@ -59,6 +59,7 @@ type ADCollector struct {
LdapSearchesTotal *prometheus.Desc
LdapUdpOperationsTotal *prometheus.Desc
LdapWritesTotal *prometheus.Desc
LdapClientSessions *prometheus.Desc
LinkValuesCleanedTotal *prometheus.Desc
PhantomObjectsCleanedTotal *prometheus.Desc
PhantomObjectsVisitedTotal *prometheus.Desc
@@ -343,6 +344,12 @@ func newADCollector(logger log.Logger) (Collector, error) {
nil,
nil,
),
LdapClientSessions: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "ldap_client_sessions"),
"This is the number of sessions opened by LDAP clients at the time the data is taken. This is helpful in determining LDAP client activity and if the DC is able to handle the load. Of course, spikes during normal periods of authentication — such as first thing in the morning — are not necessarily a problem, but long sustained periods of high values indicate an overworked DC.",
nil,
nil,
),
LinkValuesCleanedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "link_values_cleaned_total"),
"",
@@ -1190,6 +1197,11 @@ func (c *ADCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
prometheus.CounterValue,
float64(dst[0].LDAPWritesPersec),
)
ch <- prometheus.MustNewConstMetric(
c.LdapClientSessions,
prometheus.GaugeValue,
float64(dst[0].LDAPClientSessions),
)
ch <- prometheus.MustNewConstMetric(
c.LinkValuesCleanedTotal,

View File

@@ -59,16 +59,18 @@ type HyperVCollector struct {
HostLPTotalRunTimePercent *prometheus.Desc
// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
HostGuestRunTime *prometheus.Desc
HostHypervisorRunTime *prometheus.Desc
HostRemoteRunTime *prometheus.Desc
HostTotalRunTime *prometheus.Desc
HostGuestRunTime *prometheus.Desc
HostHypervisorRunTime *prometheus.Desc
HostRemoteRunTime *prometheus.Desc
HostTotalRunTime *prometheus.Desc
HostCPUWaitTimePerDispatch *prometheus.Desc
// Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
VMGuestRunTime *prometheus.Desc
VMHypervisorRunTime *prometheus.Desc
VMRemoteRunTime *prometheus.Desc
VMTotalRunTime *prometheus.Desc
VMGuestRunTime *prometheus.Desc
VMHypervisorRunTime *prometheus.Desc
VMRemoteRunTime *prometheus.Desc
VMTotalRunTime *prometheus.Desc
VMCPUWaitTimePerDispatch *prometheus.Desc
// Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch
BroadcastPacketsReceived *prometheus.Desc
@@ -362,6 +364,12 @@ func newHyperVCollector(logger log.Logger) (Collector, error) {
[]string{"core"},
nil,
),
HostCPUWaitTimePerDispatch: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "wait_time_per_dispatch_total"),
"Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor",
[]string{"core"},
nil,
),
//
@@ -389,6 +397,12 @@ func newHyperVCollector(logger log.Logger) (Collector, error) {
[]string{"vm", "core"},
nil,
),
VMCPUWaitTimePerDispatch: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "wait_time_per_dispatch_total"),
"Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor",
[]string{"vm", "core"},
nil,
),
//
BroadcastPacketsReceived: prometheus.NewDesc(
@@ -1093,6 +1107,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct {
PercentHypervisorRunTime uint64
PercentRemoteRunTime uint64
PercentTotalRunTime uint64
CPUWaitTimePerDispatch uint64
}
func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
@@ -1142,6 +1157,12 @@ func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*pro
coreId,
)
ch <- prometheus.MustNewConstMetric(
c.HostCPUWaitTimePerDispatch,
prometheus.CounterValue,
float64(obj.CPUWaitTimePerDispatch),
coreId,
)
}
return nil, nil
@@ -1154,6 +1175,7 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct {
PercentHypervisorRunTime uint64
PercentRemoteRunTime uint64
PercentTotalRunTime uint64
CPUWaitTimePerDispatch uint64
}
func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
@@ -1209,6 +1231,13 @@ func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prome
vmName, coreId,
)
ch <- prometheus.MustNewConstMetric(
c.VMCPUWaitTimePerDispatch,
prometheus.CounterValue,
float64(obj.CPUWaitTimePerDispatch),
vmName, coreId,
)
}
return nil, nil

View File

@@ -220,7 +220,7 @@ type IISCollector struct {
}
func newIISCollectorFlags(app *kingpin.Application) {
oldSiteInclude = app.Flag(FlagIISSiteOldInclude, "DEPRECATED: Use --collector.iis.site-include").Default(".+").Hidden().String()
oldSiteInclude = app.Flag(FlagIISSiteOldInclude, "DEPRECATED: Use --collector.iis.site-include").Hidden().String()
oldSiteExclude = app.Flag(FlagIISSiteOldExclude, "DEPRECATED: Use --collector.iis.site-exclude").Hidden().String()
oldAppInclude = app.Flag(FlagIISAppOldInclude, "DEPRECATED: Use --collector.iis.app-include").Hidden().String()
oldAppExclude = app.Flag(FlagIISAppOldExclude, "DEPRECATED: Use --collector.iis.app-exclude").Hidden().String()

View File

@@ -288,6 +288,14 @@ var collectors = []collectorInit{
return []string{"Paging File"}
},
},
{
name: "physical_disk",
flags: newPhysicalDiskCollectorFlags,
builder: NewPhysicalDiskCollector,
perfCounterFunc: func(_ log.Logger) []string {
return []string{"PhysicalDisk"}
},
},
{
name: "process",
flags: newProcessCollectorFlags,

298
collector/physical_disk.go Normal file
View File

@@ -0,0 +1,298 @@
//go:build windows
// +build windows
package collector
import (
"fmt"
"regexp"
"strings"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
)
const (
FlagPhysicalDiskExclude = "collector.physical_disk.disk-exclude"
FlagPhysicalDiskInclude = "collector.physical_disk.disk-include"
)
var (
diskInclude *string
diskExclude *string
diskIncludeSet bool
diskExcludeSet bool
)
// A PhysicalDiskCollector is a Prometheus collector for perflib PhysicalDisk metrics
type PhysicalDiskCollector struct {
logger log.Logger
RequestsQueued *prometheus.Desc
ReadBytesTotal *prometheus.Desc
ReadsTotal *prometheus.Desc
WriteBytesTotal *prometheus.Desc
WritesTotal *prometheus.Desc
ReadTime *prometheus.Desc
WriteTime *prometheus.Desc
IdleTime *prometheus.Desc
SplitIOs *prometheus.Desc
ReadLatency *prometheus.Desc
WriteLatency *prometheus.Desc
ReadWriteLatency *prometheus.Desc
diskIncludePattern *regexp.Regexp
diskExcludePattern *regexp.Regexp
}
// newPhysicalDiskCollectorFlags ...
func newPhysicalDiskCollectorFlags(app *kingpin.Application) {
diskInclude = app.Flag(
FlagPhysicalDiskInclude,
"Regexp of disks to include. Disk number must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
diskIncludeSet = true
return nil
}).String()
diskExclude = app.Flag(
FlagPhysicalDiskExclude,
"Regexp of disks to exclude. Disk number must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
diskExcludeSet = true
return nil
}).String()
}
// NewPhysicalDiskCollector ...
func NewPhysicalDiskCollector(logger log.Logger) (Collector, error) {
const subsystem = "physical_disk"
logger = log.With(logger, "collector", subsystem)
return &PhysicalDiskCollector{
logger: logger,
RequestsQueued: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "requests_queued"),
"The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)",
[]string{"disk"},
nil,
),
ReadBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_bytes_total"),
"The number of bytes transferred from the disk during read operations (PhysicalDisk.DiskReadBytesPerSec)",
[]string{"disk"},
nil,
),
ReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "reads_total"),
"The number of read operations on the disk (PhysicalDisk.DiskReadsPerSec)",
[]string{"disk"},
nil,
),
WriteBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "write_bytes_total"),
"The number of bytes transferred to the disk during write operations (PhysicalDisk.DiskWriteBytesPerSec)",
[]string{"disk"},
nil,
),
WritesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "writes_total"),
"The number of write operations on the disk (PhysicalDisk.DiskWritesPerSec)",
[]string{"disk"},
nil,
),
ReadTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_seconds_total"),
"Seconds that the disk was busy servicing read requests (PhysicalDisk.PercentDiskReadTime)",
[]string{"disk"},
nil,
),
WriteTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "write_seconds_total"),
"Seconds that the disk was busy servicing write requests (PhysicalDisk.PercentDiskWriteTime)",
[]string{"disk"},
nil,
),
IdleTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "idle_seconds_total"),
"Seconds that the disk was idle (PhysicalDisk.PercentIdleTime)",
[]string{"disk"},
nil,
),
SplitIOs: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "split_ios_total"),
"The number of I/Os to the disk were split into multiple I/Os (PhysicalDisk.SplitIOPerSec)",
[]string{"disk"},
nil,
),
ReadLatency: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_latency_seconds_total"),
"Shows the average time, in seconds, of a read operation from the disk (PhysicalDisk.AvgDiskSecPerRead)",
[]string{"disk"},
nil,
),
WriteLatency: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "write_latency_seconds_total"),
"Shows the average time, in seconds, of a write operation to the disk (PhysicalDisk.AvgDiskSecPerWrite)",
[]string{"disk"},
nil,
),
ReadWriteLatency: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_write_latency_seconds_total"),
"Shows the time, in seconds, of the average disk transfer (PhysicalDisk.AvgDiskSecPerTransfer)",
[]string{"disk"},
nil,
),
diskIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *diskInclude)),
diskExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *diskExclude)),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *PhysicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ctx, ch); err != nil {
_ = level.Error(c.logger).Log("failed collecting physical_disk metrics", "desc", desc, "err", err)
return err
}
return nil
}
// Win32_PerfRawData_PerfDisk_PhysicalDisk docs:
// - https://docs.microsoft.com/en-us/previous-versions/aa394308(v=vs.85) - Win32_PerfRawData_PerfDisk_PhysicalDisk class
type PhysicalDisk struct {
Name string
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`
DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"`
DiskReadsPerSec float64 `perflib:"Disk Reads/sec"`
DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"`
DiskWritesPerSec float64 `perflib:"Disk Writes/sec"`
PercentDiskReadTime float64 `perflib:"% Disk Read Time"`
PercentDiskWriteTime float64 `perflib:"% Disk Write Time"`
PercentIdleTime float64 `perflib:"% Idle Time"`
SplitIOPerSec float64 `perflib:"Split IO/Sec"`
AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"`
AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"`
AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"`
}
func (c *PhysicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []PhysicalDisk
if err := unmarshalObject(ctx.perfObjects["PhysicalDisk"], &dst, c.logger); err != nil {
return nil, err
}
for _, disk := range dst {
if disk.Name == "_Total" ||
c.diskExcludePattern.MatchString(disk.Name) ||
!c.diskIncludePattern.MatchString(disk.Name) {
continue
}
// Parse physical disk number from disk.Name. Mountpoint information is
// sometimes included, e.g. "1 C:".
disk_number, _, _ := strings.Cut(disk.Name, " ")
ch <- prometheus.MustNewConstMetric(
c.RequestsQueued,
prometheus.GaugeValue,
disk.CurrentDiskQueueLength,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.ReadBytesTotal,
prometheus.CounterValue,
disk.DiskReadBytesPerSec,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.ReadsTotal,
prometheus.CounterValue,
disk.DiskReadsPerSec,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.WriteBytesTotal,
prometheus.CounterValue,
disk.DiskWriteBytesPerSec,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.WritesTotal,
prometheus.CounterValue,
disk.DiskWritesPerSec,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.ReadTime,
prometheus.CounterValue,
disk.PercentDiskReadTime,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.WriteTime,
prometheus.CounterValue,
disk.PercentDiskWriteTime,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.IdleTime,
prometheus.CounterValue,
disk.PercentIdleTime,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.SplitIOs,
prometheus.CounterValue,
disk.SplitIOPerSec,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.ReadLatency,
prometheus.CounterValue,
disk.AvgDiskSecPerRead*ticksToSecondsScaleFactor,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.WriteLatency,
prometheus.CounterValue,
disk.AvgDiskSecPerWrite*ticksToSecondsScaleFactor,
disk_number,
)
ch <- prometheus.MustNewConstMetric(
c.ReadWriteLatency,
prometheus.CounterValue,
disk.AvgDiskSecPerTransfer*ticksToSecondsScaleFactor,
disk_number,
)
}
return nil, nil
}

View File

@@ -19,7 +19,6 @@ package collector
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -37,11 +36,13 @@ import (
)
const (
FlagTextFileDirectory = "collector.textfile.directory"
FlagTextFileDirectory = "collector.textfile.directory"
FlagTextFileDirectories = "collector.textfile.directories"
)
var (
textFileDirectory *string
textFileDirectory *string
textFileDirectories *string
mtimeDesc = prometheus.NewDesc(
prometheus.BuildFQName(Namespace, "textfile", "mtime_seconds"),
@@ -54,7 +55,7 @@ var (
type textFileCollector struct {
logger log.Logger
path string
directories string
// Only set for testing to get predictable output.
mtime *float64
}
@@ -63,17 +64,27 @@ type textFileCollector struct {
func newTextFileCollectorFlags(app *kingpin.Application) {
textFileDirectory = app.Flag(
FlagTextFileDirectory,
"Directory to read text files with metrics from.",
).Default(getDefaultPath()).String()
"DEPRECATED: Use --collector.textfile.directories",
).Default("").Hidden().String()
textFileDirectories = app.Flag(
FlagTextFileDirectories,
"Directory or Directories to read text files with metrics from.",
).Default("").String()
}
// newTextFileCollector returns a new Collector exposing metrics read from files
// in the given textfile directory.
func newTextFileCollector(logger log.Logger) (Collector, error) {
const subsystem = "textfile"
directories := getDefaultPath()
if *textFileDirectory != "" || *textFileDirectories != "" {
directories = *textFileDirectory + "," + *textFileDirectories
directories = strings.Trim(directories, ",")
}
_ = level.Info(logger).Log("msg", fmt.Sprintf("textfile collector directories: %s", directories))
return &textFileCollector{
logger: log.With(logger, "collector", subsystem),
path: *textFileDirectory,
logger: log.With(logger, "collector", subsystem),
directories: directories,
}, nil
}
@@ -250,89 +261,55 @@ func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) {
// Update implements the Collector interface.
func (c *textFileCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
error := 0.0
mtimes := map[string]time.Time{}
// Iterate over files and accumulate their metrics.
files, err := ioutil.ReadDir(c.path)
if err != nil && c.path != "" {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error reading textfile collector directory %q", c.path), "err", err)
error = 1.0
}
errorMetric := 0.0
var mtimes = map[string]time.Time{}
// 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") {
continue
}
path := filepath.Join(c.path, f.Name())
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("Processing file %q", path))
file, err := os.Open(path)
if err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error opening %q: %v", path, err))
error = 1.0
continue
}
var parser expfmt.TextParser
r, encoding := utfbom.Skip(carriageReturnFilteringReader{r: file})
if err = checkBOM(encoding); err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Invalid file encoding detected in %s: %s - file must be UTF8", path, err.Error()))
error = 1.0
continue
}
parsedFamilies, err := parser.TextToMetricFamilies(r)
closeErr := file.Close()
if closeErr != nil {
_ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Error closing file"), "err", err)
}
if err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error parsing %q: %v", path, err))
error = 1.0
continue
}
// Use temporary array to check for duplicates
var families_array []*dto.MetricFamily
for _, mf := range parsedFamilies {
families_array = append(families_array, mf)
for _, m := range mf.Metric {
if m.TimestampMs != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Textfile %q contains unsupported client-side timestamps, skipping entire file", path))
error = 1.0
continue fileLoop
// Iterate over files and accumulate their metrics.
for _, directory := range strings.Split(c.directories, ",") {
err := filepath.WalkDir(directory, func(path string, dirEntry os.DirEntry, err error) error {
if err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error reading directory: %s", path), "err", err)
errorMetric = 1.0
return nil
}
if !dirEntry.IsDir() && strings.HasSuffix(dirEntry.Name(), ".prom") {
_ = level.Debug(c.logger).Log("msg", fmt.Sprintf("Processing file: %s", path))
families_array, err := scrapeFile(path, c.logger)
if err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error scraping file: %q. Skip File.", path), "err", err)
errorMetric = 1.0
return nil
}
fileInfo, err := os.Stat(path)
if err != nil {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error reading file info: %q. Skip File.", path), "err", err)
errorMetric = 1.0
return nil
}
if _, hasName := mtimes[fileInfo.Name()]; hasName {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Duplicate filename detected: %q. Skip File.", path))
errorMetric = 1.0
return nil
}
mtimes[fileInfo.Name()] = fileInfo.ModTime()
metricFamilies = append(metricFamilies, families_array...)
}
if mf.Help == nil {
help := fmt.Sprintf("Metric read from %s", path)
mf.Help = &help
}
}
// If duplicate metrics are detected in a *single* file, skip processing of file metrics
if duplicateMetricEntry(families_array) {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Duplicate metrics detected in file %s. Skipping file processing.", f.Name()))
error = 1.0
continue
}
// Only set this once it has been parsed and validated, so that
// a failure does not appear fresh.
mtimes[f.Name()] = f.ModTime()
for _, metricFamily := range parsedFamilies {
metricFamilies = append(metricFamilies, metricFamily)
return nil
})
if err != nil && directory != "" {
_ = level.Error(c.logger).Log("msg", fmt.Sprintf("Error reading textfile collector directory: %s", c.directories), "err", err)
errorMetric = 1.0
}
}
// If duplicates are detected across *multiple* files, return error.
if duplicateMetricEntry(metricFamilies) {
_ = level.Error(c.logger).Log("msg", "Duplicate metrics detected across multiple files")
error = 1.0
errorMetric = 1.0
} else {
for _, mf := range metricFamilies {
c.convertMetricFamily(mf, ch)
@@ -340,7 +317,6 @@ fileLoop:
}
c.exportMTimes(mtimes, ch)
// Export if there were errors.
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
@@ -348,11 +324,53 @@ fileLoop:
"1 if there was an error opening or reading a file, 0 otherwise",
nil, nil,
),
prometheus.GaugeValue, error,
prometheus.GaugeValue, errorMetric,
)
return nil
}
func scrapeFile(path string, log log.Logger) ([]*dto.MetricFamily, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
var parser expfmt.TextParser
r, encoding := utfbom.Skip(carriageReturnFilteringReader{r: file})
if err = checkBOM(encoding); err != nil {
return nil, err
}
parsedFamilies, err := parser.TextToMetricFamilies(r)
closeErr := file.Close()
if closeErr != nil {
_ = level.Warn(log).Log("msg", fmt.Sprintf("Error closing file %q", path), "err", closeErr)
}
if err != nil {
return nil, err
}
// Use temporary array to check for duplicates
var families_array []*dto.MetricFamily
for _, mf := range parsedFamilies {
families_array = append(families_array, mf)
for _, m := range mf.Metric {
if m.TimestampMs != nil {
return nil, fmt.Errorf("textfile contains unsupported client-side timestamps")
}
}
if mf.Help == nil {
help := fmt.Sprintf("Metric read from %s", path)
mf.Help = &help
}
}
// If duplicate metrics are detected in a *single* file, skip processing of file metrics
if duplicateMetricEntry(families_array) {
return nil, fmt.Errorf("duplicate metrics detected")
}
return families_array, nil
}
func checkBOM(encoding utfbom.Encoding) error {
if encoding == utfbom.Unknown || encoding == utfbom.UTF8 {
return nil

View File

@@ -1,19 +1,25 @@
package collector
import (
"io/ioutil"
"fmt"
"io"
"os"
"strings"
"testing"
"github.com/dimchansky/utfbom"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
)
var baseDir = "../tools/textfile-test"
func TestCRFilter(t *testing.T) {
sr := strings.NewReader("line 1\r\nline 2")
cr := carriageReturnFilteringReader{r: sr}
b, err := ioutil.ReadAll(cr)
b, err := io.ReadAll(cr)
if err != nil {
t.Error(err)
}
@@ -153,3 +159,73 @@ func TestDuplicateMetricEntry(t *testing.T) {
t.Errorf("Unexpected duplicate found in differentValues")
}
}
func TestMultipleDirectories(t *testing.T) {
testDir := baseDir + "/multiple-dirs"
testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir)
collector := &textFileCollector{
logger: log.NewLogfmtLogger(os.Stdout),
directories: testDirs,
}
scrapeContext, err := PrepareScrapeContext([]string{"textfile_test"})
if err != nil {
t.Errorf("Unexpected error %s", err)
}
metrics := make(chan prometheus.Metric)
got := ""
go func() {
for {
var metric dto.Metric
val := <-metrics
err := val.Write(&metric)
if err != nil {
t.Errorf("Unexpected error %s", err)
}
got += metric.String()
}
}()
err = collector.Collect(scrapeContext, metrics)
if err != nil {
t.Errorf("Unexpected error %s", err)
}
for _, f := range []string{"dir1", "dir2", "dir3", "dir3sub"} {
if !strings.Contains(got, f) {
t.Errorf("Unexpected output %s: %q", f, got)
}
}
}
func TestDuplicateFileName(t *testing.T) {
testDir := baseDir + "/duplicate-filename"
collector := &textFileCollector{
logger: log.NewLogfmtLogger(os.Stdout),
directories: testDir,
}
scrapeContext, err := PrepareScrapeContext([]string{"textfile_test"})
if err != nil {
t.Errorf("Unexpected error %s", err)
}
metrics := make(chan prometheus.Metric)
got := ""
go func() {
for {
var metric dto.Metric
val := <-metrics
err := val.Write(&metric)
if err != nil {
t.Errorf("Unexpected error %s", err)
}
got += metric.String()
}
}()
err = collector.Collect(scrapeContext, metrics)
if err != nil {
t.Errorf("Unexpected error %s", err)
}
if !strings.Contains(got, "file") {
t.Errorf("Unexpected output %q", got)
}
if strings.Contains(got, "sub_file") {
t.Errorf("Unexpected output %q", got)
}
}

View File

@@ -18,8 +18,8 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
@@ -40,11 +40,8 @@ type Resolver struct {
func NewResolver(file string, logger log.Logger, insecure_skip_verify bool) (*Resolver, error) {
flags := map[string]string{}
var fileBytes []byte
url, err := url.ParseRequestURI(file)
if err != nil {
return nil, err
}
if url.Scheme == "http" || url.Scheme == "https" {
var err error
if strings.HasPrefix(file, "http://") || strings.HasPrefix(file, "https://") {
_ = level.Info(logger).Log("msg", fmt.Sprintf("Loading configuration file from URL: %v", file))
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure_skip_verify},

View File

@@ -59,6 +59,7 @@ Name | Description | Type | Labels
`windows_ad_ldap_searches_total` | _Not yet documented_ | counter | None
`windows_ad_ldap_udp_operations_total` | _Not yet documented_ | counter | None
`windows_ad_ldap_writes_total` | _Not yet documented_ | counter | None
`windows_ad_ldap_client_sessions` | This is the number of sessions opened by LDAP clients at the time the data is taken. This is helpful in determining LDAP client activity and if the DC is able to handle the load. Of course, spikes during normal periods of authentication — such as first thing in the morning — are not necessarily a problem, but long sustained periods of high values indicate an overworked DC | gauge | None
`windows_ad_link_values_cleaned_total` | _Not yet documented_ | counter | None
`windows_ad_phantom_objects_cleaned_total` | _Not yet documented_ | counter | None
`windows_ad_phantom_objects_visited_total` | _Not yet documented_ | counter | None

View File

@@ -28,49 +28,39 @@ Name | Description | Type | Labels
`windows_adfs_password_change_succeeded_total` | Total number of succeeded password changes. The Password Change Portal must be enabled in the AD FS Management tool in order to allow user password changes | counter | None
`windows_adfs_token_requests_total` | Total number of requested access tokens | counter | None
`windows_adfs_windows_integrated_authentications_total` | Total number of Windows integrated authentications using Kerberos or NTLM | counter | None
`ad_login_connection_failures_total` | Total number of connection failures to an Active Directory domain controller | counter | None
`certificate_authentications_total` | Total number of User Certificate authentications | counter | None
`device_authentications_total` | Total number of Device authentications | counter | None
`extranet_account_lockouts_total` | Total number of Extranet Account Lockouts | counter | None
`federated_authentications_total` | Total number of authentications from a federated source | counter | None
`passport_authentications_total` | Total number of Microsoft Passport SSO authentications | counter | None
`passive_requests_total` | Total number of passive (browser-based) requests | counter | None
`password_change_failed_total` | Total number of failed password changes | counter | None
`password_change_succeeded_total` | Total number of successful password changes | counter | None
`token_requests_total` | Total number of token requests | counter | None
`windows_integrated_authentications_total` | Total number of Windows integrated authentications (Kerberos/NTLM) | counter | None
`oauth_authorization_requests_total` | Total number of incoming requests to the OAuth Authorization endpoint | counter | None
`oauth_client_authentication_success_total` | Total number of successful OAuth client Authentications | counter | None
`oauth_client_authentication_failure_total` | Total number of failed OAuth client Authentications | counter | None
`oauth_client_credentials_failure_total` | Total number of failed OAuth Client Credentials Requests | counter | None
`oauth_client_credentials_success_total` | Total number of successful RP tokens issued for OAuth Client Credentials Requests | counter | None
`oauth_client_privkey_jwt_authentication_failure_total` | Total number of failed OAuth Client Private Key Jwt Authentications | counter | None
`oauth_client_privkey_jwt_authentications_success_total` | Total number of successful OAuth Client Private Key Jwt Authentications | counter | None
`oauth_client_secret_basic_authentications_failure_total` | Total number of failed OAuth Client Secret Basic Authentications | counter | None
`oauth_client_secret_basic_authentications_success_total` | Total number of successful OAuth Client Secret Basic Authentications | counter | None
`oauth_client_secret_post_authentications_failure_total` | Total number of failed OAuth Client Secret Post Authentications | counter | None
`oauth_client_secret_post_authentications_success_total` | Total number of successful OAuth Client Secret Post Authentications | counter | None
`oauth_client_windows_authentications_failure_total` | Total number of failed OAuth Client Windows Integrated Authentications | counter | None
`oauth_client_windows_authentications_success_total` | Total number of successful OAuth Client Windows Integrated Authentications | counter | None
`oauth_logon_certificate_requests_failure_total` | Total number of failed OAuth Logon Certificate Requests | counter | None
`oauth_logon_certificate_token_requests_success_total` | Total number of successful RP tokens issued for OAuth Logon Certificate Requests | counter | None
`oauth_password_grant_requests_failure_total` | Total number of failed OAuth Password Grant Requests | counter | None
`oauth_password_grant_requests_success_total` | Total number of successful OAuth Password Grant Requests | counter | None
`oauth_token_requests_success_total` | Total number of successful RP tokens issued over OAuth protocol | counter | None
`samlp_token_requests_success_total` | Total number of successful RP tokens issued over SAML-P protocol | counter | None
`sso_authentications_failure_total` | Total number of failed SSO authentications | counter | None
`sso_authentications_success_total` | Total number of successful SSO authentications | counter | None
`wsfed_token_requests_success_total` | Total number of successful RP tokens issued over WS-Fed protocol | counter | None
`wstrust_token_requests_success_total` | Total number of successful RP tokens issued over WS-Trust protocol | counter | None
`userpassword_authentications_failure_total` | Total number of failed AD U/P authentications | counter | None
`userpassword_authentications_success_total` | Total number of successful AD U/P authentications | counter | None
`external_authentications_failure_total` | Total number of failed authentications from external MFA providers | counter | None
`external_authentications_success_total` | Total number of successful authentications from external MFA providers | counter | None
`db_artifact_failure_total` | Total number of failures connecting to the artifact database | counter | None
`db_artifact_query_time_seconds_total` | Accumulator of time taken for an artifact database query | counter | None
`db_config_failure_total` | Total number of failures connecting to the configuration database | counter | None
`db_config_query_time_seconds_total` | Accumulator of time taken for a configuration database query | counter | None
`federation_metadata_requests_total` | Total number of Federation Metadata requests | counter | None
`windows_adfs_passive_requests_total` | Total number of passive (browser-based) requests | counter | None
`windows_adfs_oauth_authorization_requests_total` | Total number of incoming requests to the OAuth Authorization endpoint | counter | None
`windows_adfs_oauth_client_authentication_success_total` | Total number of successful OAuth client Authentications | counter | None
`windows_adfs_oauth_client_authentication_failure_total` | Total number of failed OAuth client Authentications | counter | None
`windows_adfs_oauth_client_credentials_failure_total` | Total number of failed OAuth Client Credentials Requests | counter | None
`windows_adfs_oauth_client_credentials_success_total` | Total number of successful RP tokens issued for OAuth Client Credentials Requests | counter | None
`windows_adfs_oauth_client_privkey_jwt_authentication_failure_total` | Total number of failed OAuth Client Private Key Jwt Authentications | counter | None
`windows_adfs_oauth_client_privkey_jwt_authentications_success_total` | Total number of successful OAuth Client Private Key Jwt Authentications | counter | None
`windows_adfs_oauth_client_secret_basic_authentications_failure_total` | Total number of failed OAuth Client Secret Basic Authentications | counter | None
`windows_adfs_oauth_client_secret_basic_authentications_success_total` | Total number of successful OAuth Client Secret Basic Authentications | counter | None
`windows_adfs_oauth_client_secret_post_authentications_failure_total` | Total number of failed OAuth Client Secret Post Authentications | counter | None
`windows_adfs_oauth_client_secret_post_authentications_success_total` | Total number of successful OAuth Client Secret Post Authentications | counter | None
`windows_adfs_oauth_client_windows_authentications_failure_total` | Total number of failed OAuth Client Windows Integrated Authentications | counter | None
`windows_adfs_oauth_client_windows_authentications_success_total` | Total number of successful OAuth Client Windows Integrated Authentications | counter | None
`windows_adfs_oauth_logon_certificate_requests_failure_total` | Total number of failed OAuth Logon Certificate Requests | counter | None
`windows_adfs_oauth_logon_certificate_token_requests_success_total` | Total number of successful RP tokens issued for OAuth Logon Certificate Requests | counter | None
`windows_adfs_oauth_password_grant_requests_failure_total` | Total number of failed OAuth Password Grant Requests | counter | None
`windows_adfs_oauth_password_grant_requests_success_total` | Total number of successful OAuth Password Grant Requests | counter | None
`windows_adfs_oauth_token_requests_success_total` | Total number of successful RP tokens issued over OAuth protocol | counter | None
`windows_adfs_samlp_token_requests_success_total` | Total number of successful RP tokens issued over SAML-P protocol | counter | None
`windows_adfs_sso_authentications_failure_total` | Total number of failed SSO authentications | counter | None
`windows_adfs_sso_authentications_success_total` | Total number of successful SSO authentications | counter | None
`windows_adfs_wsfed_token_requests_success_total` | Total number of successful RP tokens issued over WS-Fed protocol | counter | None
`windows_adfs_wstrust_token_requests_success_total` | Total number of successful RP tokens issued over WS-Trust protocol | counter | None
`windows_adfs_userpassword_authentications_failure_total` | Total number of failed AD U/P authentications | counter | None
`windows_adfs_userpassword_authentications_success_total` | Total number of successful AD U/P authentications | counter | None
`windows_adfs_external_authentications_failure_total` | Total number of failed authentications from external MFA providers | counter | None
`windows_adfs_external_authentications_success_total` | Total number of successful authentications from external MFA providers | counter | None
`windows_adfs_db_artifact_failure_total` | Total number of failures connecting to the artifact database | counter | None
`windows_adfs_db_artifact_query_time_seconds_total` | Accumulator of time taken for an artifact database query | counter | None
`windows_adfs_db_config_failure_total` | Total number of failures connecting to the configuration database | counter | None
`windows_adfs_db_config_query_time_seconds_total` | Accumulator of time taken for a configuration database query | counter | None
`windows_adfs_federation_metadata_requests_total` | Total number of Federation Metadata requests | counter | None
### Example metric
Show rate of device authentications in AD FS:

View File

@@ -51,9 +51,11 @@ Name | Description | Type | Labels
`windows_hyperv_host_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_remote_run_time` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_total_run_time` | _Not yet documented_ | counter | `core`
`windows_hyperv_host_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `core`
`windows_hyperv_vm_cpu_guest_run_time` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_cpu_hypervisor_run_time` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_cpu_remote_run_time` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_cpu_wait_time_per_dispatch_total` | _Not yet documented_ | counter | `vm`, `core`
`windows_hyperv_vm_memory_added_total` | _Not yet documented_ | counter | `vm`
`windows_hyperv_vm_memory_pressure_average` | _Not yet documented_ | gauge | `vm`
`windows_hyperv_vm_memory_pressure_current` | _Not yet documented_ | counter | `vm`

View File

@@ -0,0 +1,80 @@
# physical_disk collector
The physical_disk collector exposes metrics about physical disks
|||
-|-
Metric name prefix | `physical_disk`
Data source | Perflib
Counters | `physicalDisk` ([`Win32_PerfRawData_PerfDisk_physicalDisk`](https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71)))
Enabled by default? | Yes
## Flags
### `--collector.physical_disk.disk-include`
If given, a disk needs to match the include regexp in order for the corresponding disk metrics to be reported
### `--collector.physical_disk.disk-exclude`
If given, a disk needs to *not* match the exclude regexp in order for the corresponding disk metrics to be reported
## Metrics
Name | Description | Type | Labels
-----|-------------|------|-------
`requests_queued` | Number of requests outstanding on the disk at the time the performance data is collected | gauge | `disk`
`read_bytes_total` | Rate at which bytes are transferred from the disk during read operations | counter | `disk`
`reads_total` | Rate of read operations on the disk | counter | `disk`
`write_bytes_total` | Rate at which bytes are transferred to the disk during write operations | counter | `disk`
`writes_total` | Rate of write operations on the disk | counter | `disk`
`read_seconds_total` | Seconds the disk was busy servicing read requests | counter | `disk`
`write_seconds_total` | Seconds the disk was busy servicing write requests | counter | `disk`
`free_bytes` | Unused space of the disk in bytes (not real time, updates every 10-15 min) | gauge | `disk`
`size_bytes` | Total size of the disk in bytes (not real time, updates every 10-15 min) | gauge | `disk`
`idle_seconds_total` | Seconds the disk was idle (not servicing read/write requests) | counter | `disk`
`split_ios_total` | Number of I/Os to the disk split into multiple I/Os | counter | `disk`
### Warning about size metrics
The `free_bytes` and `size_bytes` metrics are not updated in real time and might have a delay of 10-15min.
This is the same behavior as the windows performance counters.
### Example metric
Query the rate of write operations to a disk
```
rate(windows_physical_disk_read_bytes_total{instance="localhost", disk=~"0"}[2m])
```
## Useful queries
Calculate rate of total IOPS for disk
```
rate(windows_physical_disk_reads_total{instance="localhost", disk=~"0"}[2m]) + rate(windows_physical_disk_writes_total{instance="localhost", disk=~"0"}[2m])
```
## Alerting examples
**prometheus.rules**
```yaml
groups:
- name: Windows Disk Alerts
rules:
# Sends an alert when disk space usage is above 95%
- alert: DiskSpaceUsage
expr: 100.0 - 100 * (windows_physical_disk_free_bytes / windows_physical_disk_size_bytes) > 95
for: 10m
labels:
severity: high
annotations:
summary: "Disk Space Usage (instance {{ $labels.instance }})"
description: "Disk Space on Drive is used more than 95%\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
# Alerts on disks with over 85% space usage predicted to fill within the next four days
- alert: DiskFilling
expr: 100 * (windows_physical_disk_free_bytes / windows_physical_disk_size_bytes) < 15 and predict_linear(windows_physical_disk_free_bytes[6h], 4 * 24 * 3600) < 0
for: 10m
labels:
severity: warning
annotations:
summary: "Disk full in four days (instance {{ $labels.instance }})"
description: "{{ $labels.disk }} is expected to fill up within four days. Currently {{ $value | humanize }}% is available.\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
```

View File

@@ -21,7 +21,7 @@ Name | Description | Type | Labels
`windows_tcp_connections_active_total` | Number of times TCP connections have made a direct transition from the CLOSED state to the SYN-SENT state.| counter | af
`windows_tcp_connections_established` | Number of TCP connections for which the current state is either ESTABLISHED or CLOSE-WAIT. | gauge | af
`windows_tcp_connections_passive_total` | Number of times TCP connections have made a direct transition from the LISTEN state to the SYN-RCVD state. | counter | af
`windows_tcp_connections_reset_total` | Number of times TCP connections have made a direct transition from the LISTEN state to the SYN-RCVD state. | counter | af
`windows_tcp_connections_reset_total` | Connections Reset is the number of times TCP connections have made a direct transition to the CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state. | counter | af
`windows_tcp_segments_total` | Total segments sent or received using the TCP protocol | counter | af
`windows_tcp_segments_received_total` | Total segments received, including those received in error. This count includes segments received on currently established connections | counter | af
`windows_tcp_segments_retransmitted_total` | Total segments retransmitted. That is, segments transmitted that contain one or more previously transmitted bytes | counter | af

View File

@@ -10,15 +10,25 @@ Enabled by default? | Yes
## Flags
### `--collector.textfile.directory`
### `--collector.textfile.directory`
:warning: DEPRECATED Use `--collector.textfile.directories`
The directory containing the files to be ingested. Only files with the extension `.prom` are read. The `.prom` file must end with an empty line feed to work properly.
<br>
### `--collector.textfile.directories`
One or multiple directories containing the files to be ingested.
E.G. `--collector.textfile.directories="C:\MyDir1,C:\MyDir2"`
Default value: `C:\Program Files\windows_exporter\textfile_inputs`
Required: No
## Metrics
> **Note:**
> - If there are duplicated filenames among the directories, only the first one found will be read. For any other files with the same name, the `windows_textfile_scrape_error` metric will be set to 1 and a error message will be logged.
> - Only files with the extension `.prom` are read. The `.prom` file must end with an empty line feed to work properly.
Metrics will primarily come from the files on disk. The below listed metrics
are collected to give information about the reading of the metrics themselves.
@@ -38,7 +48,7 @@ _This collector does not yet have any useful queries added, we would appreciate
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
# Example use
This Powershell script, when run in the `collector.textfile.directory` (default `C:\Program Files\windows_exporter\textfile_inputs`), generates a valid `.prom` file that should successfully ingested by windows_exporter.
This Powershell script, when run in the `--collector.textfile.directories` (default `C:\Program Files\windows_exporter\textfile_inputs`), generates a valid `.prom` file that should successfully ingested by windows_exporter.
```Powershell
$alpha = 42

View File

@@ -49,7 +49,7 @@ type prometheusVersion struct {
}
const (
defaultCollectors = "cpu,cs,logical_disk,net,os,service,system,textfile"
defaultCollectors = "cpu,cs,logical_disk,physical_disk,net,os,service,system,textfile"
defaultCollectorsPlaceholder = "[defaults]"
)

26
go.mod
View File

@@ -3,45 +3,51 @@ module github.com/prometheus-community/windows_exporter
go 1.19
require (
github.com/Microsoft/hcsshim v0.9.8
github.com/Microsoft/hcsshim v0.11.1
github.com/alecthomas/kingpin/v2 v2.3.2
github.com/dimchansky/utfbom v1.1.1
github.com/go-kit/log v0.2.1
github.com/go-ole/go-ole v1.2.6
github.com/go-ole/go-ole v1.3.0
github.com/prometheus/client_golang v1.16.0
github.com/prometheus/client_model v0.4.0
github.com/prometheus/common v0.44.0
github.com/prometheus/exporter-toolkit v0.10.0
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/yusufpapurcu/wmi v1.2.3
go.opencensus.io v0.23.0 // indirect
golang.org/x/sys v0.10.0
go.opencensus.io v0.24.0 // indirect
golang.org/x/sys v0.12.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/Microsoft/go-winio v0.4.17 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/cgroups v1.0.1 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/containerd v1.7.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.8.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.30.0 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.2 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

929
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -32,14 +32,14 @@ loop:
changes <- c.CurrentStatus
case svc.Stop, svc.Shutdown:
_ = logger.Info(100, "Service Stop Received")
s.stopCh <- true
changes <- svc.Status{State: svc.StopPending}
break loop
default:
_ = logger.Error(102, fmt.Sprintf("unexpected control request #%d", c))
}
}
}
changes <- svc.Status{State: svc.StopPending}
s.stopCh <- true
return
}
@@ -48,7 +48,7 @@ var StopCh = make(chan bool)
func init() {
isService, err := svc.IsWindowsService()
if err != nil {
logger, err := eventlog.Open("windows_exporter")
logger, err = eventlog.Open("windows_exporter")
if err != nil {
os.Exit(2)
}
@@ -57,7 +57,7 @@ func init() {
}
if isService {
logger, err := eventlog.Open("windows_exporter")
logger, err = eventlog.Open("windows_exporter")
if err != nil {
os.Exit(2)
}

View File

@@ -52,7 +52,7 @@
<fw:RemoteAddress>[REMOTE_ADDR]</fw:RemoteAddress>
</fw:FirewallException>
</File>
<ServiceInstall Id="InstallExporterService" Name="windows_exporter" DisplayName="windows_exporter" Description="Exports Prometheus metrics about the system" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="--log.format eventlog [CollectorsFlag] [ListenFlagBoth] [ListenFlagAddr] [ListenFlagPort] [MetricsPathFlag] [TextfileDirFlag] [ExtraFlags]">
<ServiceInstall Id="InstallExporterService" Name="windows_exporter" DisplayName="windows_exporter" Description="Exports Prometheus metrics about the system" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="--log.file eventlog [CollectorsFlag] [ListenFlagBoth] [ListenFlagAddr] [ListenFlagPort] [MetricsPathFlag] [TextfileDirFlag] [ExtraFlags]">
<util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" RestartServiceDelayInSeconds="60" />
<ServiceDependency Id="wmiApSrv" />
</ServiceInstall>

View File

@@ -1,3 +1,10 @@
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
labels:
name: monitoring
---
apiVersion: apps/v1
kind: DaemonSet
metadata:

View File

@@ -24,6 +24,7 @@ func (f *AllowedFile) String() string {
// Set updates the value of the allowed format.
func (f *AllowedFile) Set(s string) error {
f.s = s
switch s {
case "stdout":
f.w = os.Stdout
@@ -77,6 +78,8 @@ func New(config *Config) (log.Logger, error) {
return nil, err
}
l = eventlog.NewEventLogLogger(w, loggerFunc)
} else if config.File.w == nil {
panic("logger: file writer is nil")
} else {
l = loggerFunc(log.NewSyncWriter(config.File.w))
}

View File

@@ -40,6 +40,7 @@ test_alpha_total 42
windows_exporter_collector_success{collector="cpu"} 1
windows_exporter_collector_success{collector="cs"} 1
windows_exporter_collector_success{collector="logical_disk"} 1
windows_exporter_collector_success{collector="physical_disk"} 1
windows_exporter_collector_success{collector="net"} 1
windows_exporter_collector_success{collector="os"} 1
windows_exporter_collector_success{collector="service"} 1
@@ -50,6 +51,7 @@ windows_exporter_collector_success{collector="textfile"} 1
windows_exporter_collector_timeout{collector="cpu"} 0
windows_exporter_collector_timeout{collector="cs"} 0
windows_exporter_collector_timeout{collector="logical_disk"} 0
windows_exporter_collector_timeout{collector="physical_disk"} 0
windows_exporter_collector_timeout{collector="net"} 0
windows_exporter_collector_timeout{collector="os"} 0
windows_exporter_collector_timeout{collector="service"} 0
@@ -89,6 +91,30 @@ windows_exporter_collector_timeout{collector="textfile"} 0
# TYPE windows_logical_disk_write_seconds_total counter
# HELP windows_logical_disk_writes_total The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)
# TYPE windows_logical_disk_writes_total counter
# HELP windows_physical_disk_idle_seconds_total Seconds that the disk was idle (PhysicalDisk.PercentIdleTime)
# TYPE windows_physical_disk_idle_seconds_total counter
# HELP windows_physical_disk_read_bytes_total The number of bytes transferred from the disk during read operations (PhysicalDisk.DiskReadBytesPerSec)
# TYPE windows_physical_disk_read_bytes_total counter
# HELP windows_physical_disk_read_latency_seconds_total Shows the average time, in seconds, of a read operation from the disk (PhysicalDisk.AvgDiskSecPerRead)
# TYPE windows_physical_disk_read_latency_seconds_total counter
# HELP windows_physical_disk_read_seconds_total Seconds that the disk was busy servicing read requests (PhysicalDisk.PercentDiskReadTime)
# TYPE windows_physical_disk_read_seconds_total counter
# HELP windows_physical_disk_read_write_latency_seconds_total Shows the time, in seconds, of the average disk transfer (PhysicalDisk.AvgDiskSecPerTransfer)
# TYPE windows_physical_disk_read_write_latency_seconds_total counter
# HELP windows_physical_disk_reads_total The number of read operations on the disk (PhysicalDisk.DiskReadsPerSec)
# TYPE windows_physical_disk_reads_total counter
# HELP windows_physical_disk_requests_queued The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)
# TYPE windows_physical_disk_requests_queued gauge
# HELP windows_physical_disk_split_ios_total The number of I/Os to the disk were split into multiple I/Os (PhysicalDisk.SplitIOPerSec)
# TYPE windows_physical_disk_split_ios_total counter
# HELP windows_physical_disk_write_bytes_total The number of bytes transferred to the disk during write operations (PhysicalDisk.DiskWriteBytesPerSec)
# TYPE windows_physical_disk_write_bytes_total counter
# HELP windows_physical_disk_write_latency_seconds_total Shows the average time, in seconds, of a write operation to the disk (PhysicalDisk.AvgDiskSecPerWrite)
# TYPE windows_physical_disk_write_latency_seconds_total counter
# HELP windows_physical_disk_write_seconds_total Seconds that the disk was busy servicing write requests (PhysicalDisk.PercentDiskWriteTime)
# TYPE windows_physical_disk_write_seconds_total counter
# HELP windows_physical_disk_writes_total The number of write operations on the disk (PhysicalDisk.DiskWritesPerSec)
# TYPE windows_physical_disk_writes_total counter
# HELP windows_net_bytes_received_total (Network.BytesReceivedPerSec)
# TYPE windows_net_bytes_received_total counter
# HELP windows_net_bytes_sent_total (Network.BytesSentPerSec)

View File

@@ -18,7 +18,7 @@ mkdir $textfile_dir | Out-Null
Copy-Item 'e2e-textfile.prom' -Destination "$($textfile_dir)/e2e-textfile.prom"
# Omit dynamic collector information that will change after each run
$skip_re = "^(go_|windows_exporter_build_info|windows_exporter_collector_duration_seconds|windows_exporter_perflib_snapshot_duration_seconds|process_|windows_textfile_mtime_seconds|windows_cpu|windows_cs|windows_logical_disk|windows_net|windows_os|windows_service|windows_system|windows_textfile_mtime_seconds)"
$skip_re = "^(go_|windows_exporter_build_info|windows_exporter_collector_duration_seconds|windows_exporter_perflib_snapshot_duration_seconds|process_|windows_textfile_mtime_seconds|windows_cpu|windows_cs|windows_logical_disk|windows_physical_disk|windows_net|windows_os|windows_service|windows_system|windows_textfile_mtime_seconds)"
# Start process in background, awaiting HTTP requests.
# Use default collectors, port and address: http://localhost:9182/metrics

View File

@@ -0,0 +1,3 @@
# HELP windows_test Some Test
# TYPE windows_test gauge
windows_test{flag="file"} 1

View File

@@ -0,0 +1,3 @@
# HELP windows_test Some Test
# TYPE windows_test gauge
windows_test{flag="sub_file"} 2

View File

@@ -0,0 +1,3 @@
# HELP windows_test Some Test
# TYPE windows_test gauge
windows_test{flag="dir1"} 1

View File

@@ -0,0 +1,3 @@
# HELP windows_test Some Test
# TYPE windows_test gauge
windows_test{flag="dir2"} 2

View File

@@ -0,0 +1,3 @@
# HELP windows_test Some Test
# TYPE windows_test gauge
windows_test{flag="dir3"} 3

View File

@@ -0,0 +1,3 @@
# HELP windows_test Some Test
# TYPE windows_test gauge
windows_test{flag="dir3sub"} 3