diff options
author | Ken Herner <chosenken@gmail.com> | 2015-09-08 10:14:18 -0400 |
---|---|---|
committer | Ken Herner <chosenken@gmail.com> | 2015-09-10 10:27:58 -0400 |
commit | 7569c6ce23af643dea396626f2b1015a46c79f76 (patch) | |
tree | ca5161b08cc3d57f95adf64564443fcf91fd72e9 | |
parent | 6f17231e44466cf2059e0705628c9e5a95bbb8fd (diff) | |
download | prometheus_node_collector-7569c6ce23af643dea396626f2b1015a46c79f76.tar.bz2 prometheus_node_collector-7569c6ce23af643dea396626f2b1015a46c79f76.tar.xz prometheus_node_collector-7569c6ce23af643dea396626f2b1015a46c79f76.zip |
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
-rw-r--r-- | collector/filefd_linux.go | 84 | ||||
-rw-r--r-- | collector/filefd_linux_test.go | 27 | ||||
-rw-r--r-- | collector/fixtures/file-nr | 1 | ||||
-rw-r--r-- | node_exporter.go | 2 |
4 files changed, 113 insertions, 1 deletions
diff --git a/collector/filefd_linux.go b/collector/filefd_linux.go new file mode 100644 index 0000000..47a5064 --- /dev/null +++ b/collector/filefd_linux.go | |||
@@ -0,0 +1,84 @@ | |||
1 | // +build !nofilefd | ||
2 | |||
3 | package collector | ||
4 | |||
5 | import ( | ||
6 | "bufio" | ||
7 | "fmt" | ||
8 | "github.com/prometheus/client_golang/prometheus" | ||
9 | "io" | ||
10 | "os" | ||
11 | "strconv" | ||
12 | "strings" | ||
13 | ) | ||
14 | |||
15 | const ( | ||
16 | procFileFDStat = "/proc/sys/fs/file-nr" | ||
17 | fileFDStatSubsystem = "filefd" | ||
18 | ) | ||
19 | |||
20 | type fileFDStatCollector struct { | ||
21 | metrics map[string]prometheus.Gauge | ||
22 | } | ||
23 | |||
24 | func init() { | ||
25 | Factories[fileFDStatSubsystem] = NewFileFDStatCollector | ||
26 | } | ||
27 | |||
28 | // NewFileFDStatCollector returns a new Collector exposing file-nr stats. | ||
29 | func NewFileFDStatCollector() (Collector, error) { | ||
30 | return &fileFDStatCollector{ | ||
31 | metrics: map[string]prometheus.Gauge{}, | ||
32 | }, nil | ||
33 | } | ||
34 | |||
35 | func (c *fileFDStatCollector) Update(ch chan<- prometheus.Metric) (err error) { | ||
36 | fileFDStat, err := getFileFDStats(procFileFDStat) | ||
37 | if err != nil { | ||
38 | return fmt.Errorf("couldn't get file-nr: %s", err) | ||
39 | } | ||
40 | for name, value := range fileFDStat { | ||
41 | if _, ok := c.metrics[name]; !ok { | ||
42 | c.metrics[name] = prometheus.NewGauge( | ||
43 | prometheus.GaugeOpts{ | ||
44 | Namespace: Namespace, | ||
45 | Subsystem: fileFDStatSubsystem, | ||
46 | Name: name, | ||
47 | Help: fmt.Sprintf("filefd %s from %s.", name, procFileFDStat), | ||
48 | }, | ||
49 | ) | ||
50 | v, err := strconv.ParseFloat(value, 64) | ||
51 | if err != nil { | ||
52 | return fmt.Errorf("invalid value %s in file-nr: %s", value, err) | ||
53 | } | ||
54 | c.metrics[name].Set(v) | ||
55 | } | ||
56 | } | ||
57 | for _, m := range c.metrics { | ||
58 | m.Collect(ch) | ||
59 | } | ||
60 | return err | ||
61 | } | ||
62 | |||
63 | func getFileFDStats(fileName string) (map[string]string, error) { | ||
64 | file, err := os.Open(fileName) | ||
65 | if err != nil { | ||
66 | return nil, err | ||
67 | } | ||
68 | defer file.Close() | ||
69 | return parseFileFDStats(file, fileName) | ||
70 | } | ||
71 | |||
72 | func parseFileFDStats(r io.Reader, fileName string) (map[string]string, error) { | ||
73 | var scanner = bufio.NewScanner(r) | ||
74 | scanner.Scan() | ||
75 | // The file-nr proc file is separated by tabs, not spaces. | ||
76 | line := strings.Split(string(scanner.Text()), "\u0009") | ||
77 | var fileFDStat = map[string]string{} | ||
78 | // The file-nr proc is only 1 line with 3 values. | ||
79 | fileFDStat["allocated"] = line[0] | ||
80 | // The second value is skipped as it will alwasy be zero in linux 2.6. | ||
81 | fileFDStat["maximum"] = line[2] | ||
82 | |||
83 | return fileFDStat, nil | ||
84 | } | ||
diff --git a/collector/filefd_linux_test.go b/collector/filefd_linux_test.go new file mode 100644 index 0000000..31e4811 --- /dev/null +++ b/collector/filefd_linux_test.go | |||
@@ -0,0 +1,27 @@ | |||
1 | package collector | ||
2 | |||
3 | import ( | ||
4 | "os" | ||
5 | "testing" | ||
6 | ) | ||
7 | |||
8 | func TestFileFDStats(t *testing.T) { | ||
9 | file, err := os.Open("fixtures/file-nr") | ||
10 | if err != nil { | ||
11 | t.Fatal(err) | ||
12 | } | ||
13 | defer file.Close() | ||
14 | |||
15 | fileFDStats, err := parseFileFDStats(file, fileName) | ||
16 | if err != nil { | ||
17 | t.Fatal(err) | ||
18 | } | ||
19 | |||
20 | if want, got := "1024", fileFDStats["allocated"]; want != got { | ||
21 | t.Errorf("want filefd allocated %s, got %s", want, got) | ||
22 | } | ||
23 | |||
24 | if want, got := "1631329", fileFDStats["maximum"]; want != got { | ||
25 | t.Errorf("want filefd maximum %s, got %s", want, got) | ||
26 | } | ||
27 | } | ||
diff --git a/collector/fixtures/file-nr b/collector/fixtures/file-nr new file mode 100644 index 0000000..d5a4f87 --- /dev/null +++ b/collector/fixtures/file-nr | |||
@@ -0,0 +1 @@ | |||
1024 0 1631329 | |||
diff --git a/node_exporter.go b/node_exporter.go index 56f2d2d..890e527 100644 --- a/node_exporter.go +++ b/node_exporter.go | |||
@@ -28,7 +28,7 @@ var ( | |||
28 | memProfile = flag.String("debug.memprofile-file", "", "Write memory profile to this file upon receipt of SIGUSR1.") | 28 | memProfile = flag.String("debug.memprofile-file", "", "Write memory profile to this file upon receipt of SIGUSR1.") |
29 | listenAddress = flag.String("web.listen-address", ":9100", "Address on which to expose metrics and web interface.") | 29 | listenAddress = flag.String("web.listen-address", ":9100", "Address on which to expose metrics and web interface.") |
30 | metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") | 30 | metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") |
31 | enabledCollectors = flag.String("collectors.enabled", "diskstats,filesystem,loadavg,meminfo,stat,textfile,time,netdev,netstat,sockstat", "Comma-separated list of collectors to use.") | 31 | enabledCollectors = flag.String("collectors.enabled", "diskstats,filesystem,loadavg,meminfo,stat,textfile,time,netdev,netstat,sockstat,filefd", "Comma-separated list of collectors to use.") |
32 | printCollectors = flag.Bool("collectors.print", false, "If true, print available collectors and exit.") | 32 | printCollectors = flag.Bool("collectors.print", false, "If true, print available collectors and exit.") |
33 | authUser = flag.String("auth.user", "", "Username for basic auth.") | 33 | authUser = flag.String("auth.user", "", "Username for basic auth.") |
34 | authPass = flag.String("auth.pass", "", "Password for basic auth.") | 34 | authPass = flag.String("auth.pass", "", "Password for basic auth.") |