Add new measurement with results of pgrep lookup to procstat input (#4307)

This commit is contained in:
maxunt 2018-06-19 11:47:13 -07:00 committed by Daniel Nelson
parent 8b678b9041
commit 86e4cd0083
4 changed files with 53 additions and 8 deletions

View File

@ -11,6 +11,7 @@ import (
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
"syscall"
"time" "time"
"unicode" "unicode"
) )
@ -193,3 +194,15 @@ func RandomSleep(max time.Duration, shutdown chan struct{}) {
return 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
}

View File

@ -6,6 +6,8 @@ import (
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
"github.com/influxdata/telegraf/internal"
) )
// Implemention of PIDGatherer that execs pgrep to find processes // Implemention of PIDGatherer that execs pgrep to find processes
@ -62,6 +64,12 @@ func find(path string, args []string) ([]PID, error) {
func run(path string, args []string) (string, error) { func run(path string, args []string) (string, error) {
out, err := exec.Command(path, args...).Output() 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 { if err != nil {
return "", fmt.Errorf("Error running %s: %s", path, err) return "", fmt.Errorf("Error running %s: %s", path, err)
} }

View File

@ -97,7 +97,7 @@ func (p *Procstat) Gather(acc telegraf.Accumulator) error {
p.createProcess = defaultProcess p.createProcess = defaultProcess
} }
procs, err := p.updateProcesses(p.procs) procs, err := p.updateProcesses(acc, p.procs)
if err != nil { if err != nil {
acc.AddError(fmt.Errorf("E! Error: procstat getting process, exe: [%s] pidfile: [%s] pattern: [%s] user: [%s] %s", 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())) p.Exe, p.PidFile, p.Pattern, p.User, err.Error()))
@ -230,8 +230,8 @@ func (p *Procstat) addMetrics(proc Process, acc telegraf.Accumulator) {
} }
// Update monitored Processes // Update monitored Processes
func (p *Procstat) updateProcesses(prevInfo map[PID]Process) (map[PID]Process, error) { func (p *Procstat) updateProcesses(acc telegraf.Accumulator, prevInfo map[PID]Process) (map[PID]Process, error) {
pids, tags, err := p.findPids() pids, tags, err := p.findPids(acc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -281,9 +281,9 @@ func (p *Procstat) getPIDFinder() (PIDFinder, error) {
} }
// Get matching PIDs and their initial tags // 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 pids []PID
var tags map[string]string tags := make(map[string]string)
var err error var err error
f, err := p.getPIDFinder() f, err := p.getPIDFinder()
@ -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") 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. // execCommand is so tests can mock out exec.Command usage.

View File

@ -343,7 +343,8 @@ func TestGather_systemdUnitPIDs(t *testing.T) {
createPIDFinder: pidFinder([]PID{}, nil), createPIDFinder: pidFinder([]PID{}, nil),
SystemdUnit: "TestGather_systemdUnitPIDs", SystemdUnit: "TestGather_systemdUnitPIDs",
} }
pids, tags, err := p.findPids() var acc testutil.Accumulator
pids, tags, err := p.findPids(&acc)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, []PID{11408}, pids) assert.Equal(t, []PID{11408}, pids)
assert.Equal(t, "TestGather_systemdUnitPIDs", tags["systemd_unit"]) assert.Equal(t, "TestGather_systemdUnitPIDs", tags["systemd_unit"])
@ -364,8 +365,20 @@ func TestGather_cgroupPIDs(t *testing.T) {
createPIDFinder: pidFinder([]PID{}, nil), createPIDFinder: pidFinder([]PID{}, nil),
CGroup: td, CGroup: td,
} }
pids, tags, err := p.findPids() var acc testutil.Accumulator
pids, tags, err := p.findPids(&acc)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, []PID{1234, 5678}, pids) assert.Equal(t, []PID{1234, 5678}, pids)
assert.Equal(t, td, tags["cgroup"]) 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))
}