diff --git a/CHANGELOG.md b/CHANGELOG.md index 754701e44..82a224f21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## v0.12.1 [unreleased] + +### Features + +### Bugfixes +- [#968](https://github.com/influxdata/telegraf/issues/968): Processes plugin gets unknown state when spaces are in (command name) + ## v0.12.0 [2016-04-05] ### Features diff --git a/plugins/inputs/system/processes.go b/plugins/inputs/system/processes.go index aae0e6ba4..8c50a4ebd 100644 --- a/plugins/inputs/system/processes.go +++ b/plugins/inputs/system/processes.go @@ -144,11 +144,18 @@ func (p *Processes) gatherFromProc(fields map[string]interface{}) error { continue } + // Parse out data after () + i := bytes.LastIndex(data, []byte(")")) + if i == -1 { + continue + } + data = data[i+2:] + stats := bytes.Fields(data) if len(stats) < 3 { return fmt.Errorf("Something is terribly wrong with %s", statFile) } - switch stats[2][0] { + switch stats[0][0] { case 'R': fields["running"] = fields["running"].(int64) + int64(1) case 'S': @@ -163,11 +170,11 @@ func (p *Processes) gatherFromProc(fields map[string]interface{}) error { fields["paging"] = fields["paging"].(int64) + int64(1) default: log.Printf("processes: Unknown state [ %s ] in file %s", - string(stats[2][0]), statFile) + string(stats[0][0]), statFile) } fields["total"] = fields["total"].(int64) + int64(1) - threads, err := strconv.Atoi(string(stats[19])) + threads, err := strconv.Atoi(string(stats[17])) if err != nil { log.Printf("processes: Error parsing thread count: %s", err) continue diff --git a/plugins/inputs/system/processes_test.go b/plugins/inputs/system/processes_test.go index de9b6aa5b..eef52cd67 100644 --- a/plugins/inputs/system/processes_test.go +++ b/plugins/inputs/system/processes_test.go @@ -82,6 +82,28 @@ func TestFromProcFiles(t *testing.T) { acc.AssertContainsTaggedFields(t, "processes", fields, map[string]string{}) } +func TestFromProcFilesWithSpaceInCmd(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skip("This test only runs on linux") + } + tester := tester{} + processes := &Processes{ + readProcFile: tester.testProcFile2, + forceProc: true, + } + + var acc testutil.Accumulator + err := processes.Gather(&acc) + require.NoError(t, err) + + fields := getEmptyFields() + fields["sleeping"] = tester.calls + fields["total_threads"] = tester.calls * 2 + fields["total"] = tester.calls + + acc.AssertContainsTaggedFields(t, "processes", fields, map[string]string{}) +} + func testExecPS() ([]byte, error) { return []byte(testPSOut), nil } @@ -96,6 +118,11 @@ func (t *tester) testProcFile(_ string) ([]byte, error) { return []byte(fmt.Sprintf(testProcStat, "S", "2")), nil } +func (t *tester) testProcFile2(_ string) ([]byte, error) { + t.calls++ + return []byte(fmt.Sprintf(testProcStat2, "S", "2")), nil +} + func testExecPSError() ([]byte, error) { return []byte(testPSOut), fmt.Errorf("ERROR!") } @@ -149,3 +176,6 @@ S+ const testProcStat = `10 (rcuob/0) %s 2 0 0 0 -1 2129984 0 0 0 0 0 0 0 0 20 0 %s 0 11 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ` + +const testProcStat2 = `10 (rcuob 0) %s 2 0 0 0 -1 2129984 0 0 0 0 0 0 0 0 20 0 %s 0 11 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +`