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

procstat: Add user, pidfile, pattern & exe tags #1069

Merged
merged 1 commit into from
Apr 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ based on _prefix_ in addition to globs. This means that a filter like
- [#889](https://github.com/influxdata/telegraf/pull/889): Improved MySQL plugin. Thanks @maksadbek!
- [#1060](https://github.com/influxdata/telegraf/pull/1060): TTL metrics added to MongoDB input plugin
- [#1056](https://github.com/influxdata/telegraf/pull/1056): Don't allow inputs to overwrite host tags.
- [#1035](https://github.com/influxdata/telegraf/issues/1035): Add `user`, `exe`, `pidfile` tags to procstat plugin.

### Bugfixes

Expand Down
53 changes: 37 additions & 16 deletions plugins/inputs/procstat/procstat.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ type Procstat struct {
Prefix string
User string

// pidmap maps a pid to a process object, so we don't recreate every gather
pidmap map[int32]*process.Process
// tagmap maps a pid to a map of tags for that pid
tagmap map[int32]map[string]string
}

func NewProcstat() *Procstat {
return &Procstat{
pidmap: make(map[int32]*process.Process),
tagmap: make(map[int32]map[string]string),
}
}

Expand Down Expand Up @@ -61,8 +65,8 @@ func (p *Procstat) Gather(acc telegraf.Accumulator) error {
log.Printf("Error: procstat getting process, exe: [%s] pidfile: [%s] pattern: [%s] user: [%s] %s",
p.Exe, p.PidFile, p.Pattern, p.User, err.Error())
} else {
for _, proc := range p.pidmap {
p := NewSpecProcessor(p.Prefix, acc, proc)
for pid, proc := range p.pidmap {
p := NewSpecProcessor(p.Prefix, acc, proc, p.tagmap[pid])
p.pushMetrics()
}
}
Expand Down Expand Up @@ -103,45 +107,50 @@ func (p *Procstat) getAllPids() ([]int32, error) {
var err error

if p.PidFile != "" {
pids, err = pidsFromFile(p.PidFile)
pids, err = p.pidsFromFile()
} else if p.Exe != "" {
pids, err = pidsFromExe(p.Exe)
pids, err = p.pidsFromExe()
} else if p.Pattern != "" {
pids, err = pidsFromPattern(p.Pattern)
pids, err = p.pidsFromPattern()
} else if p.User != "" {
pids, err = pidsFromUser(p.User)
pids, err = p.pidsFromUser()
} else {
err = fmt.Errorf("Either exe, pid_file or pattern has to be specified")
err = fmt.Errorf("Either exe, pid_file, user, or pattern has to be specified")
}

return pids, err
}

func pidsFromFile(file string) ([]int32, error) {
func (p *Procstat) pidsFromFile() ([]int32, error) {
var out []int32
var outerr error
pidString, err := ioutil.ReadFile(file)
pidString, err := ioutil.ReadFile(p.PidFile)
if err != nil {
outerr = fmt.Errorf("Failed to read pidfile '%s'. Error: '%s'", file, err)
outerr = fmt.Errorf("Failed to read pidfile '%s'. Error: '%s'",
p.PidFile, err)
} else {
pid, err := strconv.Atoi(strings.TrimSpace(string(pidString)))
if err != nil {
outerr = err
} else {
out = append(out, int32(pid))
p.tagmap[int32(pid)] = map[string]string{
"pidfile": p.PidFile,
"pid": string(pidString),
}
}
}
return out, outerr
}

func pidsFromExe(exe string) ([]int32, error) {
func (p *Procstat) pidsFromExe() ([]int32, error) {
var out []int32
var outerr error
bin, err := exec.LookPath("pgrep")
if err != nil {
return out, fmt.Errorf("Couldn't find pgrep binary: %s", err)
}
pgrep, err := exec.Command(bin, exe).Output()
pgrep, err := exec.Command(bin, p.Exe).Output()
if err != nil {
return out, fmt.Errorf("Failed to execute %s. Error: '%s'", bin, err)
} else {
Expand All @@ -150,6 +159,10 @@ func pidsFromExe(exe string) ([]int32, error) {
ipid, err := strconv.Atoi(pid)
if err == nil {
out = append(out, int32(ipid))
p.tagmap[int32(ipid)] = map[string]string{
"exe": p.Exe,
"pid": pid,
}
} else {
outerr = err
}
Expand All @@ -158,14 +171,14 @@ func pidsFromExe(exe string) ([]int32, error) {
return out, outerr
}

func pidsFromPattern(pattern string) ([]int32, error) {
func (p *Procstat) pidsFromPattern() ([]int32, error) {
var out []int32
var outerr error
bin, err := exec.LookPath("pgrep")
if err != nil {
return out, fmt.Errorf("Couldn't find pgrep binary: %s", err)
}
pgrep, err := exec.Command(bin, "-f", pattern).Output()
pgrep, err := exec.Command(bin, "-f", p.Pattern).Output()
if err != nil {
return out, fmt.Errorf("Failed to execute %s. Error: '%s'", bin, err)
} else {
Expand All @@ -174,6 +187,10 @@ func pidsFromPattern(pattern string) ([]int32, error) {
ipid, err := strconv.Atoi(pid)
if err == nil {
out = append(out, int32(ipid))
p.tagmap[int32(ipid)] = map[string]string{
"pattern": p.Pattern,
"pid": pid,
}
} else {
outerr = err
}
Expand All @@ -182,14 +199,14 @@ func pidsFromPattern(pattern string) ([]int32, error) {
return out, outerr
}

func pidsFromUser(user string) ([]int32, error) {
func (p *Procstat) pidsFromUser() ([]int32, error) {
var out []int32
var outerr error
bin, err := exec.LookPath("pgrep")
if err != nil {
return out, fmt.Errorf("Couldn't find pgrep binary: %s", err)
}
pgrep, err := exec.Command(bin, "-u", user).Output()
pgrep, err := exec.Command(bin, "-u", p.User).Output()
if err != nil {
return out, fmt.Errorf("Failed to execute %s. Error: '%s'", bin, err)
} else {
Expand All @@ -198,6 +215,10 @@ func pidsFromUser(user string) ([]int32, error) {
ipid, err := strconv.Atoi(pid)
if err == nil {
out = append(out, int32(ipid))
p.tagmap[int32(ipid)] = map[string]string{
"user": p.User,
"pid": pid,
}
} else {
outerr = err
}
Expand Down
1 change: 1 addition & 0 deletions plugins/inputs/procstat/procstat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func TestGather(t *testing.T) {
PidFile: file.Name(),
Prefix: "foo",
pidmap: make(map[int32]*process.Process),
tagmap: make(map[int32]map[string]string),
}
p.Gather(&acc)
assert.True(t, acc.HasFloatField("procstat", "foo_cpu_time_user"))
Expand Down
3 changes: 1 addition & 2 deletions plugins/inputs/procstat/spec_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ func NewSpecProcessor(
prefix string,
acc telegraf.Accumulator,
p *process.Process,
tags map[string]string,
) *SpecProcessor {
tags := make(map[string]string)
tags["pid"] = fmt.Sprintf("%v", p.Pid)
if name, err := p.Name(); err == nil {
tags["process_name"] = name
}
Expand Down