From 283bd6d96501a678f75bc4d2a6ea9bef3644704d Mon Sep 17 00:00:00 2001 From: Jose Luis Navarro Date: Fri, 4 Nov 2016 12:32:20 +0100 Subject: [PATCH] Collect JSON values recursively closes #1993 closes #1693 --- CHANGELOG.md | 1 + plugins/inputs/jolokia/jolokia.go | 27 +++++------ plugins/inputs/jolokia/jolokia_test.go | 63 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5c08c3b2..ed7ff2a2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ in their config file. - [#2061](https://github.com/influxdata/telegraf/issues/2061): Fix panic when file stat info cannot be collected due to permissions or other issue(s). - [#2045](https://github.com/influxdata/telegraf/issues/2045): Graylog output should set short_message field. - [#1904](https://github.com/influxdata/telegraf/issues/1904): Hddtemp always put the value in the field temperature. +- [#1693](https://github.com/influxdata/telegraf/issues/1693): Properly collect nested jolokia struct data. ## v1.1.2 [2016-12-12] diff --git a/plugins/inputs/jolokia/jolokia.go b/plugins/inputs/jolokia/jolokia.go index 2cc0d6422..6a51e9b43 100644 --- a/plugins/inputs/jolokia/jolokia.go +++ b/plugins/inputs/jolokia/jolokia.go @@ -220,6 +220,16 @@ func (j *Jolokia) prepareRequest(server Server, metric Metric) (*http.Request, e return req, nil } +func extractValues(measurement string, value interface{}, fields map[string]interface{}) { + if mapValues, ok := value.(map[string]interface{}); ok { + for k2, v2 := range mapValues { + extractValues(measurement+"_"+k2, v2, fields) + } + } else { + fields[measurement] = value + } +} + func (j *Jolokia) Gather(acc telegraf.Accumulator) error { servers := j.Servers metrics := j.Metrics @@ -244,23 +254,8 @@ func (j *Jolokia) Gather(acc telegraf.Accumulator) error { if err != nil { fmt.Printf("Error handling response: %s\n", err) } else { - if values, ok := out["value"]; ok { - switch t := values.(type) { - case map[string]interface{}: - for k, v := range t { - switch t2 := v.(type) { - case map[string]interface{}: - for k2, v2 := range t2 { - fields[measurement+"_"+k+"_"+k2] = v2 - } - case interface{}: - fields[measurement+"_"+k] = t2 - } - } - case interface{}: - fields[measurement] = t - } + extractValues(measurement, values, fields) } else { fmt.Printf("Missing key 'value' in output response\n") } diff --git a/plugins/inputs/jolokia/jolokia_test.go b/plugins/inputs/jolokia/jolokia_test.go index 13724b937..ccde619b5 100644 --- a/plugins/inputs/jolokia/jolokia_test.go +++ b/plugins/inputs/jolokia/jolokia_test.go @@ -12,6 +12,37 @@ import ( _ "github.com/stretchr/testify/require" ) +const validThreeLevelMultiValueJSON = ` +{ + "request":{ + "mbean":"java.lang:type=*", + "type":"read" + }, + "value":{ + "java.lang:type=Memory":{ + "ObjectPendingFinalizationCount":0, + "Verbose":false, + "HeapMemoryUsage":{ + "init":134217728, + "committed":173015040, + "max":1908932608, + "used":16840016 + }, + "NonHeapMemoryUsage":{ + "init":2555904, + "committed":51380224, + "max":-1, + "used":49944048 + }, + "ObjectName":{ + "objectName":"java.lang:type=Memory" + } + } + }, + "timestamp":1446129191, + "status":200 +}` + const validMultiValueJSON = ` { "request":{ @@ -103,6 +134,38 @@ func TestHttpJsonMultiValue(t *testing.T) { acc.AssertContainsTaggedFields(t, "jolokia", fields, tags) } +// Test that the proper values are ignored or collected +func TestHttpJsonThreeLevelMultiValue(t *testing.T) { + jolokia := genJolokiaClientStub(validThreeLevelMultiValueJSON, 200, Servers, []Metric{HeapMetric}) + + var acc testutil.Accumulator + err := jolokia.Gather(&acc) + + assert.Nil(t, err) + assert.Equal(t, 1, len(acc.Metrics)) + + fields := map[string]interface{}{ + "heap_memory_usage_java.lang:type=Memory_ObjectPendingFinalizationCount": 0.0, + "heap_memory_usage_java.lang:type=Memory_Verbose": false, + "heap_memory_usage_java.lang:type=Memory_HeapMemoryUsage_init": 134217728.0, + "heap_memory_usage_java.lang:type=Memory_HeapMemoryUsage_max": 1908932608.0, + "heap_memory_usage_java.lang:type=Memory_HeapMemoryUsage_used": 16840016.0, + "heap_memory_usage_java.lang:type=Memory_HeapMemoryUsage_committed": 173015040.0, + "heap_memory_usage_java.lang:type=Memory_NonHeapMemoryUsage_init": 2555904.0, + "heap_memory_usage_java.lang:type=Memory_NonHeapMemoryUsage_committed": 51380224.0, + "heap_memory_usage_java.lang:type=Memory_NonHeapMemoryUsage_max": -1.0, + "heap_memory_usage_java.lang:type=Memory_NonHeapMemoryUsage_used": 49944048.0, + "heap_memory_usage_java.lang:type=Memory_ObjectName_objectName": "java.lang:type=Memory", + } + + tags := map[string]string{ + "jolokia_host": "127.0.0.1", + "jolokia_port": "8080", + "jolokia_name": "as1", + } + acc.AssertContainsTaggedFields(t, "jolokia", fields, tags) +} + // Test that the proper values are ignored or collected func TestHttpJsonOn404(t *testing.T) {