From 20b551ab2bd8980c82fb6802296fc26cabc90de4 Mon Sep 17 00:00:00 2001 From: Matthias Rampke Date: Sat, 26 Sep 2015 14:53:46 +0200 Subject: [PATCH] Add flag to change the location of the procfs. Remove all hardcoded references to `/proc`. For all collectors that do not use `github.com/prometheus/procfs` yet, provide a wrapper to generate the full paths. Reformulate help strings, errors and comments to remove absolute references to `/proc`. This is a breaking change: the `-collector.ipvs.procfs` flag is removed in favor of the general flag. Since it only affected that collector it was only useful for development, so this should not cause many issues. --- collector/diskstats_linux.go | 6 +++--- collector/filefd_linux.go | 5 ++--- collector/filesystem_linux.go | 3 +-- collector/interrupts_linux.go | 11 ++++------- collector/ipvs.go | 7 +------ collector/ipvs_test.go | 4 ++-- collector/loadavg_linux.go | 6 +----- collector/mdadm.go | 12 ++++++------ collector/meminfo_linux.go | 7 +++---- collector/netdev_linux.go | 14 +++++--------- collector/netstat_linux.go | 8 +++----- collector/procpath.go | 17 +++++++++++++++++ collector/sockstat_linux.go | 5 ++--- collector/stat_linux.go | 7 +++---- collector/tcpstat_linux.go | 12 ++++-------- 15 files changed, 57 insertions(+), 67 deletions(-) create mode 100644 collector/procpath.go diff --git a/collector/diskstats_linux.go b/collector/diskstats_linux.go index 57c703bc..53c9e364 100644 --- a/collector/diskstats_linux.go +++ b/collector/diskstats_linux.go @@ -17,7 +17,6 @@ import ( ) const ( - procDiskStats = "/proc/diskstats" diskSubsystem = "disk" ) @@ -147,6 +146,7 @@ func NewDiskstatsCollector() (Collector, error) { } func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) (err error) { + procDiskStats := procFilePath("diskstats") diskStats, err := getDiskStats() if err != nil { return fmt.Errorf("couldn't get diskstats: %s", err) @@ -184,7 +184,7 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) (err error) { } func getDiskStats() (map[string]map[int]string, error) { - file, err := os.Open(procDiskStats) + file, err := os.Open(procFilePath("diskstats")) if err != nil { return nil, err } @@ -202,7 +202,7 @@ func parseDiskStats(r io.Reader) (map[string]map[int]string, error) { for scanner.Scan() { parts := strings.Fields(string(scanner.Text())) if len(parts) < 4 { // we strip major, minor and dev - return nil, fmt.Errorf("invalid line in %s: %s", procDiskStats, scanner.Text()) + return nil, fmt.Errorf("invalid line in %s: %s", procFilePath("diskstats"), scanner.Text()) } dev := parts[2] diskStats[dev] = map[int]string{} diff --git a/collector/filefd_linux.go b/collector/filefd_linux.go index 47a50647..2ba7e4fa 100644 --- a/collector/filefd_linux.go +++ b/collector/filefd_linux.go @@ -13,7 +13,6 @@ import ( ) const ( - procFileFDStat = "/proc/sys/fs/file-nr" fileFDStatSubsystem = "filefd" ) @@ -33,7 +32,7 @@ func NewFileFDStatCollector() (Collector, error) { } func (c *fileFDStatCollector) Update(ch chan<- prometheus.Metric) (err error) { - fileFDStat, err := getFileFDStats(procFileFDStat) + fileFDStat, err := getFileFDStats(procFilePath("sys/fs/file-nr")) if err != nil { return fmt.Errorf("couldn't get file-nr: %s", err) } @@ -44,7 +43,7 @@ func (c *fileFDStatCollector) Update(ch chan<- prometheus.Metric) (err error) { Namespace: Namespace, Subsystem: fileFDStatSubsystem, Name: name, - Help: fmt.Sprintf("filefd %s from %s.", name, procFileFDStat), + Help: fmt.Sprintf("File descriptor statistics: %s.", name), }, ) v, err := strconv.ParseFloat(value, 64) diff --git a/collector/filesystem_linux.go b/collector/filesystem_linux.go index 6090b2da..22e49981 100644 --- a/collector/filesystem_linux.go +++ b/collector/filesystem_linux.go @@ -14,7 +14,6 @@ import ( const ( defIgnoredMountPoints = "^/(sys|proc|dev)($|/)" - procMounts = "/proc/mounts" ) var ( @@ -60,7 +59,7 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) { } func mountPointDetails() ([]filesystemDetails, error) { - file, err := os.Open(procMounts) + file, err := os.Open(procFilePath("mounts")) if err != nil { return nil, err } diff --git a/collector/interrupts_linux.go b/collector/interrupts_linux.go index aebe184b..8d6c1488 100644 --- a/collector/interrupts_linux.go +++ b/collector/interrupts_linux.go @@ -4,6 +4,7 @@ package collector import ( "bufio" + "errors" "fmt" "io" "os" @@ -13,10 +14,6 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -const ( - procInterrupts = "/proc/interrupts" -) - type interruptsCollector struct { metric *prometheus.CounterVec } @@ -33,7 +30,7 @@ func NewInterruptsCollector() (Collector, error) { prometheus.CounterOpts{ Namespace: Namespace, Name: "interrupts", - Help: "Interrupt details from /proc/interrupts.", + Help: "Interrupt details.", }, []string{"CPU", "type", "info", "devices"}, ), @@ -71,7 +68,7 @@ type interrupt struct { } func getInterrupts() (map[string]interrupt, error) { - file, err := os.Open(procInterrupts) + file, err := os.Open(procFilePath("interrupts")) if err != nil { return nil, err } @@ -87,7 +84,7 @@ func parseInterrupts(r io.Reader) (map[string]interrupt, error) { ) if !scanner.Scan() { - return nil, fmt.Errorf("%s empty", procInterrupts) + return nil, errors.New("interrupts empty") } cpuNum := len(strings.Fields(string(scanner.Text()))) // one header per cpu diff --git a/collector/ipvs.go b/collector/ipvs.go index f77cc507..969b56f6 100644 --- a/collector/ipvs.go +++ b/collector/ipvs.go @@ -3,7 +3,6 @@ package collector import ( - "flag" "fmt" "strconv" @@ -11,10 +10,6 @@ import ( "github.com/prometheus/procfs" ) -var ( - ipvsProcfsMountPoint = flag.String("collector.ipvs.procfs", procfs.DefaultMountPoint, "procfs mountpoint.") -) - type ipvsCollector struct { Collector fs procfs.FS @@ -46,7 +41,7 @@ func newIPVSCollector() (*ipvsCollector, error) { subsystem = "ipvs" ) - c.fs, err = procfs.NewFS(*ipvsProcfsMountPoint) + c.fs, err = procfs.NewFS(*procPath) if err != nil { return nil, err } diff --git a/collector/ipvs_test.go b/collector/ipvs_test.go index d9326e4d..4564fbf0 100644 --- a/collector/ipvs_test.go +++ b/collector/ipvs_test.go @@ -107,7 +107,7 @@ var ( ) func TestIPVSCollector(t *testing.T) { - if err := flag.Set("collector.ipvs.procfs", "fixtures"); err != nil { + if err := flag.Set("collector.procfs", "fixtures"); err != nil { t.Fatal(err) } collector, err := newIPVSCollector() @@ -169,7 +169,7 @@ func (c miniCollector) Describe(ch chan<- *prometheus.Desc) { } func TestIPVSCollectorResponse(t *testing.T) { - if err := flag.Set("collector.ipvs.procfs", "fixtures"); err != nil { + if err := flag.Set("collector.procfs", "fixtures"); err != nil { t.Fatal(err) } collector, err := NewIPVSCollector() diff --git a/collector/loadavg_linux.go b/collector/loadavg_linux.go index bdf72988..4d2e15e4 100644 --- a/collector/loadavg_linux.go +++ b/collector/loadavg_linux.go @@ -12,10 +12,6 @@ import ( "github.com/prometheus/log" ) -const ( - procLoad = "/proc/loadavg" -) - type loadavgCollector struct { metric prometheus.Gauge } @@ -48,7 +44,7 @@ func (c *loadavgCollector) Update(ch chan<- prometheus.Metric) (err error) { } func getLoad1() (float64, error) { - data, err := ioutil.ReadFile(procLoad) + data, err := ioutil.ReadFile(procFilePath("loadavg")) if err != nil { return 0, err } diff --git a/collector/mdadm.go b/collector/mdadm.go index 78f33d56..ec851e8c 100644 --- a/collector/mdadm.go +++ b/collector/mdadm.go @@ -15,7 +15,6 @@ import ( ) var ( - statusfile = "/proc/mdstat" statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) ) @@ -90,7 +89,7 @@ func evalBuildline(buildline string) (int64, error) { func parseMdstat(mdStatusFilePath string) ([]mdStatus, error) { content, err := ioutil.ReadFile(mdStatusFilePath) if err != nil { - return []mdStatus{}, fmt.Errorf("error parsing %s: %s", statusfile, err) + return []mdStatus{}, fmt.Errorf("error parsing mdstatus: %s", err) } mdStatusFile := string(content) @@ -128,13 +127,13 @@ func parseMdstat(mdStatusFilePath string) ([]mdStatus, error) { isActive := (mainLine[2] == "active") // activity status of said md-device if len(lines) <= i+3 { - return mdStates, fmt.Errorf("error parsing %s: entry for %s has fewer lines than expected", statusfile, currentMD) + return mdStates, fmt.Errorf("error parsing mdstatus: entry for %s has fewer lines than expected", currentMD) } active, total, size, err := evalStatusline(lines[i+1]) // parse statusline, always present if err != nil { - return mdStates, fmt.Errorf("error parsing %s: %s", statusfile, err) + return mdStates, fmt.Errorf("error parsing mdstatus: %s", err) } // Now get the number of synced blocks. @@ -153,7 +152,7 @@ func parseMdstat(mdStatusFilePath string) ([]mdStatus, error) { if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") { syncedBlocks, err = evalBuildline(lines[j]) if err != nil { - return mdStates, fmt.Errorf("error parsing %s: %s", statusfile, err) + return mdStates, fmt.Errorf("error parsing mdstatus: %s", err) } } else { syncedBlocks = size @@ -209,6 +208,7 @@ var ( ) func (c *mdadmCollector) Update(ch chan<- prometheus.Metric) (err error) { + statusfile := procFilePath("mdstatus") // take care we don't crash on non-existent statusfiles _, err = os.Stat(statusfile) if os.IsNotExist(err) { @@ -223,7 +223,7 @@ func (c *mdadmCollector) Update(ch chan<- prometheus.Metric) (err error) { // First parse mdstat-file... mdstate, err := parseMdstat(statusfile) if err != nil { - return fmt.Errorf("error parsing %s: %s", statusfile, err) + return fmt.Errorf("error parsing mdstatus: %s", err) } // ... and then plug the result into the metrics to be exported. diff --git a/collector/meminfo_linux.go b/collector/meminfo_linux.go index 5ed920b1..6185913f 100644 --- a/collector/meminfo_linux.go +++ b/collector/meminfo_linux.go @@ -16,7 +16,6 @@ import ( ) const ( - procMemInfo = "/proc/meminfo" memInfoSubsystem = "memory" ) @@ -48,7 +47,7 @@ func (c *meminfoCollector) Update(ch chan<- prometheus.Metric) (err error) { Namespace: Namespace, Subsystem: memInfoSubsystem, Name: k, - Help: k + " from /proc/meminfo.", + Help: fmt.Sprintf("Memory information field %s.", k), }) } c.metrics[k].Set(v) @@ -58,7 +57,7 @@ func (c *meminfoCollector) Update(ch chan<- prometheus.Metric) (err error) { } func getMemInfo() (map[string]float64, error) { - file, err := os.Open(procMemInfo) + file, err := os.Open(procFilePath("meminfo")) if err != nil { return nil, err } @@ -86,7 +85,7 @@ func parseMemInfo(r io.Reader) (map[string]float64, error) { case 3: // has unit, we presume kB fv *= 1024 default: - return nil, fmt.Errorf("Invalid line in %s: %s", procMemInfo, line) + return nil, fmt.Errorf("Invalid line in meminfo: %s", line) } key := parts[0][:len(parts[0])-1] // remove trailing : from key // Active(anon) -> Active_anon diff --git a/collector/netdev_linux.go b/collector/netdev_linux.go index f82d50e1..998a5676 100644 --- a/collector/netdev_linux.go +++ b/collector/netdev_linux.go @@ -16,10 +16,6 @@ import ( "github.com/prometheus/log" ) -const ( - procNetDev = "/proc/net/dev" -) - var ( procNetDevFieldSep = regexp.MustCompile("[ :] *") netdevIgnoredDevices = flag.String( @@ -59,7 +55,7 @@ func (c *netDevCollector) Update(ch chan<- prometheus.Metric) (err error) { if !ok { desc = prometheus.NewDesc( prometheus.BuildFQName(Namespace, c.subsystem, key), - fmt.Sprintf("%s from /proc/net/dev.", key), + fmt.Sprintf("Network device statistic %s.", key), []string{"device"}, nil, ) @@ -76,7 +72,7 @@ func (c *netDevCollector) Update(ch chan<- prometheus.Metric) (err error) { } func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) { - file, err := os.Open(procNetDev) + file, err := os.Open(procFilePath("net/dev")) if err != nil { return nil, err } @@ -91,8 +87,8 @@ func parseNetDevStats(r io.Reader, ignore *regexp.Regexp) (map[string]map[string scanner.Scan() parts := strings.Split(string(scanner.Text()), "|") if len(parts) != 3 { // interface + receive + transmit - return nil, fmt.Errorf("invalid header line in %s: %s", - procNetDev, scanner.Text()) + return nil, fmt.Errorf("invalid header line in net/dev: %s", + scanner.Text()) } header := strings.Fields(parts[1]) @@ -101,7 +97,7 @@ func parseNetDevStats(r io.Reader, ignore *regexp.Regexp) (map[string]map[string line := strings.TrimLeft(string(scanner.Text()), " ") parts := procNetDevFieldSep.Split(line, -1) if len(parts) != 2*len(header)+1 { - return nil, fmt.Errorf("invalid line in %s: %s", procNetDev, scanner.Text()) + return nil, fmt.Errorf("invalid line in net/dev: %s", scanner.Text()) } dev := parts[0][:len(parts[0])] diff --git a/collector/netstat_linux.go b/collector/netstat_linux.go index 60188db4..61849544 100644 --- a/collector/netstat_linux.go +++ b/collector/netstat_linux.go @@ -14,8 +14,6 @@ import ( ) const ( - procNetStat = "/proc/net/netstat" - procSNMPStat = "/proc/net/snmp" netStatsSubsystem = "netstat" ) @@ -36,11 +34,11 @@ func NewNetStatCollector() (Collector, error) { } func (c *netStatCollector) Update(ch chan<- prometheus.Metric) (err error) { - netStats, err := getNetStats(procNetStat) + netStats, err := getNetStats(procFilePath("net/netstat")) if err != nil { return fmt.Errorf("couldn't get netstats: %s", err) } - snmpStats, err := getNetStats(procSNMPStat) + snmpStats, err := getNetStats(procFilePath("net/snmp")) if err != nil { return fmt.Errorf("couldn't get SNMP stats: %s", err) } @@ -58,7 +56,7 @@ func (c *netStatCollector) Update(ch chan<- prometheus.Metric) (err error) { Namespace: Namespace, Subsystem: netStatsSubsystem, Name: key, - Help: fmt.Sprintf("%s %s from /proc/net/{netstat,snmp}.", protocol, name), + Help: fmt.Sprintf("Protocol %s statistic %s.", protocol, name), }, ) } diff --git a/collector/procpath.go b/collector/procpath.go new file mode 100644 index 00000000..d9b6bd63 --- /dev/null +++ b/collector/procpath.go @@ -0,0 +1,17 @@ +package collector + +import ( + "flag" + "path" + + "github.com/prometheus/procfs" +) + +var ( + // The path of the proc filesystem. + procPath = flag.String("collector.procfs", procfs.DefaultMountPoint, "procfs mountpoint.") +) + +func procFilePath(name string) string { + return path.Join(*procPath, name) +} diff --git a/collector/sockstat_linux.go b/collector/sockstat_linux.go index d9f1944f..01b5318a 100644 --- a/collector/sockstat_linux.go +++ b/collector/sockstat_linux.go @@ -13,7 +13,6 @@ import ( ) const ( - procSockStat = "/proc/net/sockstat" sockStatSubsystem = "sockstat" ) @@ -36,7 +35,7 @@ func NewSockStatCollector() (Collector, error) { } func (c *sockStatCollector) Update(ch chan<- prometheus.Metric) (err error) { - sockStats, err := getSockStats(procSockStat) + sockStats, err := getSockStats(procFilePath("net/sockstat")) if err != nil { return fmt.Errorf("couldn't get sockstats: %s", err) } @@ -49,7 +48,7 @@ func (c *sockStatCollector) Update(ch chan<- prometheus.Metric) (err error) { Namespace: Namespace, Subsystem: sockStatSubsystem, Name: key, - Help: fmt.Sprintf("%s %s from /proc/net/sockstat.", protocol, name), + Help: fmt.Sprintf("Number of %s sockets in state %s.", protocol, name), }, ) } diff --git a/collector/stat_linux.go b/collector/stat_linux.go index 80ceb3d8..9eb83c6c 100644 --- a/collector/stat_linux.go +++ b/collector/stat_linux.go @@ -12,8 +12,7 @@ import ( ) const ( - procStat = "/proc/stat" - userHz = 100 + userHz = 100 ) type statCollector struct { @@ -75,9 +74,9 @@ func NewStatCollector() (Collector, error) { }, nil } -// Expose a variety of stats from /proc/stats. +// Expose kernel and system statistics. func (c *statCollector) Update(ch chan<- prometheus.Metric) (err error) { - file, err := os.Open(procStat) + file, err := os.Open(procFilePath("stat")) if err != nil { return err } diff --git a/collector/tcpstat_linux.go b/collector/tcpstat_linux.go index 2753b45c..8e4f15ef 100644 --- a/collector/tcpstat_linux.go +++ b/collector/tcpstat_linux.go @@ -13,11 +13,6 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -const ( - procTCPStat = "/proc/net/tcp" - procTCP6Stat = "/proc/net/tcp6" -) - type TCPConnectionState int const ( @@ -58,14 +53,15 @@ func NewTCPStatCollector() (Collector, error) { } func (c *tcpStatCollector) Update(ch chan<- prometheus.Metric) (err error) { - tcpStats, err := getTCPStats(procTCPStat) + tcpStats, err := getTCPStats(procFilePath("net/tcp")) if err != nil { return fmt.Errorf("couldn't get tcpstats: %s", err) } // if enabled ipv6 system - if _, hasIPv6 := os.Stat(procTCP6Stat); hasIPv6 == nil { - tcp6Stats, err := getTCPStats(procTCP6Stat) + tcp6File := procFilePath("net/tcp6") + if _, hasIPv6 := os.Stat(tcp6File); hasIPv6 == nil { + tcp6Stats, err := getTCPStats(tcp6File) if err != nil { return fmt.Errorf("couldn't get tcp6stats: %s", err) }