diff --git a/plugins/inputs/procstat/procstat.go b/plugins/inputs/procstat/procstat.go index 3b9f0f76c..167c35072 100644 --- a/plugins/inputs/procstat/procstat.go +++ b/plugins/inputs/procstat/procstat.go @@ -15,12 +15,14 @@ import ( ) type Procstat struct { - PidFile string `toml:"pid_file"` - Exe string - Pattern string - Prefix string - ProcessName string - User string + PidFile string `toml:"pid_file"` + Exe string + Pattern string + Prefix string + ProcessName string + CmdlineRegex string + ParentCmdlineRegex string + User string // pidmap maps a pid to a process object, so we don't recreate every gather pidmap map[int32]*process.Process @@ -70,7 +72,7 @@ func (p *Procstat) Gather(acc telegraf.Accumulator) error { p.Exe, p.PidFile, p.Pattern, p.User, err.Error()) } else { for pid, proc := range p.pidmap { - p := NewSpecProcessor(p.ProcessName, p.Prefix, acc, proc, p.tagmap[pid]) + p := NewSpecProcessor(p.ProcessName, p.Prefix, p.CmdlineRegex, p.ParentCmdlineRegex, acc, proc, p.tagmap[pid]) p.pushMetrics() } } diff --git a/plugins/inputs/procstat/spec_processor.go b/plugins/inputs/procstat/spec_processor.go index 0e73b60e9..a97e0c04e 100644 --- a/plugins/inputs/procstat/spec_processor.go +++ b/plugins/inputs/procstat/spec_processor.go @@ -2,6 +2,8 @@ package procstat import ( "time" + "regexp" + "strconv" "github.com/shirou/gopsutil/process" @@ -19,6 +21,8 @@ type SpecProcessor struct { func NewSpecProcessor( processName string, prefix string, + cmdlineRegex string, + parentCmdlineRegex string, acc telegraf.Accumulator, p *process.Process, tags map[string]string, @@ -31,6 +35,33 @@ func NewSpecProcessor( tags["process_name"] = name } } + + if cmdlineRegex != "" { + val := CmdlineSubstrings(p, &cmdlineRegex) + for i, value := range val { + tags["cmdline." + strconv.Itoa(i)] = value + } + } + + ppid, err := p.Ppid() + if err == nil { + tags["ppid"] = strconv.Itoa(int(ppid)) + + pp, err := process.NewProcess(ppid) + if err == nil { + parentName, err := pp.Name() + if err == nil { + tags["parent_name"] = parentName + } + if parentCmdlineRegex != "" { + val := CmdlineSubstrings(pp, &parentCmdlineRegex) + for i, value := range val { + tags["pcmdline." + strconv.Itoa(i)] = value + } + } + } + } + return &SpecProcessor{ Prefix: prefix, tags: tags, @@ -40,6 +71,20 @@ func NewSpecProcessor( } } +func CmdlineSubstrings(p *process.Process, regex *string) []string { + cmdline, err := p.Cmdline() + if err == nil { + re, err := regexp.Compile(*regex) + if err == nil { + cmdlineSubmatch := re.FindStringSubmatch(cmdline) + if cmdlineSubmatch != nil { + return cmdlineSubmatch[1:] + } + } + } + return nil +} + func (p *SpecProcessor) pushMetrics() { var prefix string if p.Prefix != "" {