package org.datadog.jmxfetch; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.junit.Test; public class TestApp extends TestCommon { /** * Tag metrics with MBeans parameters. * */ @Test public void testBeanTags() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:type=SimpleTestJavaApp,scope=Co|olScope,host=localhost,component="); initApplication("jmx_bean_tags.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // 14 = 13 metrics from java.lang + 1 metric explicitly defined in the yaml config file assertEquals(14, metrics.size()); List<String> tags = Arrays.asList( "type:SimpleTestJavaApp", "scope:CoolScope", "instance:jmx_test_instance", "jmx_domain:org.datadog.jmxfetch.test", "bean_host:localhost", "component" ); assertMetric("this.is.100", tags, 6); } /** * Generate metric aliases from a `alias_match` regular expression. */ @Test public void testRegexpAliasing() throws Exception { // Expose MBeans registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:foo=Bar,qux=Baz"); initApplication("jmx_alias_match.yaml"); // Collect metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // Assertions // 15 metrics = 13 from `java.lang` + 2 from the user configuration file assertEquals(15, metrics.size()); // Metric aliases are generated from `alias_match` List<String> tags = Arrays.asList( "jmx_domain:org.datadog.jmxfetch.test", "instance:jmx_test_instance", "foo:Bar", "qux:Baz" ); assertMetric("this.is.100.bar.baz", tags, 4); assertMetric("org.datadog.jmxfetch.test.baz.hashmap.thisis0", tags, 4); } /** * Test that specifying no alias on an attribute defined with a detailed hashmap works and picks up a valid default alias */ @Test public void testNoAliasOnDetailedAttribute() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:foo=Bar,qux=Baz"); initApplication("jmx_no_alias.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // Assertions // 14 metrics = 13 from `java.lang` + 1 from the user configuration file assertEquals(14, metrics.size()); // Metric aliases are generated from `alias_match` List<String> tags = Arrays.asList( "jmx_domain:org.datadog.jmxfetch.test", "instance:jmx_test_instance", "foo:Bar", "qux:Baz" ); assertMetric("jmx.org.datadog.jmxfetch.test.should_be100", tags, 4); } /** * Check JMXFetch Cassandra metric aliasing logic, i.e. compliant with CASSANDRA-4009 * when `cassandra_aliasing` flag is enabled, or default. * * More information: https://issues.apache.org/jira/browse/CASSANDRA-4009 */ @Test public void testCassandraBean() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.apache.cassandra.metrics:keyspace=MyKeySpace,type=ColumnFamily,scope=MyColumnFamily,name=PendingTasks"); initApplication("jmx_cassandra.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // 14 = 2*13 metrics from java.lang + 2*1 metric explicitly defined in the yaml config file assertEquals(28, metrics.size()); // Assert compliancy with CASSANDRA-4009 List<String> tags = Arrays.asList( "type:ColumnFamily", "keyspace:MyKeySpace", "ColumnFamily:MyColumnFamily", "jmx_domain:org.apache.cassandra.metrics", "instance:jmx_first_instance" ); assertMetric("cassandra.pending_tasks.should_be100", tags, 5); // Default behavior tags = Arrays.asList( "type:ColumnFamily", "scope:MyColumnFamily", "keyspace:MyKeySpace", "jmx_domain:org.apache.cassandra.metrics", "instance:jmx_second_instance", "name:PendingTasks"); assertMetric("cassandra.metrics.should_be1000", tags, 6); } @Test public void testCassandraDeprecatedBean() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.apache.cassandra.db:type=ColumnFamilies,keyspace=MyKeySpace,columnfamily=MyColumnFamily"); initApplication("jmx_cassandra_deprecated.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // 14 = 13 metrics from java.lang + 1 metric explicitly defined in the yaml config file assertEquals(14, metrics.size()); List<String> tags = Arrays.asList( "type:ColumnFamilies", "keyspace:MyKeySpace", "columnfamily:MyColumnFamily", "jmx_domain:org.apache.cassandra.db", "instance:jmx_test_instance"); assertMetric("cassandra.db.should_be100", tags, 5); } @Test public void testDomainInclude() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.includeme:type=AType"); initApplication("jmx_domain_include.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 28 = 13 metrics from java.lang + 15 metrics implicitly defined assertEquals(28, metrics.size()); } @Test public void testDomainExclude() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.includeme:type=AType"); registerMBean(testApp, "org.datadog.jmxfetch.excludeme:type=AnotherType"); // Initializing application initApplication("jmx_domain_exclude.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 14 = 13 metrics from java.lang + 2 metrics explicitly define- 1 implicitly defined in the exclude section assertEquals(14, metrics.size()); } @Test public void testDomainRegex() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.includeme:type=AType"); registerMBean(testApp, "org.datadog.jmxfetch.includeme.too:type=AType"); registerMBean(testApp, "org.datadog.jmxfetch.includeme.not.me:type=AType"); // Initializing application initApplication("jmx_domain_regex.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 15 = 13 metrics from java.lang + 3 metrics explicitly defined - 1 implicitly defined in exclude section assertEquals(15, metrics.size()); } @Test public void testParameterMatch() throws Exception { // Do not match beans which do not contain types specified in the conf registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:param=AParameter"); // Initializing application initApplication("jmx_list_params_include.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // 13 default metrics from java.lang assertEquals(13, metrics.size()); } @Test public void testListParamsInclude() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:foo=bar,type=RightType"); // Initializing application initApplication("jmx_list_params_include.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 14 = 13 metrics from java.lang + 1 metrics explicitly defined assertEquals(14, metrics.size()); } @Test public void testListParamsExclude() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:type=RightType"); // Initializing application initApplication("jmx_list_params_exclude.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 13 = 13 metrics from java.lang + 2 metrics explicitly defined - 2 explicitly defined assertEquals(13, metrics.size()); } @Test public void testListBeansInclude() throws Exception { // We expose a few metrics through JMX registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:type=IncludeMe"); // Initializing application initApplication("jmx_list_beans_include.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 14 = 13 metrics from java.lang + 1 metrics explicitly defined assertEquals(14, metrics.size()); } @Test public void testListBeansRegexInclude() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.test:type=IncludeMe"); registerMBean(testApp, "org.datadog.jmxfetch.test:type=IncludeMeToo"); registerMBean(testApp, "org.datadog.jmxfetch.test:type=RightType"); // Initializing application initApplication("jmx_list_beans_regex_include.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 15 = 13 metrics from java.lang + 2 metrics explicitly defined assertEquals(15, metrics.size()); } @Test public void testListBeansRegexExclude() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.test:type=IncludeMe"); registerMBean(testApp, "org.datadog.jmxfetch.test:type=ExcludeMe,scope=InScope"); registerMBean(testApp, "org.datadog.jmxfetch.test:scope=OutOfScope"); // Initializing application initApplication("jmx_list_beans_regex_exclude.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 14 = 13 metrics from java.lang + 1 metrics explicitly defined assertEquals(14, metrics.size()); } @Test public void testListBeansExclude() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.test:type=IncludeMe"); registerMBean(testApp, "org.datadog.jmxfetch.test:type=ExcludeMe"); registerMBean(testApp, "org.datadog.jmxfetch.test:type=ExcludeMeToo"); // Initializing application initApplication("jmx_list_beans_exclude.yaml"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // First filter 14 = 13 metrics from java.lang + 1 metrics explicitly defined assertEquals(14, metrics.size()); } @Test public void testExitWatcher() throws Exception { // Test the ExitWatcher logic // Create a temp file File temp = File.createTempFile("exit-jmxfetch-file-name", ".tmp"); temp.deleteOnExit(); ExitWatcher exitWatcher = new ExitWatcher(temp.getAbsolutePath()); assertTrue(exitWatcher.shouldExit()); temp.delete(); assertFalse(exitWatcher.shouldExit()); } @Test public void testMetricTypes() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.test:type=SimpleTestJavaApp"); // We do a first collection initApplication("jmx_histogram.yaml"); run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // We test for the presence and the value of the metrics we want to collect List<String> commonTags = Arrays.asList( "instance:jmx_test_instance", "env:stage", "newTag:test"); // 15 = 13 metrics from java.lang + the 3 collected (gauge and histogram) assertEquals(16, metrics.size()); assertMetric("test.gauge", 1000.0, commonTags, 5, "gauge"); assertMetric("test.gauge_by_default", 42.0, commonTags, 5, "gauge"); assertMetric("test.histogram", 424242, commonTags, 5, "histogram"); // We run a second collection. The counter should now be present run(); metrics = getMetrics(); // 16 = 13 metrics from java.lang + the 4 collected (gauge, histogram and counter) assertEquals(17, metrics.size()); assertMetric("test.gauge", 1000.0, commonTags, 5, "gauge"); assertMetric("test.gauge_by_default", 42.0, commonTags, 5, "gauge"); assertMetric("test.histogram", 424242, commonTags, 5, "histogram"); assertMetric("test.counter", 0.0, commonTags, 5, "counter"); } @Test public void testExcludeTags() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.test:type=SimpleTestJavaApp"); // We do a first collection initApplication("jmx_exclude_tags.yml"); run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // We test for the presence and the value of the metrics we want to collect. // Tags "type", "newTag" and "env" should be excluded List<String> commonTags = Arrays.asList( "instance:jmx_test_instance", "jmx_domain:org.datadog.jmxfetch.test"); // 15 = 13 metrics from java.lang + the 2 collected (gauge and histogram) assertEquals(15, metrics.size()); // There should only left 2 tags per metric assertMetric("test1.gauge", 1000.0, commonTags, 2, "gauge"); assertMetric("test1.histogram", 424242, commonTags, 2, "histogram"); } @Test public void testAdditionalTags() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean(testApp, "org.datadog.jmxfetch.test:type=SimpleTestJavaApp,name=testName"); // We do a first collection initApplication("jmx_additional_tags.yml"); run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // We test for the presence and the value of the metrics we want to collect. // Tags "type", "newTag" and "env" should be excluded List<String> commonTags = Arrays.asList( "instance:jmx_test_instance", "jmx_domain:org.datadog.jmxfetch.test", "type:SimpleTestJavaApp", "name:testName", "simple:SimpleTestJavaApp", "raw_value:value", "unknown_tag:$does-not-exist", "multiple:SimpleTestJavaApp-testName"); // 15 = 13 metrics from java.lang + the 2 collected (gauge and histogram) assertEquals(15, metrics.size()); // There should only left 2 tags per metric assertMetric("test1.gauge", 1000.0, commonTags, 8, "gauge"); assertMetric("test1.histogram", 424242, commonTags, 8, "histogram"); } /** * FIXME: Split this test in multiple sub-tests. */ @Test public void testApp() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp testApp = new SimpleTestJavaApp(); registerMBean( testApp, "org.datadog.jmxfetch.test:type=SimpleTestJavaApp"); // We do a first collection initApplication("jmx.yaml"); run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // 28 = 13 metrics from java.lang + the 5 gauges we are explicitly collecting + 9 gauges implicitly collected // + 1 multi-value, see jmx.yaml in the test/resources folder assertEquals(28, metrics.size()); // We test for the presence and the value of the metrics we want to collect List<String> commonTags = Arrays.asList( "instance:jmx_test_instance", "env:stage", "newTag:test"); assertMetric("this.is.100", 100.0, commonTags, Arrays.asList("foo","gorch","bar:baz") , 8); assertMetric("jmx.org.datadog.jmxfetch.test.number_big", 1.2345678890123457E20, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.long42424242",4.2424242E7, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.int424242", 424242.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.should_be1000", 1000.0, commonTags, 5); assertMetric("test.converted", 5.0, commonTags, 5); assertMetric("test.boolean", 1.0, commonTags, 5); assertMetric("test.defaulted", 32.0, commonTags, 5); assertMetric("subattr.this.is.0", 0.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.atomic42", 42.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.atomic4242", 4242.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.object1337", 13.37, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.primitive_float", 123.4f, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.instance_float", 567.8f, commonTags, 5); assertMetric("multiattr.foo", 1.0, commonTags, Arrays.asList("foo:1", "toto:tata"), 7); assertCoverage(); // We run a second collection. The counter should now be present run(); metrics = getMetrics(); // 30 = 13 metrics from java.lang + the 5 gauges we are explicitly collecting + 9 gauges implicitly collected // + 1 multi-value + 2 counter, see jmx.yaml in the test/resources folder assertEquals(30, metrics.size()); // We test for the same metrics but this time, the counter should be here // Previous metrics assertMetric("this.is.100", 100.0, commonTags, 8); assertMetric("jmx.org.datadog.jmxfetch.test.number_big", 1.2345678890123457E20, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.long42424242",4.2424242E7, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.int424242", 424242.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.should_be1000", 1000.0, commonTags, 5); assertMetric("test.converted", 5.0, commonTags, 5); assertMetric("test.boolean", 1.0, commonTags, 5); assertMetric("test.defaulted", 32.0, commonTags, 5); assertMetric("subattr.this.is.0", 0.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.atomic42", 42.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.atomic4242", 4242.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.object1337", 13.37, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.primitive_float", 123.4f, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.instance_float", 567.8f, commonTags, 5); assertMetric("multiattr.foo", 1.0, commonTags, Arrays.asList("foo:1", "toto:tata"), 7); // Counters assertMetric("subattr.counter", 0.0, commonTags, 5); assertMetric("test.counter", 0.0, commonTags, 5); assertCoverage(); // We run a 3rd collection but this time we increment the counter and we sleep Thread.sleep(5000); testApp.incrementCounter(5); testApp.incrementHashMapCounter(5); testApp.populateTabularData(2); run(); metrics = getMetrics(); // 31 = 13 metrics from java.lang + the 5 gauges we are explicitly collecting + 9 gauges implicitly collected // + 2 multi-value + 2 counter, see jmx.yaml in the test/resources folder assertEquals(30, metrics.size()); // Previous metrics assertMetric("this.is.100", 100.0, commonTags, 8); assertMetric("jmx.org.datadog.jmxfetch.test.number_big", 1.2345678890123457E20, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.long42424242",4.2424242E7, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.int424242", 424242.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.should_be1000", 1000.0, commonTags, 5); assertMetric("test.converted", 5.0, commonTags, 5); assertMetric("test.boolean", 1.0, commonTags, 5); assertMetric("test.defaulted", 32.0, commonTags, 5); assertMetric("subattr.this.is.0", 0.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.atomic42", 42.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.atomic4242", 4242.0, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.object1337", 13.37, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.primitive_float", 123.4f, commonTags, 5); assertMetric("jmx.org.datadog.jmxfetch.test.instance_float", 567.8f, commonTags, 5); assertMetric("multiattr.foo", 2.0, commonTags, Arrays.asList("foo:2", "toto:tata"), 7); // Counter (verify rate metrics within range) assertMetric("subattr.counter", 0.95, 1, commonTags, 5); assertMetric("test.counter", 0.95, 1, commonTags, 5); assertCoverage(); } /** * Test JMX Service Discovery. * */ @Test public void testServiceDiscovery() throws Exception { // We expose a few metrics through JMX SimpleTestJavaApp test = new SimpleTestJavaApp(); registerMBean(test, "org.datadog.jmxfetch.test:foo=Bar,qux=Baz"); registerMBean(test, "org.datadog.jmxfetch.test:type=SimpleTestJavaApp,scope=Co|olScope,host=localhost,component="); registerMBean(test, "org.apache.cassandra.metrics:keyspace=MyKeySpace,type=ColumnFamily,scope=MyColumnFamily,name=PendingTasks"); initApplication("jmx_alias_match.yaml", "jmx_sd_pipe.txt"); // Collecting metrics run(); LinkedList<HashMap<String, Object>> metrics = getMetrics(); // 14 = 13 metrics from java.lang + 1 metric explicitly defined in the yaml config file assertEquals(59, metrics.size()); List<String> tags = Arrays.asList( "type:SimpleTestJavaApp", "scope:CoolScope", "instance:jmx_test_instance", "jmx_domain:org.datadog.jmxfetch.test", "bean_host:localhost", "component" ); assertMetric("this.is.100", tags, 6); // Assert compliancy with CASSANDRA-4009 tags = Arrays.asList( "type:ColumnFamily", "keyspace:MyKeySpace", "ColumnFamily:MyColumnFamily", "jmx_domain:org.apache.cassandra.metrics", "instance:jmx_first_instance" ); assertMetric("cassandra.pending_tasks.should_be100", tags, 5); // Default behavior tags = Arrays.asList( "type:ColumnFamily", "scope:MyColumnFamily", "keyspace:MyKeySpace", "jmx_domain:org.apache.cassandra.metrics", "instance:jmx_second_instance", "name:PendingTasks"); assertMetric("cassandra.metrics.should_be1000", tags, 6); // Metric aliases are generated from `alias_match` tags = Arrays.asList( "jmx_domain:org.datadog.jmxfetch.test", "instance:jmx_test_instance", "foo:Bar", "qux:Baz" ); assertMetric("this.is.100.bar.baz", tags, 4); assertMetric("org.datadog.jmxfetch.test.baz.hashmap.thisis0", tags, 4); } }