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

Include CPU usage percent with procstat data #554

Merged
merged 1 commit into from
Jan 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
2 changes: 1 addition & 1 deletion agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func (a *Agent) Test() error {
// Special instructions for some inputs. cpu, for example, needs to be
// run twice in order to return cpu usage percentages.
switch input.Name {
case "cpu", "mongodb":
case "cpu", "mongodb", "procstat":
time.Sleep(500 * time.Millisecond)
fmt.Printf("* Plugin: %s, Collection 2\n", input.Name)
if err := input.Input.Gather(acc); err != nil {
Expand Down
28 changes: 17 additions & 11 deletions plugins/inputs/procstat/procstat.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ type Procstat struct {
Exe string
Pattern string
Prefix string

pidmap map[int32]*process.Process
}

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

var sampleConfig = `
Expand All @@ -46,12 +50,12 @@ func (_ *Procstat) Description() string {
}

func (p *Procstat) Gather(acc inputs.Accumulator) error {
procs, err := p.createProcesses()
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())
} else {
for _, proc := range procs {
for _, proc := range p.pidmap {
p := NewSpecProcessor(p.Prefix, acc, proc)
p.pushMetrics()
}
Expand All @@ -60,8 +64,7 @@ func (p *Procstat) Gather(acc inputs.Accumulator) error {
return nil
}

func (p *Procstat) createProcesses() ([]*process.Process, error) {
var out []*process.Process
func (p *Procstat) createProcesses() error {
var errstring string
var outerr error

Expand All @@ -71,19 +74,22 @@ func (p *Procstat) createProcesses() ([]*process.Process, error) {
}

for _, pid := range pids {
p, err := process.NewProcess(int32(pid))
if err == nil {
out = append(out, p)
} else {
errstring += err.Error() + " "
_, ok := p.pidmap[pid]
if !ok {
proc, err := process.NewProcess(pid)
if err == nil {
p.pidmap[pid] = proc
} else {
errstring += err.Error() + " "
}
}
}

if errstring != "" {
outerr = fmt.Errorf("%s", errstring)
}

return out, outerr
return outerr
}

func (p *Procstat) getAllPids() ([]int32, error) {
Expand Down
2 changes: 2 additions & 0 deletions plugins/inputs/procstat/procstat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strconv"
"testing"

"github.com/shirou/gopsutil/process"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand All @@ -23,6 +24,7 @@ func TestGather(t *testing.T) {
p := Procstat{
PidFile: file.Name(),
Prefix: "foo",
pidmap: make(map[int32]*process.Process),
}
p.Gather(&acc)
assert.True(t, acc.HasFloatField("procstat", "foo_cpu_time_user"))
Expand Down
40 changes: 19 additions & 21 deletions plugins/inputs/procstat/spec_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package procstat

import (
"fmt"
"log"
"time"

"github.com/shirou/gopsutil/process"

Expand Down Expand Up @@ -40,7 +40,7 @@ func NewSpecProcessor(
tags := make(map[string]string)
tags["pid"] = fmt.Sprintf("%v", p.Pid)
if name, err := p.Name(); err == nil {
tags["name"] = name
tags["process_name"] = name
}
return &SpecProcessor{
Prefix: prefix,
Expand All @@ -52,21 +52,11 @@ func NewSpecProcessor(
}

func (p *SpecProcessor) pushMetrics() {
if err := p.pushFDStats(); err != nil {
log.Printf("procstat, fd stats not available: %s", err.Error())
}
if err := p.pushCtxStats(); err != nil {
log.Printf("procstat, ctx stats not available: %s", err.Error())
}
if err := p.pushIOStats(); err != nil {
log.Printf("procstat, io stats not available: %s", err.Error())
}
if err := p.pushCPUStats(); err != nil {
log.Printf("procstat, cpu stats not available: %s", err.Error())
}
if err := p.pushMemoryStats(); err != nil {
log.Printf("procstat, mem stats not available: %s", err.Error())
}
p.pushFDStats()
p.pushCtxStats()
p.pushIOStats()
p.pushCPUStats()
p.pushMemoryStats()
p.flush()
}

Expand Down Expand Up @@ -113,10 +103,18 @@ func (p *SpecProcessor) pushCPUStats() error {
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)
p.add("cpu_time_steal", cpu_time.Steal)
p.add("cpu_time_stolen", cpu_time.Stolen)
p.add("cpu_time_guest", cpu_time.Guest)
p.add("cpu_time_guest_nice", cpu_time.GuestNice)

cpu_perc, err := p.proc.CPUPercent(time.Duration(0))
if err != nil {
return err
} else if cpu_perc == 0 {
return nil
}
p.add("cpu_usage", cpu_perc)

return nil
}
Expand Down