2022-11-16 17:11:10 +00:00
//go:build windows
2023-11-04 19:51:35 +00:00
package diskdrive
2022-11-16 17:11:10 +00:00
import (
"errors"
"strings"
2023-11-04 19:51:35 +00:00
"github.com/alecthomas/kingpin/v2"
2023-04-22 10:17:51 +00:00
"github.com/go-kit/log"
"github.com/go-kit/log/level"
2023-11-04 19:51:35 +00:00
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus-community/windows_exporter/pkg/wmi"
2022-11-16 17:11:10 +00:00
"github.com/prometheus/client_golang/prometheus"
)
const (
2023-11-04 19:51:35 +00:00
Name = "diskdrive"
2022-11-16 17:50:42 +00:00
win32DiskQuery = "SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive"
2022-11-16 17:11:10 +00:00
)
2023-11-04 19:51:35 +00:00
type Config struct { }
var ConfigDefaults = Config { }
// A collector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive
type collector struct {
2023-04-22 10:17:51 +00:00
logger log . Logger
2022-11-16 17:11:10 +00:00
DiskInfo * prometheus . Desc
Status * prometheus . Desc
Size * prometheus . Desc
Partitions * prometheus . Desc
Availability * prometheus . Desc
}
2023-11-04 19:51:35 +00:00
func New ( logger log . Logger , _ * Config ) types . Collector {
c := & collector { }
c . SetLogger ( logger )
return c
}
func NewWithFlags ( _ * kingpin . Application ) types . Collector {
return & collector { }
}
func ( c * collector ) GetName ( ) string {
return Name
}
func ( c * collector ) SetLogger ( logger log . Logger ) {
c . logger = log . With ( logger , "collector" , Name )
}
func ( c * collector ) GetPerfCounter ( ) ( [ ] string , error ) {
return [ ] string { } , nil
}
func ( c * collector ) Build ( ) error {
c . DiskInfo = prometheus . NewDesc (
prometheus . BuildFQName ( types . Namespace , Name , "info" ) ,
"General drive information" ,
[ ] string {
"device_id" ,
"model" ,
"caption" ,
"name" ,
} ,
nil ,
)
c . Status = prometheus . NewDesc (
prometheus . BuildFQName ( types . Namespace , Name , "status" ) ,
"Status of the drive" ,
[ ] string { "name" , "status" } ,
nil ,
)
c . Size = prometheus . NewDesc (
prometheus . BuildFQName ( types . Namespace , Name , "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." ,
[ ] string { "name" } ,
nil ,
)
c . Partitions = prometheus . NewDesc (
prometheus . BuildFQName ( types . Namespace , Name , "partitions" ) ,
"Number of partitions" ,
[ ] string { "name" } ,
nil ,
)
c . Availability = prometheus . NewDesc (
prometheus . BuildFQName ( types . Namespace , Name , "availability" ) ,
"Availability Status" ,
[ ] string { "name" , "availability" } ,
nil ,
)
return nil
2022-11-16 17:11:10 +00:00
}
type Win32_DiskDrive struct {
DeviceID string
Model string
Size uint64
2022-11-16 17:50:42 +00:00
Name string
2022-11-16 17:11:10 +00:00
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.
2023-11-04 19:51:35 +00:00
func ( c * collector ) Collect ( _ * types . ScrapeContext , ch chan <- prometheus . Metric ) error {
2022-11-16 17:11:10 +00:00
if desc , err := c . collect ( ch ) ; err != nil {
2023-06-08 00:29:50 +00:00
_ = level . Error ( c . logger ) . Log ( "msg" , "failed collecting disk_drive_info metrics" , "desc" , desc , "err" , err )
2022-11-16 17:11:10 +00:00
return err
}
return nil
}
2023-11-04 19:51:35 +00:00
func ( c * collector ) collect ( ch chan <- prometheus . Metric ) ( * prometheus . Desc , error ) {
2022-11-16 17:11:10 +00:00
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" )
}
2022-11-18 20:01:46 +00:00
for _ , disk := range dst {
2022-11-16 17:11:10 +00:00
ch <- prometheus . MustNewConstMetric (
c . DiskInfo ,
prometheus . GaugeValue ,
1.0 ,
2022-11-18 20:01:46 +00:00
strings . Trim ( disk . DeviceID , "\\.\\" ) ,
strings . TrimRight ( disk . Model , " " ) ,
strings . TrimRight ( disk . Caption , " " ) ,
strings . TrimRight ( disk . Name , "\\.\\" ) ,
2022-11-16 17:11:10 +00:00
)
for _ , status := range allDiskStatus {
isCurrentState := 0.0
2022-11-18 20:01:46 +00:00
if status == disk . Status {
2022-11-16 17:11:10 +00:00
isCurrentState = 1.0
}
ch <- prometheus . MustNewConstMetric (
c . Status ,
prometheus . GaugeValue ,
isCurrentState ,
2022-11-18 20:01:46 +00:00
strings . Trim ( disk . Name , "\\.\\" ) ,
2022-11-16 17:11:10 +00:00
status ,
)
}
ch <- prometheus . MustNewConstMetric (
c . Size ,
2022-11-18 20:01:46 +00:00
prometheus . GaugeValue ,
float64 ( disk . Size ) ,
strings . Trim ( disk . Name , "\\.\\" ) ,
2022-11-16 17:11:10 +00:00
)
ch <- prometheus . MustNewConstMetric (
c . Partitions ,
2022-11-18 20:01:46 +00:00
prometheus . GaugeValue ,
float64 ( disk . Partitions ) ,
strings . Trim ( disk . Name , "\\.\\" ) ,
2022-11-16 17:11:10 +00:00
)
for availNum , val := range availMap {
isCurrentState := 0.0
2022-11-18 20:01:46 +00:00
if availNum == int ( disk . Availability ) {
2022-11-16 17:11:10 +00:00
isCurrentState = 1.0
}
ch <- prometheus . MustNewConstMetric (
c . Availability ,
prometheus . GaugeValue ,
isCurrentState ,
2022-11-18 20:01:46 +00:00
strings . Trim ( disk . Name , "\\.\\" ) ,
2022-11-16 17:11:10 +00:00
val ,
)
}
}
return nil , nil
}