ProcessStatCollector: continue if PID disappears between opening and reading file
Signed-off-by: Dustin Hooten <dustinhooten@gmail.com>pull/1948/head
parent
88ee42742e
commit
b7626ecdbf
|
@ -19,6 +19,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/go-kit/kit/log"
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/go-kit/kit/log/level"
|
"github.com/go-kit/kit/log/level"
|
||||||
|
@ -111,7 +113,7 @@ func (c *processCollector) getAllocatedThreads() (int, map[string]int32, int, er
|
||||||
for _, pid := range p {
|
for _, pid := range p {
|
||||||
stat, err := pid.Stat()
|
stat, err := pid.Stat()
|
||||||
// PIDs can vanish between getting the list and getting stats.
|
// PIDs can vanish between getting the list and getting stats.
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) || errorContains(err, syscall.ESRCH) {
|
||||||
level.Debug(c.logger).Log("msg", "file not found when retrieving stats for pid", "pid", pid, "err", err)
|
level.Debug(c.logger).Log("msg", "file not found when retrieving stats for pid", "pid", pid, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -125,3 +127,7 @@ func (c *processCollector) getAllocatedThreads() (int, map[string]int32, int, er
|
||||||
}
|
}
|
||||||
return pids, procStates, thread, nil
|
return pids, procStates, thread, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func errorContains(err, target error) bool {
|
||||||
|
return err != nil && target != nil && strings.Contains(err.Error(), target.Error())
|
||||||
|
}
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-kit/kit/log"
|
"errors"
|
||||||
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -52,3 +54,28 @@ func TestReadProcessStatus(t *testing.T) {
|
||||||
t.Fatalf("Total running pids cannot be greater than %d or equals to 0", maxPid)
|
t.Fatalf("Total running pids cannot be greater than %d or equals to 0", maxPid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_errorContains(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
err error
|
||||||
|
target error
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{err: nil, target: nil, expected: false},
|
||||||
|
{err: errors.New("e"), target: nil, expected: false},
|
||||||
|
{err: nil, target: errors.New("e"), expected: false},
|
||||||
|
{err: errors.New("abc"), target: errors.New("def"), expected: false},
|
||||||
|
{err: errors.New("abc"), target: errors.New("bc"), expected: true},
|
||||||
|
{err: errors.New("read /proc/2054/stat: no such process"), target: syscall.ESRCH, expected: true},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
actual := errorContains(tc.err, tc.target)
|
||||||
|
if actual != tc.expected {
|
||||||
|
negation := " not"
|
||||||
|
if tc.expected {
|
||||||
|
negation = ""
|
||||||
|
}
|
||||||
|
t.Fatalf("Expected \"%v\"%s to contain \"%v\", got %v", tc.err, negation, tc.target, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue