mirror of
https://github.com/prometheus/node_exporter.git
synced 2024-11-13 17:14:23 -08:00
76bbd8dd18
While the statfs(2) approach is reliable for normally mounted filesystems, the flags returned can be inconsistent when filesystem has been remounted read-only after encountering an error. The returned flags do accurately represent the internal state of the filesystem, but they do not reflect whether the VFS layer will accept writes. Instead, it makes sense to parse the current VFS mount state from the options field in /proc/mounts since it takes precedence. Signed-off-by: Brandon Gilmore <bgilmore@valvesoftware.com>
177 lines
5.2 KiB
Go
177 lines
5.2 KiB
Go
// Copyright 2015 The Prometheus Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// +build !nofilesystem
|
|
// +build linux freebsd openbsd darwin,amd64 dragonfly
|
|
|
|
package collector
|
|
|
|
import (
|
|
"regexp"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"gopkg.in/alecthomas/kingpin.v2"
|
|
)
|
|
|
|
// Arch-dependent implementation must define:
|
|
// * defIgnoredMountPoints
|
|
// * defIgnoredFSTypes
|
|
// * filesystemLabelNames
|
|
// * filesystemCollector.GetStats
|
|
|
|
var (
|
|
ignoredMountPoints = kingpin.Flag(
|
|
"collector.filesystem.ignored-mount-points",
|
|
"Regexp of mount points to ignore for filesystem collector.",
|
|
).Default(defIgnoredMountPoints).String()
|
|
ignoredFSTypes = kingpin.Flag(
|
|
"collector.filesystem.ignored-fs-types",
|
|
"Regexp of filesystem types to ignore for filesystem collector.",
|
|
).Default(defIgnoredFSTypes).String()
|
|
|
|
filesystemLabelNames = []string{"device", "mountpoint", "fstype"}
|
|
)
|
|
|
|
type filesystemCollector struct {
|
|
ignoredMountPointsPattern *regexp.Regexp
|
|
ignoredFSTypesPattern *regexp.Regexp
|
|
sizeDesc, freeDesc, availDesc *prometheus.Desc
|
|
filesDesc, filesFreeDesc *prometheus.Desc
|
|
roDesc, deviceErrorDesc *prometheus.Desc
|
|
}
|
|
|
|
type filesystemLabels struct {
|
|
device, mountPoint, fsType, options string
|
|
}
|
|
|
|
type filesystemStats struct {
|
|
labels filesystemLabels
|
|
size, free, avail float64
|
|
files, filesFree float64
|
|
ro, deviceError float64
|
|
}
|
|
|
|
func init() {
|
|
registerCollector("filesystem", defaultEnabled, NewFilesystemCollector)
|
|
}
|
|
|
|
// NewFilesystemCollector returns a new Collector exposing filesystems stats.
|
|
func NewFilesystemCollector() (Collector, error) {
|
|
subsystem := "filesystem"
|
|
mountPointPattern := regexp.MustCompile(*ignoredMountPoints)
|
|
filesystemsTypesPattern := regexp.MustCompile(*ignoredFSTypes)
|
|
|
|
sizeDesc := prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, subsystem, "size_bytes"),
|
|
"Filesystem size in bytes.",
|
|
filesystemLabelNames, nil,
|
|
)
|
|
|
|
freeDesc := prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, subsystem, "free_bytes"),
|
|
"Filesystem free space in bytes.",
|
|
filesystemLabelNames, nil,
|
|
)
|
|
|
|
availDesc := prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, subsystem, "avail_bytes"),
|
|
"Filesystem space available to non-root users in bytes.",
|
|
filesystemLabelNames, nil,
|
|
)
|
|
|
|
filesDesc := prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, subsystem, "files"),
|
|
"Filesystem total file nodes.",
|
|
filesystemLabelNames, nil,
|
|
)
|
|
|
|
filesFreeDesc := prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, subsystem, "files_free"),
|
|
"Filesystem total free file nodes.",
|
|
filesystemLabelNames, nil,
|
|
)
|
|
|
|
roDesc := prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, subsystem, "readonly"),
|
|
"Filesystem read-only status.",
|
|
filesystemLabelNames, nil,
|
|
)
|
|
|
|
deviceErrorDesc := prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, subsystem, "device_error"),
|
|
"Whether an error occurred while getting statistics for the given device.",
|
|
filesystemLabelNames, nil,
|
|
)
|
|
|
|
return &filesystemCollector{
|
|
ignoredMountPointsPattern: mountPointPattern,
|
|
ignoredFSTypesPattern: filesystemsTypesPattern,
|
|
sizeDesc: sizeDesc,
|
|
freeDesc: freeDesc,
|
|
availDesc: availDesc,
|
|
filesDesc: filesDesc,
|
|
filesFreeDesc: filesFreeDesc,
|
|
roDesc: roDesc,
|
|
deviceErrorDesc: deviceErrorDesc,
|
|
}, nil
|
|
}
|
|
|
|
func (c *filesystemCollector) Update(ch chan<- prometheus.Metric) error {
|
|
stats, err := c.GetStats()
|
|
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.deviceErrorDesc, prometheus.GaugeValue,
|
|
s.deviceError, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
|
)
|
|
if s.deviceError > 0 {
|
|
continue
|
|
}
|
|
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.sizeDesc, prometheus.GaugeValue,
|
|
s.size, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.freeDesc, prometheus.GaugeValue,
|
|
s.free, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.availDesc, prometheus.GaugeValue,
|
|
s.avail, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.filesDesc, prometheus.GaugeValue,
|
|
s.files, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.filesFreeDesc, prometheus.GaugeValue,
|
|
s.filesFree, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
c.roDesc, prometheus.GaugeValue,
|
|
s.ro, s.labels.device, s.labels.mountPoint, s.labels.fsType,
|
|
)
|
|
}
|
|
return nil
|
|
}
|