From 5b1e02125b34a5394a33b70d9505fe76e8c197f7 Mon Sep 17 00:00:00 2001 From: Cameron Sparr Date: Tue, 8 Mar 2016 11:42:31 +0100 Subject: [PATCH] Cross platform support for the 'processes' plugin closes #798 --- plugins/inputs/system/processes.go | 62 +++++++++++++++++++++---- plugins/inputs/system/processes_test.go | 6 +-- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/plugins/inputs/system/processes.go b/plugins/inputs/system/processes.go index c4b791e3c81ef..b013695d5042f 100644 --- a/plugins/inputs/system/processes.go +++ b/plugins/inputs/system/processes.go @@ -1,8 +1,11 @@ +// +build !windows + package system import ( "fmt" "log" + "runtime" "github.com/influxdata/telegraf" "github.com/influxdata/telegraf/plugins/inputs" @@ -23,15 +26,28 @@ func (s *Processes) Gather(acc telegraf.Accumulator) error { if err != nil { return fmt.Errorf("error getting pids list: %s", err) } + // TODO handle other OS (Windows/BSD/Solaris/OSX) fields := map[string]interface{}{ - "paging": uint64(0), - "blocked": uint64(0), - "zombie": uint64(0), - "stopped": uint64(0), - "running": uint64(0), - "sleeping": uint64(0), + "blocked": int64(0), + "zombie": int64(0), + "stopped": int64(0), + "running": int64(0), + "sleeping": int64(0), + } + + switch runtime.GOOS { + case "freebsd": + fields["idle"] = int64(0) + fields["wait"] = int64(0) + case "darwin": + fields["idle"] = int64(0) + case "openbsd": + fields["idle"] = int64(0) + case "linux": + fields["paging"] = int64(0) } + for _, pid := range pids { process, err := process.NewProcess(pid) if err != nil { @@ -39,16 +55,44 @@ func (s *Processes) Gather(acc telegraf.Accumulator) error { continue } status, err := process.Status() - if err != nil { + if err != nil || len(status) == 0 { log.Printf("Can not get process %d status: %s\n", pid, err) continue } + + if status == "disk sleep" { + status = "blocked" + } + + switch status[0:1] { + case "W": + switch runtime.GOOS { + case "freebsd": + status = "wait" + default: + status = "paging" + } + case "U", "D": + // Also known as uninterruptible sleep or disk sleep + status = "blocked" + case "Z": + status = "zombie" + case "T": + status = "stopped" + case "R": + status = "running" + case "S": + status = "sleeping" + case "I": + status = "idle" + } + _, exists := fields[status] if !exists { - log.Printf("Status '%s' for process with pid: %d\n", status, pid) + log.Printf("Unknown Status '%s' for process with pid: %d\n", status, pid) continue } - fields[status] = fields[status].(uint64) + uint64(1) + fields[status] = fields[status].(int64) + int64(1) } acc.AddFields("processes", fields, nil) diff --git a/plugins/inputs/system/processes_test.go b/plugins/inputs/system/processes_test.go index 246884711082a..58c37576da7c7 100644 --- a/plugins/inputs/system/processes_test.go +++ b/plugins/inputs/system/processes_test.go @@ -15,7 +15,7 @@ func TestProcesses(t *testing.T) { err := processes.Gather(&acc) require.NoError(t, err) - assert.True(t, acc.HasUIntField("processes", "running")) - assert.True(t, acc.HasUIntField("processes", "sleeping")) - assert.True(t, acc.HasUIntField("processes", "stopped")) + assert.True(t, acc.HasIntField("processes", "running")) + assert.True(t, acc.HasIntField("processes", "sleeping")) + assert.True(t, acc.HasIntField("processes", "stopped")) }