windows_exporter/collector/logical_disk.go

343 lines
10 KiB
Go
Raw Normal View History

//go:build windows
// +build windows
package collector
2016-08-27 09:34:27 +00:00
import (
"fmt"
"regexp"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/log"
2016-08-27 09:34:27 +00:00
"github.com/prometheus/client_golang/prometheus"
)
const (
FlagLogicalDiskVolumeBlacklist = "collector.logical_disk.volume-blacklist"
FlagLogicalDiskVolumeWhitelist = "collector.logical_disk.volume-whitelist"
)
2016-08-27 09:34:27 +00:00
var (
volumeWhitelist *string
volumeBlacklist *string
2016-08-27 09:34:27 +00:00
)
2019-09-19 12:49:33 +00:00
// A LogicalDiskCollector is a Prometheus collector for perflib logicalDisk metrics
2016-08-27 09:34:27 +00:00
type LogicalDiskCollector struct {
2019-03-26 17:29:17 +00:00
RequestsQueued *prometheus.Desc
AvgReadQueue *prometheus.Desc
AvgWriteQueue *prometheus.Desc
2019-03-26 17:29:17 +00:00
ReadBytesTotal *prometheus.Desc
ReadsTotal *prometheus.Desc
WriteBytesTotal *prometheus.Desc
WritesTotal *prometheus.Desc
ReadTime *prometheus.Desc
WriteTime *prometheus.Desc
TotalSpace *prometheus.Desc
FreeSpace *prometheus.Desc
IdleTime *prometheus.Desc
SplitIOs *prometheus.Desc
ReadLatency *prometheus.Desc
WriteLatency *prometheus.Desc
ReadWriteLatency *prometheus.Desc
2016-08-27 09:34:27 +00:00
volumeWhitelistPattern *regexp.Regexp
volumeBlacklistPattern *regexp.Regexp
}
// newLogicalDiskCollectorFlags ...
func newLogicalDiskCollectorFlags(app *kingpin.Application) {
volumeWhitelist = app.Flag(
FlagLogicalDiskVolumeWhitelist,
"Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.",
).Default(".+").String()
volumeBlacklist = app.Flag(
FlagLogicalDiskVolumeBlacklist,
"Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.",
).Default("").String()
}
// newLogicalDiskCollector ...
func newLogicalDiskCollector() (Collector, error) {
2016-08-27 14:33:23 +00:00
const subsystem = "logical_disk"
2016-08-27 09:34:27 +00:00
return &LogicalDiskCollector{
RequestsQueued: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "requests_queued"),
2016-08-27 09:34:27 +00:00
"The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)",
[]string{"volume"},
nil,
),
AvgReadQueue: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "avg_read_requests_queued"),
"Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)",
[]string{"volume"},
nil,
),
AvgWriteQueue: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "avg_write_requests_queued"),
"Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)",
[]string{"volume"},
nil,
),
2016-08-27 09:34:27 +00:00
ReadBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_bytes_total"),
2016-08-27 09:34:27 +00:00
"The number of bytes transferred from the disk during read operations (LogicalDisk.DiskReadBytesPerSec)",
[]string{"volume"},
nil,
),
ReadsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "reads_total"),
2016-08-27 09:34:27 +00:00
"The number of read operations on the disk (LogicalDisk.DiskReadsPerSec)",
[]string{"volume"},
nil,
),
WriteBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "write_bytes_total"),
2016-08-27 09:34:27 +00:00
"The number of bytes transferred to the disk during write operations (LogicalDisk.DiskWriteBytesPerSec)",
[]string{"volume"},
nil,
),
WritesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "writes_total"),
2016-08-27 09:34:27 +00:00
"The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)",
[]string{"volume"},
nil,
),
ReadTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_seconds_total"),
2016-08-27 09:34:27 +00:00
"Seconds that the disk was busy servicing read requests (LogicalDisk.PercentDiskReadTime)",
[]string{"volume"},
nil,
),
WriteTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "write_seconds_total"),
2016-08-27 09:34:27 +00:00
"Seconds that the disk was busy servicing write requests (LogicalDisk.PercentDiskWriteTime)",
[]string{"volume"},
nil,
),
FreeSpace: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "free_bytes"),
"Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)",
2016-08-27 09:34:27 +00:00
[]string{"volume"},
nil,
),
TotalSpace: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "size_bytes"),
"Total space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)",
2016-08-27 09:34:27 +00:00
[]string{"volume"},
nil,
),
IdleTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "idle_seconds_total"),
2016-08-27 09:34:27 +00:00
"Seconds that the disk was idle (LogicalDisk.PercentIdleTime)",
[]string{"volume"},
nil,
),
SplitIOs: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "split_ios_total"),
2016-08-27 09:34:27 +00:00
"The number of I/Os to the disk were split into multiple I/Os (LogicalDisk.SplitIOPerSec)",
[]string{"volume"},
nil,
),
2019-03-26 17:29:17 +00:00
ReadLatency: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_latency_seconds_total"),
"Shows the average time, in seconds, of a read operation from the disk (LogicalDisk.AvgDiskSecPerRead)",
[]string{"volume"},
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 (LogicalDisk.AvgDiskSecPerWrite)",
[]string{"volume"},
nil,
),
ReadWriteLatency: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_write_latency_seconds_total"),
"Shows the time, in seconds, of the average disk transfer (LogicalDisk.AvgDiskSecPerTransfer)",
[]string{"volume"},
nil,
),
2016-08-27 09:34:27 +00:00
volumeWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeWhitelist)),
volumeBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeBlacklist)),
}, nil
2016-08-27 09:34:27 +00:00
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *LogicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
2019-09-19 12:49:33 +00:00
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting logical_disk metrics:", desc, err)
return err
2016-08-27 09:34:27 +00:00
}
return nil
2016-08-27 09:34:27 +00:00
}
2018-10-04 19:35:33 +00:00
// Win32_PerfRawData_PerfDisk_LogicalDisk docs:
// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class
// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference
2019-09-19 12:49:33 +00:00
type logicalDisk struct {
Name string
CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"`
AvgDiskReadQueueLength float64 `perflib:"Avg. Disk Read Queue Length"`
AvgDiskWriteQueueLength float64 `perflib:"Avg. Disk Write 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"`
PercentFreeSpace float64 `perflib:"% Free Space_Base"`
PercentFreeSpace_Base float64 `perflib:"Free Megabytes"`
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"`
2016-08-27 09:34:27 +00:00
}
2019-09-19 12:49:33 +00:00
func (c *LogicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []logicalDisk
if err := unmarshalObject(ctx.perfObjects["LogicalDisk"], &dst); err != nil {
2016-08-27 09:34:27 +00:00
return nil, err
}
for _, volume := range dst {
if volume.Name == "_Total" ||
c.volumeBlacklistPattern.MatchString(volume.Name) ||
!c.volumeWhitelistPattern.MatchString(volume.Name) {
continue
}
ch <- prometheus.MustNewConstMetric(
c.RequestsQueued,
prometheus.GaugeValue,
2019-09-19 12:49:33 +00:00
volume.CurrentDiskQueueLength,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.AvgReadQueue,
prometheus.GaugeValue,
volume.AvgDiskReadQueueLength*ticksToSecondsScaleFactor,
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.AvgWriteQueue,
prometheus.GaugeValue,
volume.AvgDiskWriteQueueLength*ticksToSecondsScaleFactor,
volume.Name,
)
2016-08-27 09:34:27 +00:00
ch <- prometheus.MustNewConstMetric(
c.ReadBytesTotal,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.DiskReadBytesPerSec,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ReadsTotal,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.DiskReadsPerSec,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.WriteBytesTotal,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.DiskWriteBytesPerSec,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.WritesTotal,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.DiskWritesPerSec,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ReadTime,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.PercentDiskReadTime,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.WriteTime,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.PercentDiskWriteTime,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.FreeSpace,
prometheus.GaugeValue,
2019-09-19 12:49:33 +00:00
volume.PercentFreeSpace_Base*1024*1024,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.TotalSpace,
prometheus.GaugeValue,
2019-09-19 12:49:33 +00:00
volume.PercentFreeSpace*1024*1024,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.IdleTime,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.PercentIdleTime,
2016-08-27 09:34:27 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.SplitIOs,
prometheus.CounterValue,
2019-09-19 12:49:33 +00:00
volume.SplitIOPerSec,
2016-08-27 09:34:27 +00:00
volume.Name,
)
2019-03-26 17:29:17 +00:00
ch <- prometheus.MustNewConstMetric(
c.ReadLatency,
prometheus.CounterValue,
volume.AvgDiskSecPerRead*ticksToSecondsScaleFactor,
2019-03-26 17:29:17 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.WriteLatency,
prometheus.CounterValue,
volume.AvgDiskSecPerWrite*ticksToSecondsScaleFactor,
2019-03-26 17:29:17 +00:00
volume.Name,
)
ch <- prometheus.MustNewConstMetric(
c.ReadWriteLatency,
prometheus.CounterValue,
volume.AvgDiskSecPerTransfer*ticksToSecondsScaleFactor,
2019-03-26 17:29:17 +00:00
volume.Name,
)
2016-08-27 09:34:27 +00:00
}
return nil, nil
}