windows_exporter/collector/logical_disk.go

392 lines
12 KiB
Go
Raw Normal View History

//go:build windows
// +build windows
package collector
2016-08-27 09:34:27 +00:00
import (
"errors"
2016-08-27 09:34:27 +00:00
"fmt"
"regexp"
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
2016-08-27 09:34:27 +00:00
"github.com/prometheus/client_golang/prometheus"
)
const (
FlagLogicalDiskVolumeOldExclude = "collector.logical_disk.volume-blacklist"
FlagLogicalDiskVolumeOldInclude = "collector.logical_disk.volume-whitelist"
FlagLogicalDiskVolumeExclude = "collector.logical_disk.volume-exclude"
FlagLogicalDiskVolumeInclude = "collector.logical_disk.volume-include"
)
2016-08-27 09:34:27 +00:00
var (
volumeOldInclude *string
volumeOldExclude *string
volumeInclude *string
volumeExclude *string
volumeIncludeSet bool
volumeExcludeSet bool
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 {
logger log.Logger
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
volumeIncludePattern *regexp.Regexp
volumeExcludePattern *regexp.Regexp
2016-08-27 09:34:27 +00:00
}
// newLogicalDiskCollectorFlags ...
func newLogicalDiskCollectorFlags(app *kingpin.Application) {
volumeInclude = app.Flag(
FlagLogicalDiskVolumeInclude,
"Regexp of volumes to include. Volume name must both match include and not match exclude to be included.",
).Default(".+").PreAction(func(c *kingpin.ParseContext) error {
volumeIncludeSet = true
return nil
}).String()
volumeExclude = app.Flag(
FlagLogicalDiskVolumeExclude,
"Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.",
).Default("").PreAction(func(c *kingpin.ParseContext) error {
volumeExcludeSet = true
return nil
}).String()
volumeOldInclude = app.Flag(
FlagLogicalDiskVolumeOldInclude,
"DEPRECATED: Use --collector.logical_disk.volume-include",
).Hidden().String()
volumeOldExclude = app.Flag(
FlagLogicalDiskVolumeOldExclude,
"DEPRECATED: Use --collector.logical_disk.volume-exclude",
).Hidden().String()
}
// newLogicalDiskCollector ...
func newLogicalDiskCollector(logger log.Logger) (Collector, error) {
const subsystem = "logical_disk"
logger = log.With(logger, "collector", subsystem)
if *volumeOldExclude != "" {
if !volumeExcludeSet {
level.Warn(logger).Log("msg", "--collector.logical_disk.volume-blacklist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-exclude")
*volumeExclude = *volumeOldExclude
} else {
return nil, errors.New("--collector.logical_disk.volume-blacklist and --collector.logical_disk.volume-exclude are mutually exclusive")
}
}
if *volumeOldInclude != "" {
if !volumeIncludeSet {
level.Warn(logger).Log("msg", "--collector.logical_disk.volume-whitelist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-include")
*volumeInclude = *volumeOldInclude
} else {
return nil, errors.New("--collector.logical_disk.volume-whitelist and --collector.logical_disk.volume-include are mutually exclusive")
}
}
2016-08-27 09:34:27 +00:00
return &LogicalDiskCollector{
logger: logger,
2016-08-27 09:34:27 +00:00
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,
),
volumeIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeInclude)),
volumeExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeExclude)),
}, 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 {
level.Error(c.logger).Log("failed collecting logical_disk metrics", "desc", desc, "err", 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, c.logger); err != nil {
2016-08-27 09:34:27 +00:00
return nil, err
}
for _, volume := range dst {
if volume.Name == "_Total" ||
c.volumeExcludePattern.MatchString(volume.Name) ||
!c.volumeIncludePattern.MatchString(volume.Name) {
2016-08-27 09:34:27 +00:00
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
}