mirror of
https://github.com/prometheus/node_exporter.git
synced 2025-01-12 22:37:32 -08:00
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.
This commit is contained in:
parent
cf3aa37f1a
commit
20b551ab2b
|
@ -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{}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])]
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
17
collector/procpath.go
Normal file
17
collector/procpath.go
Normal file
|
@ -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)
|
||||
}
|
|
@ -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),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue