follow-up for 2a12f948a97173ec8bf4c900e6725712021ef737
This commit is contained in:
parent
2a12f948a9
commit
c070763356
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -9,3 +9,7 @@ import (
|
||||
func writeProcessMetrics(w io.Writer) {
|
||||
// TODO: implement it
|
||||
}
|
||||
|
||||
func writeFDMetrics(w io.Writer) {
|
||||
// TODO: implement it.
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user