telegraf/plugins/inputs/procstat/spec_processor.go

148 lines
3.3 KiB
Go

package procstat
import (
"time"
"regexp"
"strconv"
"github.com/shirou/gopsutil/process"
"github.com/influxdata/telegraf"
)
type SpecProcessor struct {
Prefix string
tags map[string]string
fields map[string]interface{}
acc telegraf.Accumulator
proc *process.Process
}
func NewSpecProcessor(
processName string,
prefix string,
cmdlineRegex string,
parentCmdlineRegex string,
acc telegraf.Accumulator,
p *process.Process,
tags map[string]string,
) *SpecProcessor {
if processName != "" {
tags["process_name"] = processName
} else {
name, err := p.Name()
if err == nil {
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,
fields: make(map[string]interface{}),
acc: acc,
proc: p,
}
}
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 != "" {
prefix = p.Prefix + "_"
}
fields := map[string]interface{}{}
numThreads, err := p.proc.NumThreads()
if err == nil {
fields[prefix+"num_threads"] = numThreads
}
fds, err := p.proc.NumFDs()
if err == nil {
fields[prefix+"num_fds"] = fds
}
ctx, err := p.proc.NumCtxSwitches()
if err == nil {
fields[prefix+"voluntary_context_switches"] = ctx.Voluntary
fields[prefix+"involuntary_context_switches"] = ctx.Involuntary
}
io, err := p.proc.IOCounters()
if err == nil {
fields[prefix+"read_count"] = io.ReadCount
fields[prefix+"write_count"] = io.WriteCount
fields[prefix+"read_bytes"] = io.ReadBytes
fields[prefix+"write_bytes"] = io.WriteCount
}
cpu_time, err := p.proc.Times()
if err == nil {
fields[prefix+"cpu_time_user"] = cpu_time.User
fields[prefix+"cpu_time_system"] = cpu_time.System
fields[prefix+"cpu_time_idle"] = cpu_time.Idle
fields[prefix+"cpu_time_nice"] = cpu_time.Nice
fields[prefix+"cpu_time_iowait"] = cpu_time.Iowait
fields[prefix+"cpu_time_irq"] = cpu_time.Irq
fields[prefix+"cpu_time_soft_irq"] = cpu_time.Softirq
fields[prefix+"cpu_time_steal"] = cpu_time.Steal
fields[prefix+"cpu_time_stolen"] = cpu_time.Stolen
fields[prefix+"cpu_time_guest"] = cpu_time.Guest
fields[prefix+"cpu_time_guest_nice"] = cpu_time.GuestNice
}
cpu_perc, err := p.proc.Percent(time.Duration(0))
if err == nil && cpu_perc != 0 {
fields[prefix+"cpu_usage"] = cpu_perc
}
mem, err := p.proc.MemoryInfo()
if err == nil {
fields[prefix+"memory_rss"] = mem.RSS
fields[prefix+"memory_vms"] = mem.VMS
fields[prefix+"memory_swap"] = mem.Swap
}
p.acc.AddFields("procstat", fields, p.tags)
}