mirror of
https://github.com/prometheus/node_exporter.git
synced 2024-11-09 23:24:09 -08:00
Fix export of stale device error metrics for unmounted filesystems
Instead of maintaining a counter metric for device errors in memory, this change exports a gauge and uses const metrics to avoid leaking metrics for unmounted filesystems.
This commit is contained in:
parent
7b93b52010
commit
d290ea94b8
|
@ -46,9 +46,9 @@ var (
|
||||||
type filesystemCollector struct {
|
type filesystemCollector struct {
|
||||||
ignoredMountPointsPattern *regexp.Regexp
|
ignoredMountPointsPattern *regexp.Regexp
|
||||||
ignoredFSTypesPattern *regexp.Regexp
|
ignoredFSTypesPattern *regexp.Regexp
|
||||||
sizeDesc, freeDesc, availDesc,
|
sizeDesc, freeDesc, availDesc *prometheus.Desc
|
||||||
filesDesc, filesFreeDesc, roDesc *prometheus.Desc
|
filesDesc, filesFreeDesc *prometheus.Desc
|
||||||
devErrors *prometheus.CounterVec
|
roDesc, deviceErrorDesc *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
type filesystemLabels struct {
|
type filesystemLabels struct {
|
||||||
|
@ -57,7 +57,9 @@ type filesystemLabels struct {
|
||||||
|
|
||||||
type filesystemStats struct {
|
type filesystemStats struct {
|
||||||
labels filesystemLabels
|
labels filesystemLabels
|
||||||
size, free, avail, files, filesFree, ro float64
|
size, free, avail float64
|
||||||
|
files, filesFree float64
|
||||||
|
ro, deviceError float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -106,10 +108,11 @@ func NewFilesystemCollector() (Collector, error) {
|
||||||
filesystemLabelNames, nil,
|
filesystemLabelNames, nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
devErrors := prometheus.NewCounterVec(prometheus.CounterOpts{
|
deviceErrorDesc := prometheus.NewDesc(
|
||||||
Name: prometheus.BuildFQName(Namespace, subsystem, "device_errors_total"),
|
prometheus.BuildFQName(Namespace, subsystem, "device_error"),
|
||||||
Help: "Total number of errors occurred when getting stats for device",
|
"Whether an error occured while getting statistics for the given device.",
|
||||||
}, filesystemLabelNames)
|
filesystemLabelNames, nil,
|
||||||
|
)
|
||||||
|
|
||||||
return &filesystemCollector{
|
return &filesystemCollector{
|
||||||
ignoredMountPointsPattern: mountPointPattern,
|
ignoredMountPointsPattern: mountPointPattern,
|
||||||
|
@ -120,7 +123,7 @@ func NewFilesystemCollector() (Collector, error) {
|
||||||
filesDesc: filesDesc,
|
filesDesc: filesDesc,
|
||||||
filesFreeDesc: filesFreeDesc,
|
filesFreeDesc: filesFreeDesc,
|
||||||
roDesc: roDesc,
|
roDesc: roDesc,
|
||||||
devErrors: devErrors,
|
deviceErrorDesc: deviceErrorDesc,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +140,14 @@ func (c *filesystemCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
}
|
}
|
||||||
seen[s.labels] = true
|
seen[s.labels] = true
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.deviceErrorDesc, prometheus.GaugeValue,
|
||||||
|
s.deviceError, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
||||||
|
)
|
||||||
|
if s.deviceError > 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.sizeDesc, prometheus.GaugeValue,
|
c.sizeDesc, prometheus.GaugeValue,
|
||||||
s.size, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
s.size, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
||||||
|
@ -162,6 +173,5 @@ func (c *filesystemCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
s.ro, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
s.ro, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
c.devErrors.Collect(ch)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,13 +46,15 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
log.Debugf("Ignoring fs type: %s", labels.fsType)
|
log.Debugf("Ignoring fs type: %s", labels.fsType)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
labelValues := []string{labels.device, labels.mountPoint, labels.fsType}
|
|
||||||
buf := new(syscall.Statfs_t)
|
buf := new(syscall.Statfs_t)
|
||||||
err := syscall.Statfs(labels.mountPoint, buf)
|
err := syscall.Statfs(labels.mountPoint, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.devErrors.WithLabelValues(labelValues...).Inc()
|
stats = append(stats, filesystemStats{
|
||||||
log.Debugf("Statfs on %s returned %s",
|
labels: labels,
|
||||||
labels.mountPoint, err)
|
deviceError: 1,
|
||||||
|
})
|
||||||
|
log.Errorf("Error on statfs() system call for %q: %s", labels.mountPoint, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +84,14 @@ func mountPointDetails() ([]filesystemLabels, error) {
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
filesystems := []filesystemLabels{}
|
filesystems := []filesystemLabels{}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
parts := strings.Fields(scanner.Text())
|
parts := strings.Fields(scanner.Text())
|
||||||
filesystems = append(filesystems, filesystemLabels{parts[0], parts[1], parts[2]})
|
filesystems = append(filesystems, filesystemLabels{
|
||||||
|
device: parts[0],
|
||||||
|
mountPoint: parts[1],
|
||||||
|
fsType: parts[2],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return filesystems, scanner.Err()
|
return filesystems, scanner.Err()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue