From 653182a90c41e04c14f4b2f6551a8912a9407658 Mon Sep 17 00:00:00 2001 From: sixfears7 <57415489+6fears7@users.noreply.github.com> Date: Wed, 16 Nov 2022 12:11:10 -0500 Subject: [PATCH 1/9] Added diskdrive collector To retrieve data from Win32_DiskDrive Object Signed-off-by: sixfears7 <57415489+6fears7@users.noreply.github.com> Signed-off-by: pgibbs1 --- diskdrive.go | 203 ++++++++++++++++++++++++++++++++++++++++++++++ diskdrive_test.go | 17 ++++ 2 files changed, 220 insertions(+) create mode 100644 diskdrive.go create mode 100644 diskdrive_test.go diff --git a/diskdrive.go b/diskdrive.go new file mode 100644 index 00000000..fa6749a7 --- /dev/null +++ b/diskdrive.go @@ -0,0 +1,203 @@ +//go:build windows +// +build windows + +package collector + +import ( + "errors" + "strings" + + "github.com/StackExchange/wmi" + "github.com/prometheus-community/windows_exporter/log" + "github.com/prometheus/client_golang/prometheus" +) + +func init() { + registerCollector("disk_drive", newDiskDriveInfoCollector) +} + +const ( + win32DiskQuery = "SELECT DeviceID, Model, Caption, Partitions, Size, Status, Availability FROM WIN32_DiskDrive" +) + +// A DiskDriveInfoCollector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive +type DiskDriveInfoCollector struct { + DiskInfo *prometheus.Desc + Status *prometheus.Desc + Size *prometheus.Desc + Partitions *prometheus.Desc + Availability *prometheus.Desc +} + +func newDiskDriveInfoCollector() (Collector, error) { + const subsystem = "disk_drive" + + return &DiskDriveInfoCollector{ + DiskInfo: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "info"), + "General drive information", + []string{ + "device_id", + "model", + "caption", + }, + nil, + ), + + Status: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "status"), + "Status of the drive", + []string{ + "name", "status"}, + nil, + ), + + Size: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "size"), + "Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector.", + nil, + nil, + ), + + Partitions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "partitions"), + "Number of partitions", + nil, + nil, + ), + + Availability: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availability"), + "Availability Status", + []string{ + "name", "availability"}, + nil, + ), + }, nil +} + +type Win32_DiskDrive struct { + DeviceID string + Model string + Size uint64 + Caption string + Partitions uint32 + Status string + Availability uint16 +} + +var ( + allDiskStatus = []string{ + "OK", + "Error", + "Degraded", + "Unknown", + "Pred fail", + "Starting", + "Stopping", + "Service", + "Stressed", + "Nonrecover", + "No Contact", + "Lost Comm", + } + + availMap = map[int]string{ + + 1: "Other", + 2: "Unknown", + 3: "Running / Full Power", + 4: "Warning", + 5: "In Test", + 6: "Not Applicable", + 7: "Power Off", + 8: "Off line", + 9: "Off Duty", + 10: "Degraded", + 11: "Not Installed", + 12: "Install Error", + 13: "Power Save - Unknown", + 14: "Power Save - Low Power Mode", + 15: "Power Save - Standby", + 16: "Power Cycle", + 17: "Power Save - Warning", + 18: "Paused", + 19: "Not Ready", + 20: "Not Configured", + 21: "Quiesced", + } +) + +// Collect sends the metric values for each metric to the provided prometheus Metric channel. +func (c *DiskDriveInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting disk_drive_info metrics:", desc, err) + return err + } + return nil +} + +func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_DiskDrive + + if err := wmi.Query(win32DiskQuery, &dst); err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + for _, processor := range dst { + ch <- prometheus.MustNewConstMetric( + c.DiskInfo, + prometheus.GaugeValue, + 1.0, + strings.TrimRight(processor.DeviceID, " "), + strings.TrimRight(processor.Model, " "), + strings.TrimRight(processor.Caption, " "), + ) + + for _, status := range allDiskStatus { + isCurrentState := 0.0 + if status == processor.Status { + isCurrentState = 1.0 + } + + ch <- prometheus.MustNewConstMetric( + c.Status, + prometheus.GaugeValue, + isCurrentState, + strings.TrimRight(processor.Model, " "), + status, + ) + } + + ch <- prometheus.MustNewConstMetric( + c.Size, + prometheus.CounterValue, + float64(dst[0].Size), + ) + + ch <- prometheus.MustNewConstMetric( + c.Partitions, + prometheus.CounterValue, + float64(dst[0].Partitions), + ) + + for availNum, val := range availMap { + isCurrentState := 0.0 + if availNum == int(processor.Availability) { + isCurrentState = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.Availability, + prometheus.GaugeValue, + isCurrentState, + strings.TrimRight(processor.Model, " "), + val, + ) + } + } + + return nil, nil +} diff --git a/diskdrive_test.go b/diskdrive_test.go new file mode 100644 index 00000000..2bd1466b --- /dev/null +++ b/diskdrive_test.go @@ -0,0 +1,17 @@ +package collector + +import ( + "testing" +) + +func BenchmarkDiskDriveCollector(b *testing.B) { + benchmarkCollector(b, "disk_drive", newDiskDriveInfoCollector) +} + +// goos: windows +// goarch: amd64 +// pkg: github.com/prometheus-community/windows_exporter/collector +// cpu: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz +// BenchmarkDiskDriveCollector-8 1 1334272800 ns/op 41182008 B/op 125688 allocs/op +// PASS +// ok github.com/prometheus-community/windows_exporter/collector 4.943s From f24fc07ac49257493500c160a7a535cebde3995b Mon Sep 17 00:00:00 2001 From: pgibbs1 Date: Wed, 16 Nov 2022 12:12:28 -0500 Subject: [PATCH 2/9] Fixed moved files Signed-off-by: pgibbs1 --- diskdrive.go => collector/diskdrive.go | 0 diskdrive_test.go => collector/diskdrive_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename diskdrive.go => collector/diskdrive.go (100%) rename diskdrive_test.go => collector/diskdrive_test.go (100%) diff --git a/diskdrive.go b/collector/diskdrive.go similarity index 100% rename from diskdrive.go rename to collector/diskdrive.go diff --git a/diskdrive_test.go b/collector/diskdrive_test.go similarity index 100% rename from diskdrive_test.go rename to collector/diskdrive_test.go From 6912c5b1e79294f44057cc6a4357e00fef20102a Mon Sep 17 00:00:00 2001 From: pgibbs1 Date: Wed, 16 Nov 2022 12:14:05 -0500 Subject: [PATCH 3/9] Removed commented benchmark Signed-off-by: pgibbs1 --- collector/diskdrive_test.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/collector/diskdrive_test.go b/collector/diskdrive_test.go index 2bd1466b..933e4e37 100644 --- a/collector/diskdrive_test.go +++ b/collector/diskdrive_test.go @@ -7,11 +7,3 @@ import ( func BenchmarkDiskDriveCollector(b *testing.B) { benchmarkCollector(b, "disk_drive", newDiskDriveInfoCollector) } - -// goos: windows -// goarch: amd64 -// pkg: github.com/prometheus-community/windows_exporter/collector -// cpu: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz -// BenchmarkDiskDriveCollector-8 1 1334272800 ns/op 41182008 B/op 125688 allocs/op -// PASS -// ok github.com/prometheus-community/windows_exporter/collector 4.943s From 9a2ef3fca87b8d48e9002b6f2213ce3a0c9d8c49 Mon Sep 17 00:00:00 2001 From: pgibbs1 Date: Wed, 16 Nov 2022 12:50:42 -0500 Subject: [PATCH 4/9] Fixed blackslashes, replaced model with name Signed-off-by: pgibbs1 --- collector/diskdrive.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/collector/diskdrive.go b/collector/diskdrive.go index fa6749a7..10f1f9dc 100644 --- a/collector/diskdrive.go +++ b/collector/diskdrive.go @@ -17,7 +17,7 @@ func init() { } const ( - win32DiskQuery = "SELECT DeviceID, Model, Caption, Partitions, Size, Status, Availability FROM WIN32_DiskDrive" + win32DiskQuery = "SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive" ) // A DiskDriveInfoCollector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive @@ -40,6 +40,7 @@ func newDiskDriveInfoCollector() (Collector, error) { "device_id", "model", "caption", + "name", }, nil, ), @@ -80,6 +81,7 @@ type Win32_DiskDrive struct { DeviceID string Model string Size uint64 + Name string Caption string Partitions uint32 Status string @@ -152,9 +154,10 @@ func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*promethe c.DiskInfo, prometheus.GaugeValue, 1.0, - strings.TrimRight(processor.DeviceID, " "), + strings.Trim(processor.DeviceID, "\\.\\"), strings.TrimRight(processor.Model, " "), strings.TrimRight(processor.Caption, " "), + strings.TrimRight(processor.Name, "\\.\\"), ) for _, status := range allDiskStatus { @@ -167,7 +170,7 @@ func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*promethe c.Status, prometheus.GaugeValue, isCurrentState, - strings.TrimRight(processor.Model, " "), + strings.Trim(processor.Name, "\\.\\"), status, ) } @@ -193,7 +196,7 @@ func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*promethe c.Availability, prometheus.GaugeValue, isCurrentState, - strings.TrimRight(processor.Model, " "), + strings.Trim(processor.Name, "\\.\\"), val, ) } From 586152a4adc229220f00e66af5e49b1e7ce92190 Mon Sep 17 00:00:00 2001 From: sixfears7 <57415489+6fears7@users.noreply.github.com> Date: Fri, 18 Nov 2022 14:57:21 -0500 Subject: [PATCH 5/9] Updated code to add label to size and partition Signed-off-by: sixfears7 <57415489+6fears7@users.noreply.github.com> Signed-off-by: pgibbs1 --- collector/diskdrive.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/collector/diskdrive.go b/collector/diskdrive.go index 10f1f9dc..3498fa38 100644 --- a/collector/diskdrive.go +++ b/collector/diskdrive.go @@ -56,14 +56,14 @@ func newDiskDriveInfoCollector() (Collector, error) { Size: prometheus.NewDesc( prometheus.BuildFQName(Namespace, subsystem, "size"), "Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector.", - nil, + []string{"name"}, nil, ), Partitions: prometheus.NewDesc( prometheus.BuildFQName(Namespace, subsystem, "partitions"), "Number of partitions", - nil, + []string{"name"}, nil, ), @@ -178,13 +178,15 @@ func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*promethe ch <- prometheus.MustNewConstMetric( c.Size, prometheus.CounterValue, - float64(dst[0].Size), + float64(processor.Size), + strings.Trim(processor.Name, "\\.\\"), ) ch <- prometheus.MustNewConstMetric( c.Partitions, prometheus.CounterValue, - float64(dst[0].Partitions), + float64(processor.Partitions), + strings.Trim(processor.Name, "\\.\\"), ) for availNum, val := range availMap { From f2f9f624b5d771314501c1220c3ed720fd1e3288 Mon Sep 17 00:00:00 2001 From: sixfears7 <57415489+6fears7@users.noreply.github.com> Date: Fri, 18 Nov 2022 15:01:46 -0500 Subject: [PATCH 6/9] Updated naming convention, fixed metric type Signed-off-by: sixfears7 <57415489+6fears7@users.noreply.github.com> Signed-off-by: pgibbs1 --- collector/diskdrive.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/collector/diskdrive.go b/collector/diskdrive.go index 3498fa38..451a5904 100644 --- a/collector/diskdrive.go +++ b/collector/diskdrive.go @@ -149,20 +149,20 @@ func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*promethe return nil, errors.New("WMI query returned empty result set") } - for _, processor := range dst { + for _, disk := range dst { ch <- prometheus.MustNewConstMetric( c.DiskInfo, prometheus.GaugeValue, 1.0, - strings.Trim(processor.DeviceID, "\\.\\"), - strings.TrimRight(processor.Model, " "), - strings.TrimRight(processor.Caption, " "), - strings.TrimRight(processor.Name, "\\.\\"), + strings.Trim(disk.DeviceID, "\\.\\"), + strings.TrimRight(disk.Model, " "), + strings.TrimRight(disk.Caption, " "), + strings.TrimRight(disk.Name, "\\.\\"), ) for _, status := range allDiskStatus { isCurrentState := 0.0 - if status == processor.Status { + if status == disk.Status { isCurrentState = 1.0 } @@ -170,35 +170,35 @@ func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*promethe c.Status, prometheus.GaugeValue, isCurrentState, - strings.Trim(processor.Name, "\\.\\"), + strings.Trim(disk.Name, "\\.\\"), status, ) } ch <- prometheus.MustNewConstMetric( c.Size, - prometheus.CounterValue, - float64(processor.Size), - strings.Trim(processor.Name, "\\.\\"), + prometheus.GaugeValue, + float64(disk.Size), + strings.Trim(disk.Name, "\\.\\"), ) ch <- prometheus.MustNewConstMetric( c.Partitions, - prometheus.CounterValue, - float64(processor.Partitions), - strings.Trim(processor.Name, "\\.\\"), + prometheus.GaugeValue, + float64(disk.Partitions), + strings.Trim(disk.Name, "\\.\\"), ) for availNum, val := range availMap { isCurrentState := 0.0 - if availNum == int(processor.Availability) { + if availNum == int(disk.Availability) { isCurrentState = 1.0 } ch <- prometheus.MustNewConstMetric( c.Availability, prometheus.GaugeValue, isCurrentState, - strings.Trim(processor.Name, "\\.\\"), + strings.Trim(disk.Name, "\\.\\"), val, ) } From 27977e373085746af6de7515566c15b63c62b281 Mon Sep 17 00:00:00 2001 From: pgibbs1 Date: Tue, 10 Jan 2023 13:50:34 -0500 Subject: [PATCH 7/9] Added collector docs, entry to readme Signed-off-by: pgibbs1 --- docs/README.md | 1 + docs/collector.diskdrive.md | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 docs/collector.diskdrive.md diff --git a/docs/README.md b/docs/README.md index 7f53c93d..67b67d43 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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) +- [`diskdrive`](collector.diskdrive.md)] - [`dfsr`](collector.dfsr.md) - [`dhcp`](collector.dhcp.md) - [`dns`](collector.dns.md) diff --git a/docs/collector.diskdrive.md b/docs/collector.diskdrive.md new file mode 100644 index 00000000..60a95c44 --- /dev/null +++ b/docs/collector.diskdrive.md @@ -0,0 +1,41 @@ +# diskdrive collector + +The diskdrive collector exposes metrics about logical disks (in contrast to physical disks) + +| | | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Metric name prefix | `diskdrive` | +| Classes | [`Win32_PerfRawData_DNS_DNS`] (https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive) | +| Enabled by default? | No | + +## Flags + +None + +## Metrics + +| Name | Description | Type | Labels | +| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | +| `disk_drive_info` | General identifiable information about the disk drive | gauge | None | +| `disk_drive_availability` | Power-related | counter | None | +| `disk_drive_partitions` | Number of paritions on the drive | gauge | None | +| `disk_drive_size` | Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector. | gauge | None | +| `disk_drive_status` | Operational status of the drive | counter | None | + +## Alerting examples +**prometheus.rules** +```yaml +groups: +- name: Windows Disk Alerts + rules: + + # Sends an alert when disk space usage is above 95% + - alert: Drive_Status + expr: windows_disk_drive_status{status="OK"} != 1 + for: 10m + labels: + severity: high + annotations: + summary: "Instance: {{ $labels.instance }} has drive status: {{ $labels.status }} on disk {{ $labels.name }}" + description: "Drive Status Unhealthy" +``` From b0844b9118c33bf0521c0e2635f31fba9f4d5470 Mon Sep 17 00:00:00 2001 From: pgibbs1 Date: Tue, 10 Jan 2023 14:00:55 -0500 Subject: [PATCH 8/9] Fixed linting md Signed-off-by: pgibbs1 --- docs/collector.diskdrive.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/collector.diskdrive.md b/docs/collector.diskdrive.md index 60a95c44..ad5de754 100644 --- a/docs/collector.diskdrive.md +++ b/docs/collector.diskdrive.md @@ -17,8 +17,8 @@ None | Name | Description | Type | Labels | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | | `disk_drive_info` | General identifiable information about the disk drive | gauge | None | -| `disk_drive_availability` | Power-related | counter | None | -| `disk_drive_partitions` | Number of paritions on the drive | gauge | None | +| `disk_drive_availability` | The disk drive's current availability | counter | None | +| `disk_drive_partitions` | Number of partitions on the drive | gauge | None | | `disk_drive_size` | Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector. | gauge | None | | `disk_drive_status` | Operational status of the drive | counter | None | From da2707c5946b9853d42037f064dd3cd63244c629 Mon Sep 17 00:00:00 2001 From: pgibbs1 Date: Tue, 10 Jan 2023 14:03:30 -0500 Subject: [PATCH 9/9] Removed placeholder text Signed-off-by: pgibbs1 --- docs/collector.diskdrive.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/collector.diskdrive.md b/docs/collector.diskdrive.md index ad5de754..3dacd9ad 100644 --- a/docs/collector.diskdrive.md +++ b/docs/collector.diskdrive.md @@ -1,6 +1,6 @@ # diskdrive collector -The diskdrive collector exposes metrics about logical disks (in contrast to physical disks) +The diskdrive collector exposes metrics about physical disks | | | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |