From c07076335615872a81d4a0a98b8df9862939b7e7 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Thu, 4 Feb 2021 16:28:55 +0200 Subject: [PATCH] follow-up for 2a12f948a97173ec8bf4c900e6725712021ef737 --- metrics.go | 6 ++++ process_metrics_linux.go | 63 ++++++++++++++++------------------- process_metrics_linux_test.go | 35 ++++++++++--------- process_metrics_other.go | 4 +++ 4 files changed, 56 insertions(+), 52 deletions(-) diff --git a/metrics.go b/metrics.go index 962ceef..bda1cb9 100644 --- a/metrics.go +++ b/metrics.go @@ -58,11 +58,17 @@ func WritePrometheus(w io.Writer, exposeProcessMetrics bool) { // metrics.WriteProcessMetrics(w) // }) // +// See also WrteFDMetrics. func WriteProcessMetrics(w io.Writer) { writeGoMetrics(w) writeProcessMetrics(w) } +// WriteFDMetrics writes `process_max_fds` and `process_open_fds` metrics to w. +func WriteFDMetrics(w io.Writer) { + writeFDMetrics(w) +} + // UnregisterMetric removes metric with the given name from default set. func UnregisterMetric(name string) bool { return defaultSet.UnregisterMetric(name) diff --git a/process_metrics_linux.go b/process_metrics_linux.go index ab8260b..d8b7c73 100644 --- a/process_metrics_linux.go +++ b/process_metrics_linux.go @@ -8,7 +8,6 @@ import ( "io/ioutil" "log" "os" - "regexp" "strconv" "strings" "time" @@ -87,74 +86,70 @@ func writeProcessMetrics(w io.Writer) { var startTimeSeconds = time.Now().Unix() -const fdReadChunkSize = 512 - -func WriteFDMetrics(w io.Writer){ +// WriteFDMetrics writes process_max_fds and process_open_fds metrics to w. +func writeFDMetrics(w io.Writer) { totalOpenFDs, err := getOpenFDsCount("/proc/self/fd") if err != nil { - log.Printf("ERROR: %v",err) + log.Printf("ERROR: cannot determine open file descriptors count: %s", err) return } maxOpenFDs, err := getMaxFilesLimit("/proc/self/limits") if err != nil { - log.Printf("ERROR: %v",err) + log.Printf("ERROR: cannot determine the limit on open file descritors: %s", err) return } - fmt.Fprintf(w,"process_max_fds %d\n",maxOpenFDs) - fmt.Fprintf(w,"process_open_fds %d\n",totalOpenFDs) + fmt.Fprintf(w, "process_max_fds %d\n", maxOpenFDs) + fmt.Fprintf(w, "process_open_fds %d\n", totalOpenFDs) } - -func getOpenFDsCount(path string)(uint64,error){ +func getOpenFDsCount(path string) (uint64, error) { f, err := os.Open(path) if err != nil { - return 0,fmt.Errorf("cannot open process fd path: %q, err: %v",path,err) + return 0, err } defer f.Close() var totalOpenFDs uint64 for { - names, err := f.Readdirnames(fdReadChunkSize) - if err == io.EOF{ + names, err := f.Readdirnames(512) + if err == io.EOF { break } if err != nil { - return 0, fmt.Errorf("unexpected error at readdirnames: %v",err) + return 0, fmt.Errorf("unexpected error at Readdirnames: %s", err) } totalOpenFDs += uint64(len(names)) } return totalOpenFDs, nil } -var limitsRe = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`) - -func getMaxFilesLimit(path string)(uint64,error){ +func getMaxFilesLimit(path string) (uint64, error) { f, err := os.Open(path) if err != nil { - return 0,fmt.Errorf("cannot open path: %q for max files limit, err: %w",path,err) + return 0, err } defer f.Close() + prefix := "Max open files" scan := bufio.NewScanner(f) - // skip first line - scan.Scan() - for scan.Scan(){ - text := scan.Text() - if !strings.HasPrefix(text,"Max open files"){ + for scan.Scan() { + s := scan.Text() + if !strings.HasPrefix(s, prefix) { continue } - items := limitsRe.FindStringSubmatch(text) - if len(items) != 4 { - return 0,fmt.Errorf("unxpected fields num for limits file, want: %d, got: %d, line: %q",4,len(items),text) + text := strings.TrimSpace(s[len(prefix):]) + // Extract soft limit. + n := strings.IndexByte(text, ' ') + if n < 0 { + return 0, fmt.Errorf("cannot extract soft limit from %q", s) } - // use soft limit. - limit := items[2] - if limit == "unlimited"{ - return 18446744073709551615,nil + text = text[:n] + if text == "unlimited" { + return 1<<64 - 1, nil } - limitUint, err := strconv.ParseUint(limit,10,64) + limit, err := strconv.ParseUint(text, 10, 64) if err != nil { - return 0, fmt.Errorf("cannot parse limit: %q as uint64: %w",limit,err) + return 0, fmt.Errorf("cannot parse soft limit from %q: %s", s, err) } - return limitUint,nil + return limit, nil } - return 0, fmt.Errorf("max open files limit wasn't found") + return 0, fmt.Errorf("cannot find max open files limit") } diff --git a/process_metrics_linux_test.go b/process_metrics_linux_test.go index b3ea502..7d6d3a6 100644 --- a/process_metrics_linux_test.go +++ b/process_metrics_linux_test.go @@ -2,36 +2,35 @@ package metrics import "testing" -func TestGetMaxFilesLimit(t *testing.T){ - f := func(want uint64,path string, wantErr bool) { +func TestGetMaxFilesLimit(t *testing.T) { + f := func(want uint64, path string, wantErr bool) { t.Helper() got, err := getMaxFilesLimit(path) if err != nil && !wantErr { - t.Fatalf("unexpected error: %v",err) + t.Fatalf("unexpected error: %v", err) } - if got != want{ - t.Fatalf("unexpected result: %d, want: %d at getMaxFilesLimit",got,want) + if got != want { + t.Fatalf("unexpected result: %d, want: %d at getMaxFilesLimit", got, want) } } - f(1024,"testdata/limits",false) - f(0,"testdata/bad_path",true) - f(0,"testdata/limits_bad",true) + f(1024, "testdata/limits", false) + f(0, "testdata/bad_path", true) + f(0, "testdata/limits_bad", true) } - -func TestGetOpenFDsCount(t *testing.T){ - f := func(want uint64,path string, wantErr bool) { +func TestGetOpenFDsCount(t *testing.T) { + f := func(want uint64, path string, wantErr bool) { t.Helper() got, err := getOpenFDsCount(path) - if (err != nil && !wantErr)|| (err == nil && wantErr) { - t.Fatalf("unexpected error: %v",err) + if (err != nil && !wantErr) || (err == nil && wantErr) { + t.Fatalf("unexpected error: %v", err) } - if got != want{ - t.Fatalf("unexpected result: %d, want: %d at getOpenFDsCount",got,want) + if got != want { + t.Fatalf("unexpected result: %d, want: %d at getOpenFDsCount", got, want) } } - f(5,"testdata/fd/",false) - f(0,"testdata/fd/0",true) - f(0,"testdata/limits",true) + f(5, "testdata/fd/", false) + f(0, "testdata/fd/0", true) + f(0, "testdata/limits", true) } diff --git a/process_metrics_other.go b/process_metrics_other.go index 6874de3..5e6ac93 100644 --- a/process_metrics_other.go +++ b/process_metrics_other.go @@ -9,3 +9,7 @@ import ( func writeProcessMetrics(w io.Writer) { // TODO: implement it } + +func writeFDMetrics(w io.Writer) { + // TODO: implement it. +}