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

User name matching for procstat input #724

Closed
wants to merge 3 commits into from
Closed
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
3 changes: 2 additions & 1 deletion plugins/inputs/procstat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ individual process using their /proc data.

The plugin will tag processes by their PID and their process name.

Processes can be specified either by pid file or by executable name. Procstat
Processes can be specified either by pid file, by executable name, by command
line pattern matching, or by username (in this order or priority. Procstat
plugin will use `pgrep` when executable name is provided to obtain the pid.
Proctstas plugin will transmit IO, memory, cpu, file descriptor related
measurements for every process specified. A prefix can be set to isolate
Expand Down
33 changes: 31 additions & 2 deletions plugins/inputs/procstat/procstat.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type Procstat struct {
Exe string
Pattern string
Prefix string
User string

pidmap map[int32]*process.Process
}
Expand All @@ -37,6 +38,8 @@ var sampleConfig = `
# exe = "nginx"
## pattern as argument for pgrep (ie, pgrep -f <pattern>)
# pattern = "nginx"
## user as argument for pgrep (ie, pgrep -u <user>)
# user = "nginx"

## Field name prefix
prefix = ""
Expand All @@ -53,8 +56,8 @@ func (_ *Procstat) Description() string {
func (p *Procstat) Gather(acc telegraf.Accumulator) error {
err := p.createProcesses()
if err != nil {
log.Printf("Error: procstat getting process, exe: [%s] pidfile: [%s] pattern: [%s] %s",
p.Exe, p.PidFile, p.Pattern, err.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)
Expand Down Expand Up @@ -103,6 +106,8 @@ func (p *Procstat) getAllPids() ([]int32, error) {
pids, err = pidsFromExe(p.Exe)
} else if p.Pattern != "" {
pids, err = pidsFromPattern(p.Pattern)
} else if p.User != "" {
pids, err = pidsFromUser(p.User)
} else {
err = fmt.Errorf("Either exe, pid_file or pattern has to be specified")
}
Expand Down Expand Up @@ -175,6 +180,30 @@ func pidsFromPattern(pattern string) ([]int32, error) {
return out, outerr
}

func pidsFromUser(user string) ([]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()
if err != nil {
return out, fmt.Errorf("Failed to execute %s. Error: '%s'", bin, err)
} else {
pids := strings.Fields(string(pgrep))
for _, pid := range pids {
ipid, err := strconv.Atoi(pid)
if err == nil {
out = append(out, int32(ipid))
} else {
outerr = err
}
}
}
return out, outerr
}

func init() {
inputs.Add("procstat", func() telegraf.Input {
return NewProcstat()
Expand Down