Merge pull request #399 from discordianfish/fish-fs-uniq-metric

Make sure we only return one metric per mounted fs
This commit is contained in:
Johannes 'fish' Ziemke 2017-01-04 16:48:04 +01:00 committed by GitHub
commit f9d3f830cb
4 changed files with 60 additions and 49 deletions

View file

@ -66,15 +66,18 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
ro = 1
}
labelValues := []string{device, mountpoint, fstype}
stats = append(stats, filesystemStats{
labelValues: labelValues,
size: float64(mnt[i].f_blocks) * float64(mnt[i].f_bsize),
free: float64(mnt[i].f_bfree) * float64(mnt[i].f_bsize),
avail: float64(mnt[i].f_bavail) * float64(mnt[i].f_bsize),
files: float64(mnt[i].f_files),
filesFree: float64(mnt[i].f_ffree),
ro: ro,
labels: filesystemLabels{
device: device,
mountPoint: mountpoint,
fsType: fstype,
},
size: float64(mnt[i].f_blocks) * float64(mnt[i].f_bsize),
free: float64(mnt[i].f_bfree) * float64(mnt[i].f_bsize),
avail: float64(mnt[i].f_bavail) * float64(mnt[i].f_bsize),
files: float64(mnt[i].f_files),
filesFree: float64(mnt[i].f_ffree),
ro: ro,
})
}
return stats, nil

View file

@ -51,8 +51,12 @@ type filesystemCollector struct {
devErrors *prometheus.CounterVec
}
type filesystemLabels struct {
device, mountPoint, fsType string
}
type filesystemStats struct {
labelValues []string
labels filesystemLabels
size, free, avail, files, filesFree, ro float64
}
@ -126,30 +130,37 @@ func (c *filesystemCollector) Update(ch chan<- prometheus.Metric) (err error) {
if err != nil {
return err
}
// Make sure we expose a metric once, even if there are multiple mounts
seen := map[filesystemLabels]bool{}
for _, s := range stats {
if seen[s.labels] {
continue
}
seen[s.labels] = true
ch <- prometheus.MustNewConstMetric(
c.sizeDesc, prometheus.GaugeValue,
s.size, s.labelValues...,
s.size, s.labels.device, s.labels.mountPoint, s.labels.fsType,
)
ch <- prometheus.MustNewConstMetric(
c.freeDesc, prometheus.GaugeValue,
s.free, s.labelValues...,
s.free, s.labels.device, s.labels.mountPoint, s.labels.fsType,
)
ch <- prometheus.MustNewConstMetric(
c.availDesc, prometheus.GaugeValue,
s.avail, s.labelValues...,
s.avail, s.labels.device, s.labels.mountPoint, s.labels.fsType,
)
ch <- prometheus.MustNewConstMetric(
c.filesDesc, prometheus.GaugeValue,
s.files, s.labelValues...,
s.files, s.labels.device, s.labels.mountPoint, s.labels.fsType,
)
ch <- prometheus.MustNewConstMetric(
c.filesFreeDesc, prometheus.GaugeValue,
s.filesFree, s.labelValues...,
s.filesFree, s.labels.device, s.labels.mountPoint, s.labels.fsType,
)
ch <- prometheus.MustNewConstMetric(
c.roDesc, prometheus.GaugeValue,
s.ro, s.labelValues...,
s.ro, s.labels.device, s.labels.mountPoint, s.labels.fsType,
)
}
c.devErrors.Collect(ch)

View file

@ -73,15 +73,18 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
ro = 1
}
labelValues := []string{device, mountpoint, fstype}
stats = append(stats, filesystemStats{
labelValues: labelValues,
size: float64(fs.Blocks) * float64(fs.Bsize),
free: float64(fs.Bfree) * float64(fs.Bsize),
avail: float64(fs.Bavail) * float64(fs.Bsize),
files: float64(fs.Files),
filesFree: float64(fs.Ffree),
ro: ro,
labels: filesystemLabels{
device: device,
mountPoint: mountpoint,
fsType: fstype,
},
size: float64(fs.Blocks) * float64(fs.Bsize),
free: float64(fs.Bfree) * float64(fs.Bsize),
avail: float64(fs.Bavail) * float64(fs.Bsize),
files: float64(fs.Files),
filesFree: float64(fs.Ffree),
ro: ro,
})
}
return stats, nil

View file

@ -30,35 +30,29 @@ const (
ST_RDONLY = 0x1
)
type filesystemDetails struct {
device string
mountPoint string
fsType string
}
// Expose filesystem fullness.
func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
mpds, err := mountPointDetails()
mps, err := mountPointDetails()
if err != nil {
return nil, err
}
stats = []filesystemStats{}
for _, mpd := range mpds {
if c.ignoredMountPointsPattern.MatchString(mpd.mountPoint) {
log.Debugf("Ignoring mount point: %s", mpd.mountPoint)
for _, labels := range mps {
if c.ignoredMountPointsPattern.MatchString(labels.mountPoint) {
log.Debugf("Ignoring mount point: %s", labels.mountPoint)
continue
}
if c.ignoredFSTypesPattern.MatchString(mpd.fsType) {
log.Debugf("Ignoring fs type: %s", mpd.fsType)
if c.ignoredFSTypesPattern.MatchString(labels.fsType) {
log.Debugf("Ignoring fs type: %s", labels.fsType)
continue
}
labelValues := []string{mpd.device, mpd.mountPoint, mpd.fsType}
labelValues := []string{labels.device, labels.mountPoint, labels.fsType}
buf := new(syscall.Statfs_t)
err := syscall.Statfs(mpd.mountPoint, buf)
err := syscall.Statfs(labels.mountPoint, buf)
if err != nil {
c.devErrors.WithLabelValues(labelValues...).Inc()
log.Debugf("Statfs on %s returned %s",
mpd.mountPoint, err)
labels.mountPoint, err)
continue
}
@ -68,31 +62,31 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
}
stats = append(stats, filesystemStats{
labelValues: labelValues,
size: float64(buf.Blocks) * float64(buf.Bsize),
free: float64(buf.Bfree) * float64(buf.Bsize),
avail: float64(buf.Bavail) * float64(buf.Bsize),
files: float64(buf.Files),
filesFree: float64(buf.Ffree),
ro: ro,
labels: labels,
size: float64(buf.Blocks) * float64(buf.Bsize),
free: float64(buf.Bfree) * float64(buf.Bsize),
avail: float64(buf.Bavail) * float64(buf.Bsize),
files: float64(buf.Files),
filesFree: float64(buf.Ffree),
ro: ro,
})
}
return stats, nil
}
func mountPointDetails() ([]filesystemDetails, error) {
func mountPointDetails() ([]filesystemLabels, error) {
file, err := os.Open(procFilePath("mounts"))
if err != nil {
return nil, err
}
defer file.Close()
filesystems := []filesystemDetails{}
filesystems := []filesystemLabels{}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
parts := strings.Fields(scanner.Text())
filesystems = append(filesystems, filesystemDetails{parts[0], parts[1], parts[2]})
filesystems = append(filesystems, filesystemLabels{parts[0], parts[1], parts[2]})
}
return filesystems, nil
return filesystems, scanner.Err()
}