2015-10-04 05:09:18 +00:00
|
|
|
package procstat
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2015-10-07 17:42:50 +00:00
|
|
|
"log"
|
2015-10-05 22:45:40 +00:00
|
|
|
|
2015-10-04 05:09:18 +00:00
|
|
|
"github.com/shirou/gopsutil/process"
|
2015-10-05 22:45:40 +00:00
|
|
|
|
|
|
|
"github.com/influxdb/telegraf/plugins"
|
2015-10-04 05:09:18 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type SpecProcessor struct {
|
|
|
|
Prefix string
|
|
|
|
tags map[string]string
|
2015-12-15 05:37:25 +00:00
|
|
|
fields map[string]interface{}
|
2015-10-04 05:09:18 +00:00
|
|
|
acc plugins.Accumulator
|
|
|
|
proc *process.Process
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SpecProcessor) add(metric string, value interface{}) {
|
2015-10-07 18:31:49 +00:00
|
|
|
var mname string
|
|
|
|
if p.Prefix == "" {
|
|
|
|
mname = metric
|
|
|
|
} else {
|
|
|
|
mname = p.Prefix + "_" + metric
|
|
|
|
}
|
2015-12-15 05:37:25 +00:00
|
|
|
p.fields[mname] = value
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SpecProcessor) flush() {
|
|
|
|
p.acc.AddFields("procstat", p.fields, p.tags)
|
|
|
|
p.fields = make(map[string]interface{})
|
2015-10-04 05:09:18 +00:00
|
|
|
}
|
|
|
|
|
2015-10-07 17:42:50 +00:00
|
|
|
func NewSpecProcessor(
|
|
|
|
prefix string,
|
|
|
|
acc plugins.Accumulator,
|
|
|
|
p *process.Process,
|
|
|
|
) *SpecProcessor {
|
|
|
|
tags := make(map[string]string)
|
|
|
|
tags["pid"] = fmt.Sprintf("%v", p.Pid)
|
2015-10-07 18:31:49 +00:00
|
|
|
if name, err := p.Name(); err == nil {
|
|
|
|
tags["name"] = name
|
|
|
|
}
|
2015-10-04 05:09:18 +00:00
|
|
|
return &SpecProcessor{
|
|
|
|
Prefix: prefix,
|
2015-10-07 17:42:50 +00:00
|
|
|
tags: tags,
|
2015-12-15 05:37:25 +00:00
|
|
|
fields: make(map[string]interface{}),
|
2015-10-04 05:09:18 +00:00
|
|
|
acc: acc,
|
|
|
|
proc: p,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 18:31:49 +00:00
|
|
|
func (p *SpecProcessor) pushMetrics() {
|
2015-10-04 05:09:18 +00:00
|
|
|
if err := p.pushFDStats(); err != nil {
|
2015-10-07 18:31:49 +00:00
|
|
|
log.Printf("procstat, fd stats not available: %s", err.Error())
|
2015-10-04 05:09:18 +00:00
|
|
|
}
|
|
|
|
if err := p.pushCtxStats(); err != nil {
|
2015-10-07 18:31:49 +00:00
|
|
|
log.Printf("procstat, ctx stats not available: %s", err.Error())
|
2015-10-04 05:09:18 +00:00
|
|
|
}
|
|
|
|
if err := p.pushIOStats(); err != nil {
|
2015-10-07 18:31:49 +00:00
|
|
|
log.Printf("procstat, io stats not available: %s", err.Error())
|
2015-10-04 05:09:18 +00:00
|
|
|
}
|
|
|
|
if err := p.pushCPUStats(); err != nil {
|
2015-10-07 18:31:49 +00:00
|
|
|
log.Printf("procstat, cpu stats not available: %s", err.Error())
|
2015-10-04 05:09:18 +00:00
|
|
|
}
|
|
|
|
if err := p.pushMemoryStats(); err != nil {
|
2015-10-07 18:31:49 +00:00
|
|
|
log.Printf("procstat, mem stats not available: %s", err.Error())
|
2015-10-04 05:09:18 +00:00
|
|
|
}
|
2015-12-15 05:37:25 +00:00
|
|
|
p.flush()
|
2015-10-04 05:09:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SpecProcessor) pushFDStats() error {
|
|
|
|
fds, err := p.proc.NumFDs()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("NumFD error: %s\n", err)
|
|
|
|
}
|
|
|
|
p.add("num_fds", fds)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SpecProcessor) pushCtxStats() error {
|
|
|
|
ctx, err := p.proc.NumCtxSwitches()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("ContextSwitch error: %s\n", err)
|
|
|
|
}
|
|
|
|
p.add("voluntary_context_switches", ctx.Voluntary)
|
|
|
|
p.add("involuntary_context_switches", ctx.Involuntary)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SpecProcessor) pushIOStats() error {
|
|
|
|
io, err := p.proc.IOCounters()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("IOCounters error: %s\n", err)
|
|
|
|
}
|
|
|
|
p.add("read_count", io.ReadCount)
|
|
|
|
p.add("write_count", io.WriteCount)
|
|
|
|
p.add("read_bytes", io.ReadBytes)
|
|
|
|
p.add("write_bytes", io.WriteCount)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SpecProcessor) pushCPUStats() error {
|
2015-12-15 05:37:25 +00:00
|
|
|
cpu_time, err := p.proc.CPUTimes()
|
2015-10-04 05:09:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-15 05:37:25 +00:00
|
|
|
p.add("cpu_time_user", cpu_time.User)
|
|
|
|
p.add("cpu_time_system", cpu_time.System)
|
|
|
|
p.add("cpu_time_idle", cpu_time.Idle)
|
|
|
|
p.add("cpu_time_nice", cpu_time.Nice)
|
|
|
|
p.add("cpu_time_iowait", cpu_time.Iowait)
|
|
|
|
p.add("cpu_time_irq", cpu_time.Irq)
|
|
|
|
p.add("cpu_time_soft_irq", cpu_time.Softirq)
|
|
|
|
p.add("cpu_time_soft_steal", cpu_time.Steal)
|
|
|
|
p.add("cpu_time_soft_stolen", cpu_time.Stolen)
|
|
|
|
p.add("cpu_time_soft_guest", cpu_time.Guest)
|
|
|
|
p.add("cpu_time_soft_guest_nice", cpu_time.GuestNice)
|
|
|
|
|
2015-10-04 05:09:18 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SpecProcessor) pushMemoryStats() error {
|
|
|
|
mem, err := p.proc.MemoryInfo()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
p.add("memory_rss", mem.RSS)
|
|
|
|
p.add("memory_vms", mem.VMS)
|
|
|
|
p.add("memory_swap", mem.Swap)
|
|
|
|
return nil
|
|
|
|
}
|