Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/procstat adds new procstat metric about pgrep search #4307

Merged
merged 15 commits into from
Jun 19, 2018
Merged
13 changes: 13 additions & 0 deletions internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os/exec"
"strconv"
"strings"
"syscall"
"time"
"unicode"
)
Expand Down Expand Up @@ -193,3 +194,15 @@ func RandomSleep(max time.Duration, shutdown chan struct{}) {
return
}
}

// Exit status takes the error from exec.Command
// and returns the exit status and true
// if error is not exit status, will return 0 and false
func ExitStatus(err error) (int, bool) {
if exiterr, ok := err.(*exec.ExitError); ok {
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
return status.ExitStatus(), true
}
}
return 0, false
}
8 changes: 8 additions & 0 deletions plugins/inputs/procstat/pgrep.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"os/exec"
"strconv"
"strings"

"github.com/influxdata/telegraf/internal"
)

// Implemention of PIDGatherer that execs pgrep to find processes
Expand Down Expand Up @@ -62,6 +64,12 @@ func find(path string, args []string) ([]PID, error) {

func run(path string, args []string) (string, error) {
out, err := exec.Command(path, args...).Output()

//if exit code 1, ie no processes found, do not return error
if i, _ := internal.ExitStatus(err); i == 1 {
return "", nil
}

if err != nil {
return "", fmt.Errorf("Error running %s: %s", path, err)
}
Expand Down
23 changes: 17 additions & 6 deletions plugins/inputs/procstat/procstat.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (p *Procstat) Gather(acc telegraf.Accumulator) error {
p.createProcess = defaultProcess
}

procs, err := p.updateProcesses(p.procs)
procs, err := p.updateProcesses(acc, p.procs)
if err != nil {
acc.AddError(fmt.Errorf("E! Error: procstat getting process, exe: [%s] pidfile: [%s] pattern: [%s] user: [%s] %s",
p.Exe, p.PidFile, p.Pattern, p.User, err.Error()))
Expand Down Expand Up @@ -230,8 +230,8 @@ func (p *Procstat) addMetrics(proc Process, acc telegraf.Accumulator) {
}

// Update monitored Processes
func (p *Procstat) updateProcesses(prevInfo map[PID]Process) (map[PID]Process, error) {
pids, tags, err := p.findPids()
func (p *Procstat) updateProcesses(acc telegraf.Accumulator, prevInfo map[PID]Process) (map[PID]Process, error) {
pids, tags, err := p.findPids(acc)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -281,9 +281,9 @@ func (p *Procstat) getPIDFinder() (PIDFinder, error) {
}

// Get matching PIDs and their initial tags
func (p *Procstat) findPids() ([]PID, map[string]string, error) {
func (p *Procstat) findPids(acc telegraf.Accumulator) ([]PID, map[string]string, error) {
var pids []PID
var tags map[string]string
tags := make(map[string]string)
var err error

f, err := p.getPIDFinder()
Expand Down Expand Up @@ -313,7 +313,18 @@ func (p *Procstat) findPids() ([]PID, map[string]string, error) {
err = fmt.Errorf("Either exe, pid_file, user, pattern, systemd_unit, or cgroup must be specified")
}

return pids, tags, err
rTags := make(map[string]string)
for k, v := range tags {
rTags[k] = v
}

//adds a metric with info on the pgrep query
fields := make(map[string]interface{})
tags["pid_finder"] = p.PidFinder
fields["pid_count"] = len(pids)
acc.AddFields("procstat_lookup", fields, tags)

return pids, rTags, err
}

// execCommand is so tests can mock out exec.Command usage.
Expand Down
17 changes: 15 additions & 2 deletions plugins/inputs/procstat/procstat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ func TestGather_systemdUnitPIDs(t *testing.T) {
createPIDFinder: pidFinder([]PID{}, nil),
SystemdUnit: "TestGather_systemdUnitPIDs",
}
pids, tags, err := p.findPids()
var acc testutil.Accumulator
pids, tags, err := p.findPids(&acc)
require.NoError(t, err)
assert.Equal(t, []PID{11408}, pids)
assert.Equal(t, "TestGather_systemdUnitPIDs", tags["systemd_unit"])
Expand All @@ -364,8 +365,20 @@ func TestGather_cgroupPIDs(t *testing.T) {
createPIDFinder: pidFinder([]PID{}, nil),
CGroup: td,
}
pids, tags, err := p.findPids()
var acc testutil.Accumulator
pids, tags, err := p.findPids(&acc)
require.NoError(t, err)
assert.Equal(t, []PID{1234, 5678}, pids)
assert.Equal(t, td, tags["cgroup"])
}

func TestProcstatLookupMetric(t *testing.T) {
p := Procstat{
createPIDFinder: pidFinder([]PID{543}, nil),
Exe: "-Gsys",
}
var acc testutil.Accumulator
err := acc.GatherError(p.Gather)
require.NoError(t, err)
require.Equal(t, len(p.procs)+1, len(acc.Metrics))
}