Clean up code around Prometheus metrics, more DRY.

With this change, all definitions and functionality for a given metric
are in a single place only instead of being distributed all over the
file. This makes it easier to inspect the code for correctness and
adding/changing metrics.
This commit is contained in:
Julius Volz 2015-03-13 00:00:21 +01:00 committed by Julius Volz
parent b28b26ca30
commit fa17966229

View File

@ -23,61 +23,52 @@ import (
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
// This will usually be manager.Manager, but can be swapped out for testing.
type subcontainersInfoProvider interface { type subcontainersInfoProvider interface {
// Get information about all subcontainers of the specified container (includes self). // Get information about all subcontainers of the specified container (includes self).
SubcontainersInfo(containerName string, query *info.ContainerInfoRequest) ([]*info.ContainerInfo, error) SubcontainersInfo(containerName string, query *info.ContainerInfoRequest) ([]*info.ContainerInfo, error)
} }
type prometheusMetric struct { // metricValue describes a single metric value for a given set of label values
valueType prometheus.ValueType // within a parent containerMetric.
type metricValue struct {
value float64 value float64
labels []string labels []string
} }
type metricValues []metricValue
// fsValues is a helper method for assembling per-filesystem stats.
func fsValues(fsStats []info.FsStats, valueFn func(*info.FsStats) float64) metricValues {
values := make(metricValues, 0, len(fsStats))
for _, stat := range fsStats {
values = append(values, metricValue{
value: valueFn(&stat),
labels: []string{stat.Device},
})
}
return values
}
// A containerMetric describes a multi-dimensional metric used for exposing
// a certain type of container statistic.
type containerMetric struct {
name string
help string
valueType prometheus.ValueType
extraLabels []string
getValues func(s *info.ContainerStats) metricValues
}
func (cm *containerMetric) desc() *prometheus.Desc {
return prometheus.NewDesc(cm.name, cm.help, append([]string{"name", "id"}, cm.extraLabels...), nil)
}
// PrometheusCollector implements prometheus.Collector. // PrometheusCollector implements prometheus.Collector.
type PrometheusCollector struct { type PrometheusCollector struct {
infoProvider subcontainersInfoProvider infoProvider subcontainersInfoProvider
errors prometheus.Gauge errors prometheus.Gauge
lastSeen *prometheus.Desc containerMetrics []containerMetric
cpuUsageUserSeconds *prometheus.Desc
cpuUsageSystemSeconds *prometheus.Desc
cpuUsageSecondsPerCPU *prometheus.Desc
memoryUsageBytes *prometheus.Desc
memoryWorkingSet *prometheus.Desc
memoryFailures *prometheus.Desc
fsLimit *prometheus.Desc
fsUsage *prometheus.Desc
fsReads *prometheus.Desc
fsReadsSectors *prometheus.Desc
fsReadsMerged *prometheus.Desc
fsReadTime *prometheus.Desc
fsWrites *prometheus.Desc
fsWritesSectors *prometheus.Desc
fsWritesMerged *prometheus.Desc
fsWriteTime *prometheus.Desc
fsIoInProgress *prometheus.Desc
fsIoTime *prometheus.Desc
fsWeightedIoTime *prometheus.Desc
networkRxBytes *prometheus.Desc
networkRxPackets *prometheus.Desc
networkRxErrors *prometheus.Desc
networkRxDropped *prometheus.Desc
networkTxBytes *prometheus.Desc
networkTxPackets *prometheus.Desc
networkTxErrors *prometheus.Desc
networkTxDropped *prometheus.Desc
tasks *prometheus.Desc
descs []*prometheus.Desc
} }
// NewPrometheusCollector returns a new PrometheusCollector. // NewPrometheusCollector returns a new PrometheusCollector.
@ -89,188 +80,299 @@ func NewPrometheusCollector(infoProvider subcontainersInfoProvider) *PrometheusC
Name: "scrape_error", Name: "scrape_error",
Help: "1 if there was an error while getting container metrics, 0 otherwise", Help: "1 if there was an error while getting container metrics, 0 otherwise",
}), }),
lastSeen: prometheus.NewDesc( containerMetrics: []containerMetric{
"container_last_seen", {
"Last time a container was seen by the exporter", name: "container_last_seen",
[]string{"name", "id"}, help: "Last time a container was seen by the exporter",
nil), valueType: prometheus.GaugeValue,
cpuUsageUserSeconds: prometheus.NewDesc( getValues: func(s *info.ContainerStats) metricValues {
"container_cpu_user_seconds_total", return metricValues{{value: float64(time.Now().Unix())}}
"Cumulative user cpu time consumed in seconds.", },
[]string{"name", "id"}, }, {
nil), name: "container_cpu_user_seconds_total",
cpuUsageSystemSeconds: prometheus.NewDesc( help: "Cumulative user cpu time consumed in seconds.",
"container_cpu_system_seconds_total", valueType: prometheus.CounterValue,
"Cumulative system cpu time consumed in seconds.", getValues: func(s *info.ContainerStats) metricValues {
[]string{"name", "id"}, return metricValues{{value: float64(s.Cpu.Usage.User) / float64(time.Second)}}
nil), },
cpuUsageSecondsPerCPU: prometheus.NewDesc( }, {
"container_cpu_usage_seconds_total", name: "container_cpu_system_seconds_total",
"Cumulative cpu time consumed per cpu in seconds.", help: "Cumulative system cpu time consumed in seconds.",
[]string{"name", "id", "cpu"}, valueType: prometheus.CounterValue,
nil), getValues: func(s *info.ContainerStats) metricValues {
memoryUsageBytes: prometheus.NewDesc( return metricValues{{value: float64(s.Cpu.Usage.System) / float64(time.Second)}}
"container_memory_usage_bytes", },
"Current memory usage in bytes.", }, {
[]string{"name", "id"}, name: "container_cpu_usage_seconds_total",
nil), help: "Cumulative cpu time consumed per cpu in seconds.",
memoryWorkingSet: prometheus.NewDesc( valueType: prometheus.CounterValue,
"container_memory_working_set_bytes", extraLabels: []string{"cpu"},
"Current working set in bytes.", getValues: func(s *info.ContainerStats) metricValues {
[]string{"name", "id"}, values := make(metricValues, 0, len(s.Cpu.Usage.PerCpu))
nil), for i, value := range s.Cpu.Usage.PerCpu {
memoryFailures: prometheus.NewDesc( values = append(values, metricValue{
"container_memory_failures_total", value: float64(value) / float64(time.Second),
"Cumulative count of memory allocation failures.", labels: []string{fmt.Sprintf("cpu%02d", i)},
[]string{"type", "scope", "name", "id"}, })
nil),
fsLimit: prometheus.NewDesc(
"container_fs_limit_bytes",
"Number of bytes that can be consumed by the container on this filesystem.",
[]string{"name", "id", "device"},
nil),
fsUsage: prometheus.NewDesc(
"container_fs_usage_bytes",
"Number of bytes that are consumed by the container on this filesystem.",
[]string{"name", "id", "device"},
nil),
fsReads: prometheus.NewDesc(
"container_fs_reads_total",
"Cumulative count of reads completed",
[]string{"name", "id", "device"},
nil),
fsReadsSectors: prometheus.NewDesc(
"container_fs_sector_reads_total",
"Cumulative count of sector reads completed",
[]string{"name", "id", "device"},
nil),
fsReadsMerged: prometheus.NewDesc(
"container_fs_reads_merged_total",
"Cumulative count of reads merged",
[]string{"name", "id", "device"},
nil),
fsReadTime: prometheus.NewDesc(
"container_fs_read_seconds_total",
"Cumulative count of seconds spent reading",
[]string{"name", "id", "device"},
nil),
fsWrites: prometheus.NewDesc(
"container_fs_writes_total",
"Cumulative count of writes completed",
[]string{"name", "id", "device"},
nil),
fsWritesSectors: prometheus.NewDesc(
"container_fs_sector_writes_total",
"Cumulative count of sector writes completed",
[]string{"name", "id", "device"},
nil),
fsWritesMerged: prometheus.NewDesc(
"container_fs_writes_merged_total",
"Cumulative count of writes merged",
[]string{"name", "id", "device"},
nil),
fsWriteTime: prometheus.NewDesc(
"container_fs_write_seconds_total",
"Cumulative count of seconds spent writing",
[]string{"name", "id", "device"},
nil),
fsIoInProgress: prometheus.NewDesc(
"container_fs_io_current",
"Number of I/Os currently in progress",
[]string{"name", "id", "device"},
nil),
fsIoTime: prometheus.NewDesc(
"container_fs_io_time_seconds_total",
"Cumulative count of seconds spent doing I/Os",
[]string{"name", "id", "device"},
nil),
fsWeightedIoTime: prometheus.NewDesc(
"container_fs_io_time_weighted_seconds_total",
"Cumulative weighted I/O time in seconds",
[]string{"name", "id", "device"},
nil),
networkRxBytes: prometheus.NewDesc(
"container_network_receive_bytes_total",
"Cumulative count of bytes received",
[]string{"name", "id"},
nil),
networkRxPackets: prometheus.NewDesc(
"container_network_receive_packets_total",
"Cumulative count of packets received",
[]string{"name", "id"},
nil),
networkRxDropped: prometheus.NewDesc(
"container_network_receive_packets_dropped_total",
"Cumulative count of packets dropped while receiving",
[]string{"name", "id"},
nil),
networkRxErrors: prometheus.NewDesc(
"container_network_receive_errors_total",
"Cumulative count of errors encountered while receiving",
[]string{"name", "id"},
nil),
networkTxBytes: prometheus.NewDesc(
"container_network_transmit_bytes_total",
"Cumulative count of bytes transmitted",
[]string{"name", "id"},
nil),
networkTxPackets: prometheus.NewDesc(
"container_network_transmit_packets_total",
"Cumulative count of packets transmitted",
[]string{"name", "id"},
nil),
networkTxDropped: prometheus.NewDesc(
"container_network_transmit_packets_dropped_total",
"Cumulative count of packets dropped while transmitting",
[]string{"name", "id"},
nil),
networkTxErrors: prometheus.NewDesc(
"container_network_transmit_errors_total",
"Cumulative count of errors encountered while transmitting",
[]string{"name", "id"},
nil),
tasks: prometheus.NewDesc(
"container_tasks_state",
"Number of tasks in given state",
[]string{"state", "name", "id"},
nil),
} }
c.descs = []*prometheus.Desc{ return values
c.lastSeen, },
}, {
c.cpuUsageUserSeconds, name: "container_memory_usage_bytes",
c.cpuUsageSystemSeconds, help: "Current memory usage in bytes.",
valueType: prometheus.GaugeValue,
c.memoryUsageBytes, getValues: func(s *info.ContainerStats) metricValues {
c.memoryWorkingSet, return metricValues{{value: float64(s.Memory.Usage)}}
c.memoryFailures, },
}, {
c.fsLimit, name: "container_memory_working_set_bytes",
c.fsUsage, help: "Current working set in bytes.",
c.fsReads, valueType: prometheus.GaugeValue,
c.fsReadsSectors, getValues: func(s *info.ContainerStats) metricValues {
c.fsReadsMerged, return metricValues{{value: float64(s.Memory.WorkingSet)}}
c.fsReadTime, },
c.fsWrites, }, {
c.fsWritesSectors, name: "container_memory_failures_total",
c.fsWritesMerged, help: "Cumulative count of memory allocation failures.",
c.fsWriteTime, valueType: prometheus.CounterValue,
c.fsIoInProgress, extraLabels: []string{"type", "scope"},
c.fsIoTime, getValues: func(s *info.ContainerStats) metricValues {
c.fsWeightedIoTime, return metricValues{
{
c.networkRxBytes, value: float64(s.Memory.ContainerData.Pgfault),
c.networkRxPackets, labels: []string{"pgfault", "container"},
c.networkRxErrors, },
c.networkRxDropped, {
c.networkTxBytes, value: float64(s.Memory.ContainerData.Pgmajfault),
c.networkTxPackets, labels: []string{"pgmajfault", "container"},
c.networkTxErrors, },
c.networkTxDropped, {
value: float64(s.Memory.HierarchicalData.Pgfault),
c.tasks, labels: []string{"pgfault", "hierarchy"},
},
{
value: float64(s.Memory.HierarchicalData.Pgmajfault),
labels: []string{"pgmajfault", "hierarchy"},
},
}
},
}, {
name: "container_fs_limit_bytes",
help: "Number of bytes that can be consumed by the container on this filesystem.",
valueType: prometheus.GaugeValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.Limit)
})
},
}, {
name: "container_fs_usage_bytes",
help: "Number of bytes that are consumed by the container on this filesystem.",
valueType: prometheus.GaugeValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.Usage)
})
},
}, {
name: "container_fs_reads_total",
help: "Cumulative count of reads completed",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.ReadsCompleted)
})
},
}, {
name: "container_fs_sector_reads_total",
help: "Cumulative count of sector reads completed",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.SectorsRead)
})
},
}, {
name: "container_fs_reads_merged_total",
help: "Cumulative count of reads merged",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.ReadsMerged)
})
},
}, {
name: "container_fs_read_seconds_total",
help: "Cumulative count of seconds spent reading",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.ReadTime) / float64(time.Second)
})
},
}, {
name: "container_fs_writes_total",
help: "Cumulative count of writes completed",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.WritesCompleted)
})
},
}, {
name: "container_fs_sector_writes_total",
help: "Cumulative count of sector writes completed",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.SectorsWritten)
})
},
}, {
name: "container_fs_writes_merged_total",
help: "Cumulative count of writes merged",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.WritesMerged)
})
},
}, {
name: "container_fs_write_seconds_total",
help: "Cumulative count of seconds spent writing",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.WriteTime) / float64(time.Second)
})
},
}, {
name: "container_fs_io_current",
help: "Number of I/Os currently in progress",
valueType: prometheus.GaugeValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.IoInProgress)
})
},
}, {
name: "container_fs_io_time_seconds_total",
help: "Cumulative count of seconds spent doing I/Os",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(float64(fs.IoTime) / float64(time.Second))
})
},
}, {
name: "container_fs_io_time_weighted_seconds_total",
help: "Cumulative weighted I/O time in seconds",
valueType: prometheus.CounterValue,
extraLabels: []string{"device"},
getValues: func(s *info.ContainerStats) metricValues {
return fsValues(s.Filesystem, func(fs *info.FsStats) float64 {
return float64(fs.WeightedIoTime) / float64(time.Second)
})
},
}, {
name: "container_network_receive_bytes_total",
help: "Cumulative count of bytes received",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.RxBytes)}}
},
}, {
name: "container_network_receive_packets_total",
help: "Cumulative count of packets received",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.RxPackets)}}
},
}, {
name: "container_network_receive_packets_dropped_total",
help: "Cumulative count of packets dropped while receiving",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.RxDropped)}}
},
}, {
name: "container_network_receive_errors_total",
help: "Cumulative count of errors encountered while receiving",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.RxErrors)}}
},
}, {
name: "container_network_transmit_bytes_total",
help: "Cumulative count of bytes transmitted",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.TxBytes)}}
},
}, {
name: "container_network_transmit_packets_total",
help: "Cumulative count of packets transmitted",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.TxPackets)}}
},
}, {
name: "container_network_transmit_packets_dropped_total",
help: "Cumulative count of packets dropped while transmitting",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.TxDropped)}}
},
}, {
name: "container_network_transmit_errors_total",
help: "Cumulative count of errors encountered while transmitting",
valueType: prometheus.CounterValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{{value: float64(s.Network.TxErrors)}}
},
}, {
name: "container_tasks_state",
help: "Number of tasks in given state",
extraLabels: []string{"state"},
valueType: prometheus.GaugeValue,
getValues: func(s *info.ContainerStats) metricValues {
return metricValues{
{
value: float64(s.TaskStats.NrSleeping),
labels: []string{"sleeping"},
},
{
value: float64(s.TaskStats.NrRunning),
labels: []string{"running"},
},
{
value: float64(s.TaskStats.NrStopped),
labels: []string{"stopped"},
},
{
value: float64(s.TaskStats.NrUninterruptible),
labels: []string{"uninterruptible"},
},
{
value: float64(s.TaskStats.NrIoWait),
labels: []string{"iowaiting"},
},
}
},
},
},
} }
return c return c
} }
@ -279,8 +381,8 @@ func NewPrometheusCollector(infoProvider subcontainersInfoProvider) *PrometheusC
// implements prometheus.PrometheusCollector. // implements prometheus.PrometheusCollector.
func (c *PrometheusCollector) Describe(ch chan<- *prometheus.Desc) { func (c *PrometheusCollector) Describe(ch chan<- *prometheus.Desc) {
c.errors.Describe(ch) c.errors.Describe(ch)
for _, d := range c.descs { for _, cm := range c.containerMetrics {
ch <- d ch <- cm.desc()
} }
} }
@ -301,68 +403,10 @@ func (c *PrometheusCollector) Collect(ch chan<- prometheus.Metric) {
} }
stats := container.Stats[0] stats := container.Stats[0]
for desc, metrics := range map[*prometheus.Desc][]prometheusMetric{ for _, cm := range c.containerMetrics {
c.cpuUsageUserSeconds: {{valueType: prometheus.CounterValue, value: float64(stats.Cpu.Usage.User) / float64(time.Second)}}, desc := cm.desc()
c.cpuUsageSystemSeconds: {{valueType: prometheus.CounterValue, value: float64(stats.Cpu.Usage.System) / float64(time.Second)}}, for _, metricValue := range cm.getValues(stats) {
ch <- prometheus.MustNewConstMetric(desc, cm.valueType, float64(metricValue.value), append([]string{name, id}, metricValue.labels...)...)
c.memoryFailures: {
{valueType: prometheus.CounterValue, labels: []string{"pgfault", "container"}, value: float64(stats.Memory.ContainerData.Pgfault)},
{valueType: prometheus.CounterValue, labels: []string{"pgmajfault", "container"}, value: float64(stats.Memory.ContainerData.Pgmajfault)},
{valueType: prometheus.CounterValue, labels: []string{"pgfault", "hierarchy"}, value: float64(stats.Memory.HierarchicalData.Pgfault)},
{valueType: prometheus.CounterValue, labels: []string{"pgmajfault", "hierarchy"}, value: float64(stats.Memory.HierarchicalData.Pgmajfault)},
},
c.tasks: {
{valueType: prometheus.GaugeValue, labels: []string{"sleeping"}, value: float64(stats.TaskStats.NrSleeping)},
{valueType: prometheus.GaugeValue, labels: []string{"running"}, value: float64(stats.TaskStats.NrRunning)},
{valueType: prometheus.GaugeValue, labels: []string{"stopped"}, value: float64(stats.TaskStats.NrStopped)},
{valueType: prometheus.GaugeValue, labels: []string{"uninterruptible"}, value: float64(stats.TaskStats.NrUninterruptible)},
{valueType: prometheus.GaugeValue, labels: []string{"iowaiting"}, value: float64(stats.TaskStats.NrIoWait)},
},
c.lastSeen: {{valueType: prometheus.GaugeValue, value: float64(time.Now().Unix())}},
c.memoryUsageBytes: {{valueType: prometheus.GaugeValue, value: float64(stats.Memory.Usage)}},
c.memoryWorkingSet: {{valueType: prometheus.GaugeValue, value: float64(stats.Memory.WorkingSet)}},
c.networkRxBytes: {{valueType: prometheus.CounterValue, value: float64(stats.Network.RxBytes)}},
c.networkRxPackets: {{valueType: prometheus.CounterValue, value: float64(stats.Network.RxPackets)}},
c.networkRxErrors: {{valueType: prometheus.CounterValue, value: float64(stats.Network.RxErrors)}},
c.networkRxDropped: {{valueType: prometheus.CounterValue, value: float64(stats.Network.RxDropped)}},
c.networkTxBytes: {{valueType: prometheus.CounterValue, value: float64(stats.Network.TxBytes)}},
c.networkTxPackets: {{valueType: prometheus.CounterValue, value: float64(stats.Network.TxPackets)}},
c.networkTxErrors: {{valueType: prometheus.CounterValue, value: float64(stats.Network.TxErrors)}},
c.networkTxDropped: {{valueType: prometheus.CounterValue, value: float64(stats.Network.TxDropped)}},
} {
for _, m := range metrics {
ch <- prometheus.MustNewConstMetric(desc, m.valueType, float64(m.value), append(m.labels, name, id)...)
}
}
// Metrics with dynamic labels
for i, value := range stats.Cpu.Usage.PerCpu {
ch <- prometheus.MustNewConstMetric(c.cpuUsageSecondsPerCPU, prometheus.CounterValue, float64(value)/float64(time.Second), name, id, fmt.Sprintf("cpu%02d", i))
}
for _, stat := range stats.Filesystem {
for desc, m := range map[*prometheus.Desc]prometheusMetric{
c.fsReads: {valueType: prometheus.CounterValue, value: float64(stat.ReadsCompleted)},
c.fsReadsSectors: {valueType: prometheus.CounterValue, value: float64(stat.SectorsRead)},
c.fsReadsMerged: {valueType: prometheus.CounterValue, value: float64(stat.ReadsMerged)},
c.fsReadTime: {valueType: prometheus.CounterValue, value: float64(stat.ReadTime) / float64(time.Second)},
c.fsWrites: {valueType: prometheus.CounterValue, value: float64(stat.WritesCompleted)},
c.fsWritesSectors: {valueType: prometheus.CounterValue, value: float64(stat.SectorsWritten)},
c.fsWritesMerged: {valueType: prometheus.CounterValue, value: float64(stat.WritesMerged)},
c.fsWriteTime: {valueType: prometheus.CounterValue, value: float64(stat.WriteTime) / float64(time.Second)},
c.fsIoTime: {valueType: prometheus.CounterValue, value: float64(stat.IoTime) / float64(time.Second)},
c.fsWeightedIoTime: {valueType: prometheus.CounterValue, value: float64(stat.WeightedIoTime) / float64(time.Second)},
c.fsIoInProgress: {valueType: prometheus.GaugeValue, value: float64(stat.IoInProgress)},
c.fsLimit: {valueType: prometheus.GaugeValue, value: float64(stat.Limit)},
c.fsUsage: {valueType: prometheus.GaugeValue, value: float64(stat.Usage)},
} {
ch <- prometheus.MustNewConstMetric(desc, m.valueType, m.value, name, id, stat.Device)
} }
} }
} }