mirror of
https://github.com/prometheus/node_exporter.git
synced 2025-03-05 21:00:12 -08:00
Early init of procfs (#1315)
Minor change to match naming convention in other collectors. Initialize the proc or sys FS instance once while initializing each collector instead of re-creating for each metric update. Signed-off-by: Paul Gier <pgier@redhat.com>
This commit is contained in:
parent
fbe390709f
commit
b1298677aa
|
@ -30,6 +30,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type buddyinfoCollector struct {
|
type buddyinfoCollector struct {
|
||||||
|
fs procfs.FS
|
||||||
desc *prometheus.Desc
|
desc *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,18 +45,17 @@ func NewBuddyinfoCollector() (Collector, error) {
|
||||||
"Count of free blocks according to size.",
|
"Count of free blocks according to size.",
|
||||||
[]string{"node", "zone", "size"}, nil,
|
[]string{"node", "zone", "size"}, nil,
|
||||||
)
|
)
|
||||||
return &buddyinfoCollector{desc}, nil
|
fs, err := procfs.NewFS(*procPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open procfs: %v", err)
|
||||||
|
}
|
||||||
|
return &buddyinfoCollector{fs, desc}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
buddyInfo, err := c.fs.NewBuddyInfo()
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open procfs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
buddyInfo, err := fs.NewBuddyInfo()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't get buddyinfo: %s", err)
|
return fmt.Errorf("couldn't get buddyinfo: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type cpuCollector struct {
|
type cpuCollector struct {
|
||||||
|
fs procfs.FS
|
||||||
cpu *prometheus.Desc
|
cpu *prometheus.Desc
|
||||||
cpuGuest *prometheus.Desc
|
cpuGuest *prometheus.Desc
|
||||||
cpuCoreThrottle *prometheus.Desc
|
cpuCoreThrottle *prometheus.Desc
|
||||||
|
@ -38,7 +39,12 @@ func init() {
|
||||||
|
|
||||||
// NewCPUCollector returns a new Collector exposing kernel/system statistics.
|
// NewCPUCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewCPUCollector() (Collector, error) {
|
func NewCPUCollector() (Collector, error) {
|
||||||
|
fs, err := procfs.NewFS(*procPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open procfs: %v", err)
|
||||||
|
}
|
||||||
return &cpuCollector{
|
return &cpuCollector{
|
||||||
|
fs: fs,
|
||||||
cpu: nodeCPUSecondsDesc,
|
cpu: nodeCPUSecondsDesc,
|
||||||
cpuGuest: prometheus.NewDesc(
|
cpuGuest: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "guest_seconds_total"),
|
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "guest_seconds_total"),
|
||||||
|
@ -149,11 +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 {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
stats, err := c.fs.NewStat()
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open procfs: %v", err)
|
|
||||||
}
|
|
||||||
stats, err := fs.NewStat()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type cpuFreqCollector struct {
|
type cpuFreqCollector struct {
|
||||||
|
fs sysfs.FS
|
||||||
cpuFreq *prometheus.Desc
|
cpuFreq *prometheus.Desc
|
||||||
cpuFreqMin *prometheus.Desc
|
cpuFreqMin *prometheus.Desc
|
||||||
cpuFreqMax *prometheus.Desc
|
cpuFreqMax *prometheus.Desc
|
||||||
|
@ -37,7 +38,13 @@ func init() {
|
||||||
|
|
||||||
// NewCPUFreqCollector returns a new Collector exposing kernel/system statistics.
|
// NewCPUFreqCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewCPUFreqCollector() (Collector, error) {
|
func NewCPUFreqCollector() (Collector, error) {
|
||||||
|
fs, err := sysfs.NewFS(*sysPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open sysfs: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return &cpuFreqCollector{
|
return &cpuFreqCollector{
|
||||||
|
fs: fs,
|
||||||
cpuFreq: prometheus.NewDesc(
|
cpuFreq: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"),
|
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"),
|
||||||
"Current cpu thread frequency in hertz.",
|
"Current cpu thread frequency in hertz.",
|
||||||
|
@ -73,12 +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 {
|
||||||
fs, err := sysfs.NewFS(*sysPath)
|
cpuFreqs, err := c.fs.NewSystemCpufreq()
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open sysfs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuFreqs, err := fs.NewSystemCpufreq()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ func newIPVSCollector() (*ipvsCollector, error) {
|
||||||
|
|
||||||
c.fs, err = procfs.NewFS(*procPath)
|
c.fs, err = procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to open procfs: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.connections = typedDesc{prometheus.NewDesc(
|
c.connections = typedDesc{prometheus.NewDesc(
|
||||||
|
|
|
@ -30,6 +30,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type netClassCollector struct {
|
type netClassCollector struct {
|
||||||
|
fs sysfs.FS
|
||||||
subsystem string
|
subsystem string
|
||||||
ignoredDevicesPattern *regexp.Regexp
|
ignoredDevicesPattern *regexp.Regexp
|
||||||
metricDescs map[string]*prometheus.Desc
|
metricDescs map[string]*prometheus.Desc
|
||||||
|
@ -41,8 +42,13 @@ func init() {
|
||||||
|
|
||||||
// NewNetClassCollector returns a new Collector exposing network class stats.
|
// NewNetClassCollector returns a new Collector exposing network class stats.
|
||||||
func NewNetClassCollector() (Collector, error) {
|
func NewNetClassCollector() (Collector, error) {
|
||||||
|
fs, err := sysfs.NewFS(*sysPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open sysfs: %v", err)
|
||||||
|
}
|
||||||
pattern := regexp.MustCompile(*netclassIgnoredDevices)
|
pattern := regexp.MustCompile(*netclassIgnoredDevices)
|
||||||
return &netClassCollector{
|
return &netClassCollector{
|
||||||
|
fs: fs,
|
||||||
subsystem: "network",
|
subsystem: "network",
|
||||||
ignoredDevicesPattern: pattern,
|
ignoredDevicesPattern: pattern,
|
||||||
metricDescs: map[string]*prometheus.Desc{},
|
metricDescs: map[string]*prometheus.Desc{},
|
||||||
|
@ -50,7 +56,7 @@ func NewNetClassCollector() (Collector, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *netClassCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *netClassCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
netClass, err := getNetClassInfo(c.ignoredDevicesPattern)
|
netClass, err := c.getNetClassInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get net class info: %s", err)
|
return fmt.Errorf("could not get net class info: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -162,19 +168,15 @@ func pushMetric(ch chan<- prometheus.Metric, subsystem string, name string, valu
|
||||||
ch <- prometheus.MustNewConstMetric(fieldDesc, valueType, float64(value), ifaceName)
|
ch <- prometheus.MustNewConstMetric(fieldDesc, valueType, float64(value), ifaceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNetClassInfo(ignore *regexp.Regexp) (sysfs.NetClass, error) {
|
func (c *netClassCollector) getNetClassInfo() (sysfs.NetClass, error) {
|
||||||
fs, err := sysfs.NewFS(*sysPath)
|
netClass, err := c.fs.NewNetClass()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
netClass, err := fs.NewNetClass()
|
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
for device := range netClass {
|
for device := range netClass {
|
||||||
if ignore.MatchString(device) {
|
if c.ignoredDevicesPattern.MatchString(device) {
|
||||||
delete(netClass, device)
|
delete(netClass, device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type processCollector struct {
|
type processCollector struct {
|
||||||
|
fs procfs.FS
|
||||||
threadAlloc *prometheus.Desc
|
threadAlloc *prometheus.Desc
|
||||||
threadLimit *prometheus.Desc
|
threadLimit *prometheus.Desc
|
||||||
procsState *prometheus.Desc
|
procsState *prometheus.Desc
|
||||||
|
@ -38,8 +39,13 @@ func init() {
|
||||||
|
|
||||||
// NewProcessStatCollector returns a new Collector exposing process data read from the proc filesystem.
|
// NewProcessStatCollector returns a new Collector exposing process data read from the proc filesystem.
|
||||||
func NewProcessStatCollector() (Collector, error) {
|
func NewProcessStatCollector() (Collector, error) {
|
||||||
|
fs, err := procfs.NewFS(*procPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open procfs: %v", err)
|
||||||
|
}
|
||||||
subsystem := "processes"
|
subsystem := "processes"
|
||||||
return &processCollector{
|
return &processCollector{
|
||||||
|
fs: fs,
|
||||||
threadAlloc: prometheus.NewDesc(
|
threadAlloc: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, subsystem, "threads"),
|
prometheus.BuildFQName(namespace, subsystem, "threads"),
|
||||||
"Allocated threads in system",
|
"Allocated threads in system",
|
||||||
|
@ -63,39 +69,35 @@ func NewProcessStatCollector() (Collector, error) {
|
||||||
),
|
),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
func (t *processCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *processCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
pids, states, threads, err := getAllocatedThreads()
|
pids, states, threads, err := c.getAllocatedThreads()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to retrieve number of allocated threads: %q", err)
|
return fmt.Errorf("unable to retrieve number of allocated threads: %q", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(t.threadAlloc, prometheus.GaugeValue, float64(threads))
|
ch <- prometheus.MustNewConstMetric(c.threadAlloc, prometheus.GaugeValue, float64(threads))
|
||||||
maxThreads, err := readUintFromFile(procFilePath("sys/kernel/threads-max"))
|
maxThreads, err := readUintFromFile(procFilePath("sys/kernel/threads-max"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to retrieve limit number of threads: %q", err)
|
return fmt.Errorf("unable to retrieve limit number of threads: %q", err)
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(t.threadLimit, prometheus.GaugeValue, float64(maxThreads))
|
ch <- prometheus.MustNewConstMetric(c.threadLimit, prometheus.GaugeValue, float64(maxThreads))
|
||||||
|
|
||||||
for state := range states {
|
for state := range states {
|
||||||
ch <- prometheus.MustNewConstMetric(t.procsState, prometheus.GaugeValue, float64(states[state]), state)
|
ch <- prometheus.MustNewConstMetric(c.procsState, prometheus.GaugeValue, float64(states[state]), state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pidM, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
|
pidM, err := readUintFromFile(procFilePath("sys/kernel/pid_max"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to retrieve limit number of maximum pids alloved: %q", err)
|
return fmt.Errorf("unable to retrieve limit number of maximum pids alloved: %q", err)
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(t.pidUsed, prometheus.GaugeValue, float64(pids))
|
ch <- prometheus.MustNewConstMetric(c.pidUsed, prometheus.GaugeValue, float64(pids))
|
||||||
ch <- prometheus.MustNewConstMetric(t.pidMax, prometheus.GaugeValue, float64(pidM))
|
ch <- prometheus.MustNewConstMetric(c.pidMax, prometheus.GaugeValue, float64(pidM))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllocatedThreads() (int, map[string]int32, int, error) {
|
func (c *processCollector) getAllocatedThreads() (int, map[string]int32, int, error) {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
p, err := c.fs.AllProcs()
|
||||||
if err != nil {
|
|
||||||
return 0, nil, 0, err
|
|
||||||
}
|
|
||||||
p, err := fs.AllProcs()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, 0, err
|
return 0, nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ package collector
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"github.com/prometheus/procfs"
|
||||||
|
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadProcessStatus(t *testing.T) {
|
func TestReadProcessStatus(t *testing.T) {
|
||||||
|
@ -26,7 +27,12 @@ func TestReadProcessStatus(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
want := 1
|
want := 1
|
||||||
pids, states, threads, err := getAllocatedThreads()
|
fs, err := procfs.NewFS(*procPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to open procfs: %v", err)
|
||||||
|
}
|
||||||
|
c := processCollector{fs: fs}
|
||||||
|
pids, states, threads, err := c.getAllocatedThreads()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot retrieve data from procfs getAllocatedThreads function: %v ", err)
|
t.Fatalf("Cannot retrieve data from procfs getAllocatedThreads function: %v ", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type statCollector struct {
|
type statCollector struct {
|
||||||
|
fs procfs.FS
|
||||||
intr *prometheus.Desc
|
intr *prometheus.Desc
|
||||||
ctxt *prometheus.Desc
|
ctxt *prometheus.Desc
|
||||||
forks *prometheus.Desc
|
forks *prometheus.Desc
|
||||||
|
@ -38,7 +39,12 @@ func init() {
|
||||||
|
|
||||||
// NewStatCollector returns a new Collector exposing kernel/system statistics.
|
// NewStatCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewStatCollector() (Collector, error) {
|
func NewStatCollector() (Collector, error) {
|
||||||
|
fs, err := procfs.NewFS(*procPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open procfs: %v", err)
|
||||||
|
}
|
||||||
return &statCollector{
|
return &statCollector{
|
||||||
|
fs: fs,
|
||||||
intr: prometheus.NewDesc(
|
intr: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "", "intr_total"),
|
prometheus.BuildFQName(namespace, "", "intr_total"),
|
||||||
"Total number of interrupts serviced.",
|
"Total number of interrupts serviced.",
|
||||||
|
@ -74,11 +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 {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
stats, err := c.fs.NewStat()
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open procfs: %v", err)
|
|
||||||
}
|
|
||||||
stats, err := fs.NewStat()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue