From b9dbb1b01c7fea6c8294a0f41d3149369fe6b311 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Wed, 9 May 2018 08:15:24 +0200 Subject: [PATCH] Metricbeat: Ensure canonical naming for JMX beans is disabled (#7047) Canonical naming for JMX beans in Jolokia is enabled by default, this orders mbean fields, what breaks metricbeat internal mapping. We were already setting these options in the url, but url parameters are ignored in POST requests. This change adds these parameters as part of the body. --- CHANGELOG.asciidoc | 1 + metricbeat/module/jolokia/jmx/config.go | 16 +++++++++++----- metricbeat/module/jolokia/jmx/data.go | 2 +- metricbeat/module/jolokia/jmx/jmx.go | 2 +- metricbeat/tests/system/test_jolokia.py | 17 +++++++++++------ 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 7ddb46be7d41..5c52cfc32114 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -89,6 +89,7 @@ https://github.com/elastic/beats/compare/v6.2.3...master[Check the HEAD diff] - Don't stop Metricbeat if aerospike server is down. {pull}6874[6874] - disk reads and write count metrics in RabbitMQ queue metricset made optional. {issue}6876[6876] - Add mapping for docker metrics per cpu. {pull}6843[6843] +- Ensure canonical naming for JMX beans is disabled in Jolokia module. {pull}7047[7047] *Packetbeat* diff --git a/metricbeat/module/jolokia/jmx/config.go b/metricbeat/module/jolokia/jmx/config.go index e2d2bbb33345..a1d182fdf47b 100644 --- a/metricbeat/module/jolokia/jmx/config.go +++ b/metricbeat/module/jolokia/jmx/config.go @@ -33,9 +33,10 @@ type Attribute struct { // } // ] type RequestBlock struct { - Type string `json:"type"` - MBean string `json:"mbean"` - Attribute []string `json:"attribute"` + Type string `json:"type"` + MBean string `json:"mbean"` + Attribute []string `json:"attribute"` + Config map[string]interface{} `json:"config"` } type attributeMappingKey struct { @@ -56,10 +57,15 @@ func buildRequestBodyAndMapping(mappings []JMXMapping) ([]byte, AttributeMapping responseMapping := make(AttributeMapping) var blocks []RequestBlock + config := map[string]interface{}{ + "ignoreErrors": true, + "canonicalNaming": false, + } for _, mapping := range mappings { rb := RequestBlock{ - Type: "read", - MBean: mapping.MBean, + Type: "read", + MBean: mapping.MBean, + Config: config, } for _, attribute := range mapping.Attributes { diff --git a/metricbeat/module/jolokia/jmx/data.go b/metricbeat/module/jolokia/jmx/data.go index dce3aeca47da..8088acfccd7f 100644 --- a/metricbeat/module/jolokia/jmx/data.go +++ b/metricbeat/module/jolokia/jmx/data.go @@ -149,7 +149,7 @@ func parseResponseEntry( ) error { field, exists := mapping.Get(requestMbeanName, attributeName) if !exists { - return errors.Errorf("metric key '%v' not found in response (%+v)", attributeName, mapping) + return errors.Errorf("metric key '%v' for mbean '%s' not found in mapping (%+v)", attributeName, requestMbeanName, mapping) } var key eventKey diff --git a/metricbeat/module/jolokia/jmx/jmx.go b/metricbeat/module/jolokia/jmx/jmx.go index c06b58268c51..5b84d9876076 100644 --- a/metricbeat/module/jolokia/jmx/jmx.go +++ b/metricbeat/module/jolokia/jmx/jmx.go @@ -23,7 +23,7 @@ func init() { const ( defaultScheme = "http" - defaultPath = "/jolokia/?ignoreErrors=true&canonicalNaming=false" + defaultPath = "/jolokia/" ) var ( diff --git a/metricbeat/tests/system/test_jolokia.py b/metricbeat/tests/system/test_jolokia.py index 189dcc911e4d..64c9f42742db 100644 --- a/metricbeat/tests/system/test_jolokia.py +++ b/metricbeat/tests/system/test_jolokia.py @@ -2,25 +2,30 @@ import metricbeat import unittest from nose.plugins.attrib import attr +from parameterized import parameterized class Test(metricbeat.BaseTest): COMPOSE_SERVICES = ['jolokia'] + @parameterized.expand([ + 'java.lang:name=PS MarkSweep,type=GarbageCollector', + 'java.lang:type=GarbageCollector,name=PS MarkSweep' + ]) @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") - def test_jmx(self): + def test_jmx(self, mbean): """ jolokia jmx metricset test """ additional_content = """ jmx.mappings: - - mbean: 'java.lang:type=Runtime' + - mbean: '%s' attributes: - - attr: Uptime - field: uptime -""" + - attr: CollectionCount + field: gc.collection_count +""" % (mbean) self.render_config_template(modules=[{ "name": "jolokia", @@ -40,7 +45,7 @@ def test_jmx(self): evt = output[0] print(evt) - assert evt["jolokia"]["test"]["uptime"] > 0 + assert evt["jolokia"]["test"]["gc"]["collection_count"] >= 0 def get_hosts(self): return [os.getenv('JOLOKIA_HOST', 'localhost') + ':' +