update procfs to v0.0.2 (#1376)

Signed-off-by: Paul Gier <pgier@redhat.com>
pull/1378/head
Paul Gier 2019-06-12 13:47:16 -05:00 committed by Ben Kochie
parent 0759c0ac01
commit 2bc133cd48
33 changed files with 167 additions and 172 deletions

View File

@ -55,7 +55,7 @@ func NewBuddyinfoCollector() (Collector, error) {
// Update calls (*buddyinfoCollector).getBuddyInfo to get the platform specific // Update calls (*buddyinfoCollector).getBuddyInfo to get the platform specific
// buddyinfo metrics. // buddyinfo metrics.
func (c *buddyinfoCollector) Update(ch chan<- prometheus.Metric) error { func (c *buddyinfoCollector) Update(ch chan<- prometheus.Metric) error {
buddyInfo, err := c.fs.NewBuddyInfo() buddyInfo, err := c.fs.BuddyInfo()
if err != nil { if err != nil {
return fmt.Errorf("couldn't get buddyinfo: %s", err) return fmt.Errorf("couldn't get buddyinfo: %s", err)
} }

View File

@ -155,7 +155,7 @@ func (c *cpuCollector) updateThermalThrottle(ch chan<- prometheus.Metric) error
// updateStat reads /proc/stat through procfs and exports cpu related metrics. // updateStat reads /proc/stat through procfs and exports cpu related metrics.
func (c *cpuCollector) updateStat(ch chan<- prometheus.Metric) error { func (c *cpuCollector) updateStat(ch chan<- prometheus.Metric) error {
stats, err := c.fs.NewStat() stats, err := c.fs.Stat()
if err != nil { if err != nil {
return err return err
} }

View File

@ -80,7 +80,7 @@ func NewCPUFreqCollector() (Collector, error) {
// Update implements Collector and exposes cpu related metrics from /proc/stat and /sys/.../cpu/. // Update implements Collector and exposes cpu related metrics from /proc/stat and /sys/.../cpu/.
func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error { func (c *cpuFreqCollector) Update(ch chan<- prometheus.Metric) error {
cpuFreqs, err := c.fs.NewSystemCpufreq() cpuFreqs, err := c.fs.SystemCpufreq()
if err != nil { if err != nil {
return err return err
} }

View File

@ -106,7 +106,7 @@ func newIPVSCollector() (*ipvsCollector, error) {
} }
func (c *ipvsCollector) Update(ch chan<- prometheus.Metric) error { func (c *ipvsCollector) Update(ch chan<- prometheus.Metric) error {
ipvsStats, err := c.fs.NewIPVSStats() ipvsStats, err := c.fs.IPVSStats()
if err != nil { if err != nil {
// Cannot access ipvs metrics, report no error. // Cannot access ipvs metrics, report no error.
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -121,7 +121,7 @@ func (c *ipvsCollector) Update(ch chan<- prometheus.Metric) error {
ch <- c.incomingBytes.mustNewConstMetric(float64(ipvsStats.IncomingBytes)) ch <- c.incomingBytes.mustNewConstMetric(float64(ipvsStats.IncomingBytes))
ch <- c.outgoingBytes.mustNewConstMetric(float64(ipvsStats.OutgoingBytes)) ch <- c.outgoingBytes.mustNewConstMetric(float64(ipvsStats.OutgoingBytes))
backendStats, err := c.fs.NewIPVSBackendStatus() backendStats, err := c.fs.IPVSBackendStatus()
if err != nil { if err != nil {
return fmt.Errorf("could not get backend status: %s", err) return fmt.Errorf("could not get backend status: %s", err)
} }

View File

@ -169,7 +169,7 @@ func pushMetric(ch chan<- prometheus.Metric, subsystem string, name string, valu
} }
func (c *netClassCollector) getNetClassInfo() (sysfs.NetClass, error) { func (c *netClassCollector) getNetClassInfo() (sysfs.NetClass, error) {
netClass, err := c.fs.NewNetClass() netClass, err := c.fs.NetClass()
if err != nil { if err != nil {
return netClass, fmt.Errorf("error obtaining net class info: %s", err) return netClass, fmt.Errorf("error obtaining net class info: %s", err)

View File

@ -82,7 +82,7 @@ func NewPressureStatsCollector() (Collector, error) {
func (c *pressureStatsCollector) Update(ch chan<- prometheus.Metric) error { func (c *pressureStatsCollector) Update(ch chan<- prometheus.Metric) error {
for _, res := range psiResources { for _, res := range psiResources {
log.Debugf("collecting statistics for resource: %s", res) log.Debugf("collecting statistics for resource: %s", res)
vals, err := c.fs.NewPSIStatsForResource(res) vals, err := c.fs.PSIStatsForResource(res)
if err != nil { if err != nil {
log.Debug("pressure information is unavailable, you need a Linux kernel >= 4.20 and/or CONFIG_PSI enabled for your kernel") log.Debug("pressure information is unavailable, you need a Linux kernel >= 4.20 and/or CONFIG_PSI enabled for your kernel")
return nil return nil

View File

@ -105,7 +105,7 @@ func (c *processCollector) getAllocatedThreads() (int, map[string]int32, int, er
thread := 0 thread := 0
procStates := make(map[string]int32) procStates := make(map[string]int32)
for _, pid := range p { for _, pid := range p {
stat, err := pid.NewStat() stat, err := pid.Stat()
// PIDs can vanish between getting the list and getting stats. // PIDs can vanish between getting the list and getting stats.
if os.IsNotExist(err) { if os.IsNotExist(err) {
log.Debugf("file not found when retrieving stats for pid %v: %q", pid, err) log.Debugf("file not found when retrieving stats for pid %v: %q", pid, err)

View File

@ -80,7 +80,7 @@ func NewStatCollector() (Collector, error) {
// Update implements Collector and exposes kernel and system statistics. // Update implements Collector and exposes kernel and system statistics.
func (c *statCollector) Update(ch chan<- prometheus.Metric) error { func (c *statCollector) Update(ch chan<- prometheus.Metric) error {
stats, err := c.fs.NewStat() stats, err := c.fs.Stat()
if err != nil { if err != nil {
return err return err
} }

2
go.mod
View File

@ -18,7 +18,7 @@ require (
github.com/prometheus/client_golang v0.9.2 github.com/prometheus/client_golang v0.9.2
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90
github.com/prometheus/common v0.3.0 github.com/prometheus/common v0.3.0
github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae github.com/prometheus/procfs v0.0.2
github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745 github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745
github.com/sirupsen/logrus v1.4.2 // indirect github.com/sirupsen/logrus v1.4.2 // indirect
github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a

4
go.sum
View File

@ -65,8 +65,8 @@ github.com/prometheus/common v0.3.0 h1:taZ4h8Tkxv2kNyoSctBvfXEHmBmxrwmIidZTIaHon
github.com/prometheus/common v0.3.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.3.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae h1:kF6Y/ES9NQmW3t400V0XH+lO1jqvCpXBC1XoLDkvuMM= github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745 h1:IuH7WumZNax0D+rEqmy2TyhKCzrtMGqbZO0b8rO00JA= github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745 h1:IuH7WumZNax0D+rEqmy2TyhKCzrtMGqbZO0b8rO00JA=
github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8= github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=

View File

@ -38,9 +38,13 @@ func TestFileDescriptorLeak(t *testing.T) {
if _, err := os.Stat(binary); err != nil { if _, err := os.Stat(binary); err != nil {
t.Skipf("node_exporter binary not available, try to run `make build` first: %s", err) t.Skipf("node_exporter binary not available, try to run `make build` first: %s", err)
} }
if _, err := procfs.NewStat(); err != nil { fs, err := procfs.NewDefaultFS()
if err != nil {
t.Skipf("proc filesystem is not available, but currently required to read number of open file descriptors: %s", err) t.Skipf("proc filesystem is not available, but currently required to read number of open file descriptors: %s", err)
} }
if _, err := fs.Stat(); err != nil {
t.Errorf("unable to read process stats: %s", err)
}
exporter := exec.Command(binary, "--web.listen-address", address) exporter := exec.Command(binary, "--web.listen-address", address)
test := func(pid int) error { test := func(pid int) error {

View File

@ -19,7 +19,14 @@ point is initialized, and then the stat information is read.
```go ```go
fs, err := procfs.NewFS("/proc") fs, err := procfs.NewFS("/proc")
stats, err := fs.NewStat() stats, err := fs.Stat()
```
Some sub-packages such as `blockdevice`, require access to both the proc and sys filesystems.
```go
fs, err := blockdevice.NewFS("/proc", "/sys")
stats, err := fs.ProcDiskstats()
``` ```
## Building and Testing ## Building and Testing
@ -30,7 +37,7 @@ changes to the library, the `make test` command can be used to run the API test
### Updating Test Fixtures ### Updating Test Fixtures
The procfs library includes a set of test fixtures which include many example files from The procfs library includes a set of test fixtures which include many example files from
the `/proc` and `/sys` filesystems. These fixtures are included as a ttar (text tar) file the `/proc` and `/sys` filesystems. These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file
which is extracted automatically during testing. To add/update the test fixtures, first which is extracted automatically during testing. To add/update the test fixtures, first
ensure the `fixtures` directory is up to date by removing the existing directory and then ensure the `fixtures` directory is up to date by removing the existing directory and then
extracting the ttar file using `make fixtures/.unpacked` or just `make test`. extracting the ttar file using `make fixtures/.unpacked` or just `make test`.

View File

@ -32,6 +32,12 @@ type FS struct {
sys *fs.FS sys *fs.FS
} }
// NewDefaultFS returns a new Bcache using the default sys fs mount point. It will error
// if the mount point can't be read.
func NewDefaultFS() (FS, error) {
return NewFS(fs.DefaultSysMountPoint)
}
// NewFS returns a new Bcache using the given sys fs mount point. It will error // NewFS returns a new Bcache using the given sys fs mount point. It will error
// if the mount point can't be read. // if the mount point can't be read.
func NewFS(mountPoint string) (FS, error) { func NewFS(mountPoint string) (FS, error) {

View File

@ -31,18 +31,8 @@ type BuddyInfo struct {
Sizes []float64 Sizes []float64
} }
// NewBuddyInfo reads the buddyinfo statistics.
func NewBuddyInfo() ([]BuddyInfo, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return nil, err
}
return fs.NewBuddyInfo()
}
// NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem. // NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem.
func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) { func (fs FS) BuddyInfo() ([]BuddyInfo, error) {
file, err := os.Open(fs.proc.Path("buddyinfo")) file, err := os.Open(fs.proc.Path("buddyinfo"))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -26,6 +26,12 @@ type FS struct {
// DefaultMountPoint is the common mount point of the proc filesystem. // DefaultMountPoint is the common mount point of the proc filesystem.
const DefaultMountPoint = fs.DefaultProcMountPoint const DefaultMountPoint = fs.DefaultProcMountPoint
// NewDefaultFS returns a new proc FS mounted under the default proc mountPoint.
// It will error if the mount point directory can't be read or is a file.
func NewDefaultFS() (FS, error) {
return NewFS(DefaultMountPoint)
}
// NewFS returns a new proc FS mounted under the given proc mountPoint. It will error // NewFS returns a new proc FS mounted under the given proc mountPoint. It will error
// if the mount point directory can't be read or is a file. // if the mount point directory can't be read or is a file.
func NewFS(mountPoint string) (FS, error) { func NewFS(mountPoint string) (FS, error) {

View File

@ -62,18 +62,8 @@ type IPVSBackendStatus struct {
Weight uint64 Weight uint64
} }
// NewIPVSStats reads the IPVS statistics. // IPVSStats reads the IPVS statistics from the specified `proc` filesystem.
func NewIPVSStats() (IPVSStats, error) { func (fs FS) IPVSStats() (IPVSStats, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return IPVSStats{}, err
}
return fs.NewIPVSStats()
}
// NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem.
func (fs FS) NewIPVSStats() (IPVSStats, error) {
file, err := os.Open(fs.proc.Path("net/ip_vs_stats")) file, err := os.Open(fs.proc.Path("net/ip_vs_stats"))
if err != nil { if err != nil {
return IPVSStats{}, err return IPVSStats{}, err
@ -131,18 +121,8 @@ func parseIPVSStats(file io.Reader) (IPVSStats, error) {
return stats, nil return stats, nil
} }
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs. // IPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) { func (fs FS) IPVSBackendStatus() ([]IPVSBackendStatus, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return []IPVSBackendStatus{}, err
}
return fs.NewIPVSBackendStatus()
}
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
file, err := os.Open(fs.proc.Path("net/ip_vs")) file, err := os.Open(fs.proc.Path("net/ip_vs"))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -42,64 +42,64 @@ type MDStat struct {
BlocksSynced int64 BlocksSynced int64
} }
// ParseMDStat parses an mdstat-file and returns a struct with the relevant infos. // MDStat parses an mdstat-file (/proc/mdstat) and returns a slice of
func (fs FS) ParseMDStat() (mdstates []MDStat, err error) { // structs containing the relevant info. More information available here:
mdStatusFilePath := fs.proc.Path("mdstat") // https://raid.wiki.kernel.org/index.php/Mdstat
content, err := ioutil.ReadFile(mdStatusFilePath) func (fs FS) MDStat() ([]MDStat, error) {
data, err := ioutil.ReadFile(fs.proc.Path("mdstat"))
if err != nil { if err != nil {
return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) return nil, fmt.Errorf("error parsing mdstat %s: %s", fs.proc.Path("mdstat"), err)
}
mdstat, err := parseMDStat(data)
if err != nil {
return nil, fmt.Errorf("error parsing mdstat %s: %s", fs.proc.Path("mdstat"), err)
}
return mdstat, nil
} }
mdStates := []MDStat{} // parseMDStat parses data from mdstat file (/proc/mdstat) and returns a slice of
lines := strings.Split(string(content), "\n") // structs containing the relevant info.
func parseMDStat(mdstatData []byte) ([]MDStat, error) {
mdStats := []MDStat{}
lines := strings.Split(string(mdstatData), "\n")
for i, l := range lines { for i, l := range lines {
if l == "" { if strings.TrimSpace(l) == "" || l[0] == ' ' ||
continue strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") {
}
if l[0] == ' ' {
continue
}
if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") {
continue continue
} }
mainLine := strings.Split(l, " ") deviceFields := strings.Fields(l)
if len(mainLine) < 3 { if len(deviceFields) < 3 {
return mdStates, fmt.Errorf("error parsing mdline: %s", l) return nil, fmt.Errorf("not enough fields in mdline (expected at least 3): %s", l)
} }
mdName := mainLine[0] mdName := deviceFields[0]
activityState := mainLine[2] activityState := deviceFields[2]
if len(lines) <= i+3 { if len(lines) <= i+3 {
return mdStates, fmt.Errorf( return mdStats, fmt.Errorf("missing lines for md device %s", mdName)
"error parsing %s: too few lines for md device %s",
mdStatusFilePath,
mdName,
)
} }
active, total, size, err := evalStatusline(lines[i+1]) active, total, size, err := evalStatusLine(lines[i+1])
if err != nil { if err != nil {
return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) return nil, err
} }
// j is the line number of the syncing-line. syncLineIdx := i + 2
j := i + 2
if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line
j = i + 3 syncLineIdx++
} }
// If device is syncing at the moment, get the number of currently // If device is recovering/syncing at the moment, get the number of currently
// synced bytes, otherwise that number equals the size of the device. // synced bytes, otherwise that number equals the size of the device.
syncedBlocks := size syncedBlocks := size
if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") { if strings.Contains(lines[syncLineIdx], "recovery") || strings.Contains(lines[syncLineIdx], "resync") {
syncedBlocks, err = evalBuildline(lines[j]) syncedBlocks, err = evalRecoveryLine(lines[syncLineIdx])
if err != nil { if err != nil {
return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) return nil, err
} }
} }
mdStates = append(mdStates, MDStat{ mdStats = append(mdStats, MDStat{
Name: mdName, Name: mdName,
ActivityState: activityState, ActivityState: activityState,
DisksActive: active, DisksActive: active,
@ -109,10 +109,10 @@ func (fs FS) ParseMDStat() (mdstates []MDStat, err error) {
}) })
} }
return mdStates, nil return mdStats, nil
} }
func evalStatusline(statusline string) (active, total, size int64, err error) { func evalStatusLine(statusline string) (active, total, size int64, err error) {
matches := statuslineRE.FindStringSubmatch(statusline) matches := statuslineRE.FindStringSubmatch(statusline)
if len(matches) != 4 { if len(matches) != 4 {
return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline) return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline)
@ -136,7 +136,7 @@ func evalStatusline(statusline string) (active, total, size int64, err error) {
return active, total, size, nil return active, total, size, nil
} }
func evalBuildline(buildline string) (syncedBlocks int64, err error) { func evalRecoveryLine(buildline string) (syncedBlocks int64, err error) {
matches := buildlineRE.FindStringSubmatch(buildline) matches := buildlineRE.FindStringSubmatch(buildline)
if len(matches) != 2 { if len(matches) != 2 {
return 0, fmt.Errorf("unexpected buildline: %s", buildline) return 0, fmt.Errorf("unexpected buildline: %s", buildline)

View File

@ -47,23 +47,13 @@ type NetDevLine struct {
// are interface names. // are interface names.
type NetDev map[string]NetDevLine type NetDev map[string]NetDevLine
// NewNetDev returns kernel/system statistics read from /proc/net/dev. // NetDev returns kernel/system statistics read from /proc/net/dev.
func NewNetDev() (NetDev, error) { func (fs FS) NetDev() (NetDev, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return nil, err
}
return fs.NewNetDev()
}
// NewNetDev returns kernel/system statistics read from /proc/net/dev.
func (fs FS) NewNetDev() (NetDev, error) {
return newNetDev(fs.proc.Path("net/dev")) return newNetDev(fs.proc.Path("net/dev"))
} }
// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev. // NetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
func (p Proc) NewNetDev() (NetDev, error) { func (p Proc) NetDev() (NetDev, error) {
return newNetDev(p.path("net/dev")) return newNetDev(p.path("net/dev"))
} }

View File

@ -275,6 +275,12 @@ type FS struct {
proc *fs.FS proc *fs.FS
} }
// NewDefaultFS returns a new FS mounted under the default mountPoint. It will error
// if the mount point can't be read.
func NewDefaultFS() (FS, error) {
return NewFS(fs.DefaultProcMountPoint)
}
// NewFS returns a new FS mounted under the given mountPoint. It will error // NewFS returns a new FS mounted under the given mountPoint. It will error
// if the mount point can't be read. // if the mount point can't be read.
func NewFS(mountPoint string) (FS, error) { func NewFS(mountPoint string) (FS, error) {

View File

@ -54,7 +54,7 @@ func NewProc(pid int) (Proc, error) {
if err != nil { if err != nil {
return Proc{}, err return Proc{}, err
} }
return fs.NewProc(pid) return fs.Proc(pid)
} }
// AllProcs returns a list of all currently available processes under /proc. // AllProcs returns a list of all currently available processes under /proc.
@ -76,11 +76,18 @@ func (fs FS) Self() (Proc, error) {
if err != nil { if err != nil {
return Proc{}, err return Proc{}, err
} }
return fs.NewProc(pid) return fs.Proc(pid)
} }
// NewProc returns a process for the given pid. // NewProc returns a process for the given pid.
//
// Deprecated: use fs.Proc() instead
func (fs FS) NewProc(pid int) (Proc, error) { func (fs FS) NewProc(pid int) (Proc, error) {
return fs.Proc(pid)
}
// Proc returns a process for the given pid.
func (fs FS) Proc(pid int) (Proc, error) {
if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil { if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil {
return Proc{}, err return Proc{}, err
} }

View File

@ -39,8 +39,8 @@ type ProcIO struct {
CancelledWriteBytes int64 CancelledWriteBytes int64
} }
// NewIO creates a new ProcIO instance from a given Proc instance. // IO creates a new ProcIO instance from a given Proc instance.
func (p Proc) NewIO() (ProcIO, error) { func (p Proc) IO() (ProcIO, error) {
pio := ProcIO{} pio := ProcIO{}
f, err := os.Open(p.path("io")) f, err := os.Open(p.path("io"))

View File

@ -78,7 +78,14 @@ var (
) )
// NewLimits returns the current soft limits of the process. // NewLimits returns the current soft limits of the process.
//
// Deprecated: use p.Limits() instead
func (p Proc) NewLimits() (ProcLimits, error) { func (p Proc) NewLimits() (ProcLimits, error) {
return p.Limits()
}
// Limits returns the current soft limits of the process.
func (p Proc) Limits() (ProcLimits, error) {
f, err := os.Open(p.path("limits")) f, err := os.Open(p.path("limits"))
if err != nil { if err != nil {
return ProcLimits{}, err return ProcLimits{}, err

View File

@ -29,9 +29,9 @@ type Namespace struct {
// Namespaces contains all of the namespaces that the process is contained in. // Namespaces contains all of the namespaces that the process is contained in.
type Namespaces map[string]Namespace type Namespaces map[string]Namespace
// NewNamespaces reads from /proc/<pid>/ns/* to get the namespaces of which the // Namespaces reads from /proc/<pid>/ns/* to get the namespaces of which the
// process is a member. // process is a member.
func (p Proc) NewNamespaces() (Namespaces, error) { func (p Proc) Namespaces() (Namespaces, error) {
d, err := os.Open(p.path("ns")) d, err := os.Open(p.path("ns"))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -51,19 +51,10 @@ type PSIStats struct {
Full *PSILine Full *PSILine
} }
// NewPSIStatsForResource reads pressure stall information for the specified // PSIStatsForResource reads pressure stall information for the specified
// resource. At time of writing this can be either "cpu", "memory" or "io". // resource from /proc/pressure/<resource>. At time of writing this can be
func NewPSIStatsForResource(resource string) (PSIStats, error) { // either "cpu", "memory" or "io".
fs, err := NewFS(DefaultMountPoint) func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) {
if err != nil {
return PSIStats{}, err
}
return fs.NewPSIStatsForResource(resource)
}
// NewPSIStatsForResource reads pressure stall information from /proc/pressure/<resource>
func (fs FS) NewPSIStatsForResource(resource string) (PSIStats, error) {
file, err := os.Open(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource))) file, err := os.Open(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource)))
if err != nil { if err != nil {
return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %s", resource) return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %s", resource)

View File

@ -105,7 +105,14 @@ type ProcStat struct {
} }
// NewStat returns the current status information of the process. // NewStat returns the current status information of the process.
//
// Deprecated: use NewStat() instead
func (p Proc) NewStat() (ProcStat, error) { func (p Proc) NewStat() (ProcStat, error) {
return p.Stat()
}
// Stat returns the current status information of the process.
func (p Proc) Stat() (ProcStat, error) {
f, err := os.Open(p.path("stat")) f, err := os.Open(p.path("stat"))
if err != nil { if err != nil {
return ProcStat{}, err return ProcStat{}, err
@ -178,7 +185,7 @@ func (s ProcStat) ResidentMemory() int {
// StartTime returns the unix timestamp of the process in seconds. // StartTime returns the unix timestamp of the process in seconds.
func (s ProcStat) StartTime() (float64, error) { func (s ProcStat) StartTime() (float64, error) {
fs := FS{proc: s.proc} fs := FS{proc: s.proc}
stat, err := fs.NewStat() stat, err := fs.Stat()
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@ -20,6 +20,8 @@ import (
"os" "os"
"strconv" "strconv"
"strings" "strings"
"github.com/prometheus/procfs/internal/fs"
) )
// CPUStat shows how much time the cpu spend in various stages. // CPUStat shows how much time the cpu spend in various stages.
@ -78,16 +80,6 @@ type Stat struct {
SoftIRQ SoftIRQStat SoftIRQ SoftIRQStat
} }
// NewStat returns kernel/system statistics read from /proc/stat.
func NewStat() (Stat, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return Stat{}, err
}
return fs.NewStat()
}
// Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum). // Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum).
func parseCPUStat(line string) (CPUStat, int64, error) { func parseCPUStat(line string) (CPUStat, int64, error) {
cpuStat := CPUStat{} cpuStat := CPUStat{}
@ -149,9 +141,29 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) {
return softIRQStat, total, nil return softIRQStat, total, nil
} }
// NewStat returns an information about current kernel/system statistics. // NewStat returns information about current cpu/process statistics.
func (fs FS) NewStat() (Stat, error) {
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
//
// Deprecated: use fs.Stat() instead
func NewStat() (Stat, error) {
fs, err := NewFS(fs.DefaultProcMountPoint)
if err != nil {
return Stat{}, err
}
return fs.Stat()
}
// NewStat returns information about current cpu/process statistics.
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
//
// Deprecated: use fs.Stat() instead
func (fs FS) NewStat() (Stat, error) {
return fs.Stat()
}
// Stat returns information about current cpu/process statistics.
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
func (fs FS) Stat() (Stat, error) {
f, err := os.Open(fs.proc.Path("stat")) f, err := os.Open(fs.proc.Path("stat"))
if err != nil { if err != nil {

View File

@ -102,18 +102,8 @@ type PowerSupply struct {
// The map keys are the names of the power supplies. // The map keys are the names of the power supplies.
type PowerSupplyClass map[string]PowerSupply type PowerSupplyClass map[string]PowerSupply
// NewPowerSupplyClass returns info for all power supplies read from /sys/class/power_supply/. // PowerSupplyClass returns info for all power supplies read from /sys/class/power_supply/.
func NewPowerSupplyClass() (PowerSupplyClass, error) { func (fs FS) PowerSupplyClass() (PowerSupplyClass, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return nil, err
}
return fs.NewPowerSupplyClass()
}
// NewPowerSupplyClass returns info for all power supplies read from /sys/class/power_supply/.
func (fs FS) NewPowerSupplyClass() (PowerSupplyClass, error) {
path := fs.sys.Path("class/power_supply") path := fs.sys.Path("class/power_supply")
powerSupplyDirs, err := ioutil.ReadDir(path) powerSupplyDirs, err := ioutil.ReadDir(path)

View File

@ -35,8 +35,8 @@ type ClassThermalZoneStats struct {
Passive *uint64 // Optional: millidegrees Celsius. (0 for disabled, > 1000 for enabled+value) Passive *uint64 // Optional: millidegrees Celsius. (0 for disabled, > 1000 for enabled+value)
} }
// NewClassThermalZoneStats returns Thermal Zone metrics for all zones. // ClassThermalZoneStats returns Thermal Zone metrics for all zones.
func (fs FS) NewClassThermalZoneStats() ([]ClassThermalZoneStats, error) { func (fs FS) ClassThermalZoneStats() ([]ClassThermalZoneStats, error) {
zones, err := filepath.Glob(fs.sys.Path("class/thermal/thermal_zone[0-9]*")) zones, err := filepath.Glob(fs.sys.Path("class/thermal/thermal_zone[0-9]*"))
if err != nil { if err != nil {
return []ClassThermalZoneStats{}, err return []ClassThermalZoneStats{}, err

View File

@ -26,6 +26,12 @@ type FS struct {
// DefaultMountPoint is the common mount point of the sys filesystem. // DefaultMountPoint is the common mount point of the sys filesystem.
const DefaultMountPoint = fs.DefaultSysMountPoint const DefaultMountPoint = fs.DefaultSysMountPoint
// NewDefaultFS returns a new FS mounted under the default mountPoint. It will error
// if the mount point can't be read.
func NewDefaultFS() (FS, error) {
return NewFS(DefaultMountPoint)
}
// NewFS returns a new FS mounted under the given mountPoint. It will error // NewFS returns a new FS mounted under the given mountPoint. It will error
// if the mount point can't be read. // if the mount point can't be read.
func NewFS(mountPoint string) (FS, error) { func NewFS(mountPoint string) (FS, error) {

View File

@ -65,16 +65,6 @@ type NetClassIface struct {
// are interface (iface) names. // are interface (iface) names.
type NetClass map[string]NetClassIface type NetClass map[string]NetClassIface
// NewNetClass returns info for all net interfaces (iface) read from /sys/class/net/<iface>.
func NewNetClass() (NetClass, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return nil, err
}
return fs.NewNetClass()
}
// NetClassDevices scans /sys/class/net for devices and returns them as a list of names. // NetClassDevices scans /sys/class/net for devices and returns them as a list of names.
func (fs FS) NetClassDevices() ([]string, error) { func (fs FS) NetClassDevices() ([]string, error) {
var res []string var res []string
@ -95,8 +85,8 @@ func (fs FS) NetClassDevices() ([]string, error) {
return res, nil return res, nil
} }
// NewNetClass returns info for all net interfaces (iface) read from /sys/class/net/<iface>. // NetClass returns info for all net interfaces (iface) read from /sys/class/net/<iface>.
func (fs FS) NewNetClass() (NetClass, error) { func (fs FS) NetClass() (NetClass, error) {
devices, err := fs.NetClassDevices() devices, err := fs.NetClassDevices()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -46,18 +46,8 @@ type SystemCPUCpufreqStats struct {
// TODO: Add thermal_throttle support. // TODO: Add thermal_throttle support.
// NewSystemCpufreq returns CPU frequency metrics for all CPUs. // SystemCpufreq returns CPU frequency metrics for all CPUs.
func NewSystemCpufreq() ([]SystemCPUCpufreqStats, error) { func (fs FS) SystemCpufreq() ([]SystemCPUCpufreqStats, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return []SystemCPUCpufreqStats{}, err
}
return fs.NewSystemCpufreq()
}
// NewSystemCpufreq returns CPU frequency metrics for all CPUs.
func (fs FS) NewSystemCpufreq() ([]SystemCPUCpufreqStats, error) {
var g errgroup.Group var g errgroup.Group
cpus, err := filepath.Glob(fs.sys.Path("devices/system/cpu/cpu[0-9]*")) cpus, err := filepath.Glob(fs.sys.Path("devices/system/cpu/cpu[0-9]*"))

View File

@ -177,6 +177,12 @@ type FS struct {
sys *fs.FS sys *fs.FS
} }
// NewDefaultFS returns a new XFS handle using the default proc and sys mountPoints.
// It will error if either of the mounts point can't be read.
func NewDefaultFS() (FS, error) {
return NewFS(fs.DefaultProcMountPoint, fs.DefaultSysMountPoint)
}
// NewFS returns a new XFS handle using the given proc and sys mountPoints. It will error // NewFS returns a new XFS handle using the given proc and sys mountPoints. It will error
// if either of the mounts point can't be read. // if either of the mounts point can't be read.
func NewFS(procMountPoint string, sysMountPoint string) (FS, error) { func NewFS(procMountPoint string, sysMountPoint string) (FS, error) {

2
vendor/modules.txt vendored
View File

@ -45,7 +45,7 @@ github.com/prometheus/common/version
github.com/prometheus/common/expfmt github.com/prometheus/common/expfmt
github.com/prometheus/common/model github.com/prometheus/common/model
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
# github.com/prometheus/procfs v0.0.0-20190529155944-65bdadfa96ae # github.com/prometheus/procfs v0.0.2
github.com/prometheus/procfs github.com/prometheus/procfs
github.com/prometheus/procfs/bcache github.com/prometheus/procfs/bcache
github.com/prometheus/procfs/nfs github.com/prometheus/procfs/nfs