From 7569c6ce23af643dea396626f2b1015a46c79f76 Mon Sep 17 00:00:00 2001 From: Ken Herner Date: Tue, 8 Sep 2015 10:14:18 -0400 Subject: [PATCH] Initial implementation of file-nr Fixed file-nr update function Fixed file-nr test case Fixed file-nr test case again Fixed file-nr separator to tab Updated file-nr to filenr. Updated file-nr to filenr. Fixed file-nr test cases, added comments Remove reporting the second value from file-nr as it will alwasy be zero in linux 2.6 and greator Renaming file-nr to filefd Updated build constraint Updates and code cleanup for filefd. Updated enabledCollectors with the correct name for filefd Fixed filefd test wording --- collector/filefd_linux.go | 84 ++++++++++++++++++++++++++++++++++ collector/filefd_linux_test.go | 27 +++++++++++ collector/fixtures/file-nr | 1 + node_exporter.go | 2 +- 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 collector/filefd_linux.go create mode 100644 collector/filefd_linux_test.go create mode 100644 collector/fixtures/file-nr diff --git a/collector/filefd_linux.go b/collector/filefd_linux.go new file mode 100644 index 00000000..47a50647 --- /dev/null +++ b/collector/filefd_linux.go @@ -0,0 +1,84 @@ +// +build !nofilefd + +package collector + +import ( + "bufio" + "fmt" + "github.com/prometheus/client_golang/prometheus" + "io" + "os" + "strconv" + "strings" +) + +const ( + procFileFDStat = "/proc/sys/fs/file-nr" + fileFDStatSubsystem = "filefd" +) + +type fileFDStatCollector struct { + metrics map[string]prometheus.Gauge +} + +func init() { + Factories[fileFDStatSubsystem] = NewFileFDStatCollector +} + +// NewFileFDStatCollector returns a new Collector exposing file-nr stats. +func NewFileFDStatCollector() (Collector, error) { + return &fileFDStatCollector{ + metrics: map[string]prometheus.Gauge{}, + }, nil +} + +func (c *fileFDStatCollector) Update(ch chan<- prometheus.Metric) (err error) { + fileFDStat, err := getFileFDStats(procFileFDStat) + if err != nil { + return fmt.Errorf("couldn't get file-nr: %s", err) + } + for name, value := range fileFDStat { + if _, ok := c.metrics[name]; !ok { + c.metrics[name] = prometheus.NewGauge( + prometheus.GaugeOpts{ + Namespace: Namespace, + Subsystem: fileFDStatSubsystem, + Name: name, + Help: fmt.Sprintf("filefd %s from %s.", name, procFileFDStat), + }, + ) + v, err := strconv.ParseFloat(value, 64) + if err != nil { + return fmt.Errorf("invalid value %s in file-nr: %s", value, err) + } + c.metrics[name].Set(v) + } + } + for _, m := range c.metrics { + m.Collect(ch) + } + return err +} + +func getFileFDStats(fileName string) (map[string]string, error) { + file, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer file.Close() + return parseFileFDStats(file, fileName) +} + +func parseFileFDStats(r io.Reader, fileName string) (map[string]string, error) { + var scanner = bufio.NewScanner(r) + scanner.Scan() + // The file-nr proc file is separated by tabs, not spaces. + line := strings.Split(string(scanner.Text()), "\u0009") + var fileFDStat = map[string]string{} + // The file-nr proc is only 1 line with 3 values. + fileFDStat["allocated"] = line[0] + // The second value is skipped as it will alwasy be zero in linux 2.6. + fileFDStat["maximum"] = line[2] + + return fileFDStat, nil +} diff --git a/collector/filefd_linux_test.go b/collector/filefd_linux_test.go new file mode 100644 index 00000000..31e4811d --- /dev/null +++ b/collector/filefd_linux_test.go @@ -0,0 +1,27 @@ +package collector + +import ( + "os" + "testing" +) + +func TestFileFDStats(t *testing.T) { + file, err := os.Open("fixtures/file-nr") + if err != nil { + t.Fatal(err) + } + defer file.Close() + + fileFDStats, err := parseFileFDStats(file, fileName) + if err != nil { + t.Fatal(err) + } + + if want, got := "1024", fileFDStats["allocated"]; want != got { + t.Errorf("want filefd allocated %s, got %s", want, got) + } + + if want, got := "1631329", fileFDStats["maximum"]; want != got { + t.Errorf("want filefd maximum %s, got %s", want, got) + } +} diff --git a/collector/fixtures/file-nr b/collector/fixtures/file-nr new file mode 100644 index 00000000..d5a4f874 --- /dev/null +++ b/collector/fixtures/file-nr @@ -0,0 +1 @@ +1024 0 1631329 diff --git a/node_exporter.go b/node_exporter.go index 56f2d2d2..890e5273 100644 --- a/node_exporter.go +++ b/node_exporter.go @@ -28,7 +28,7 @@ var ( memProfile = flag.String("debug.memprofile-file", "", "Write memory profile to this file upon receipt of SIGUSR1.") listenAddress = flag.String("web.listen-address", ":9100", "Address on which to expose metrics and web interface.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") - enabledCollectors = flag.String("collectors.enabled", "diskstats,filesystem,loadavg,meminfo,stat,textfile,time,netdev,netstat,sockstat", "Comma-separated list of collectors to use.") + enabledCollectors = flag.String("collectors.enabled", "diskstats,filesystem,loadavg,meminfo,stat,textfile,time,netdev,netstat,sockstat,filefd", "Comma-separated list of collectors to use.") printCollectors = flag.Bool("collectors.print", false, "If true, print available collectors and exit.") authUser = flag.String("auth.user", "", "Username for basic auth.") authPass = flag.String("auth.pass", "", "Password for basic auth.")