processes plugin: fix case where there are spaces in cmd name

fixes #968
This commit is contained in:
Cameron Sparr 2016-04-05 10:21:57 -06:00
parent d871e9aee7
commit 863cbe512d
3 changed files with 47 additions and 3 deletions

View File

@ -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] ## v0.12.0 [2016-04-05]
### Features ### Features

View File

@ -144,11 +144,18 @@ func (p *Processes) gatherFromProc(fields map[string]interface{}) error {
continue continue
} }
// Parse out data after (<cmd name>)
i := bytes.LastIndex(data, []byte(")"))
if i == -1 {
continue
}
data = data[i+2:]
stats := bytes.Fields(data) stats := bytes.Fields(data)
if len(stats) < 3 { if len(stats) < 3 {
return fmt.Errorf("Something is terribly wrong with %s", statFile) return fmt.Errorf("Something is terribly wrong with %s", statFile)
} }
switch stats[2][0] { switch stats[0][0] {
case 'R': case 'R':
fields["running"] = fields["running"].(int64) + int64(1) fields["running"] = fields["running"].(int64) + int64(1)
case 'S': case 'S':
@ -163,11 +170,11 @@ func (p *Processes) gatherFromProc(fields map[string]interface{}) error {
fields["paging"] = fields["paging"].(int64) + int64(1) fields["paging"] = fields["paging"].(int64) + int64(1)
default: default:
log.Printf("processes: Unknown state [ %s ] in file %s", 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) fields["total"] = fields["total"].(int64) + int64(1)
threads, err := strconv.Atoi(string(stats[19])) threads, err := strconv.Atoi(string(stats[17]))
if err != nil { if err != nil {
log.Printf("processes: Error parsing thread count: %s", err) log.Printf("processes: Error parsing thread count: %s", err)
continue continue

View File

@ -82,6 +82,28 @@ func TestFromProcFiles(t *testing.T) {
acc.AssertContainsTaggedFields(t, "processes", fields, map[string]string{}) 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) { func testExecPS() ([]byte, error) {
return []byte(testPSOut), nil return []byte(testPSOut), nil
} }
@ -96,6 +118,11 @@ func (t *tester) testProcFile(_ string) ([]byte, error) {
return []byte(fmt.Sprintf(testProcStat, "S", "2")), nil 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) { func testExecPSError() ([]byte, error) {
return []byte(testPSOut), fmt.Errorf("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 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
`