blob: 58ee10a774c1a00a391786766add3ce1e696cc2f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.metrics.reporters;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import com.codahale.metrics.Counter;
import org.apache.lucene.util.TestUtil;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrInfoBean;
import org.apache.solr.metrics.SolrCoreMetricManager;
import org.apache.solr.metrics.SolrMetricManager;
import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.metrics.SolrMetricReporter;
import org.apache.solr.metrics.SolrMetricTestUtils;
import org.apache.solr.schema.FieldType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class SolrJmxReporterTest extends SolrTestCaseJ4 {
private static final int MAX_ITERATIONS = 20;
/** The MbeanServer started by the test, that we expect the SolrJmxReporter to find by agentId */
private static MBeanServer TEST_MBEAN_SERVER;
private static String PREFIX;
private String domain;
private SolrCoreMetricManager coreMetricManager;
private SolrMetricManager metricManager;
private String rootName;
@BeforeClass
public static void init() throws Exception {
TEST_MBEAN_SERVER = MBeanServerFactory.createMBeanServer();
PREFIX = getSimpleClassName() + "-";
}
@AfterClass
public static void shutdown() throws Exception {
if (null != TEST_MBEAN_SERVER) {
MBeanServerFactory.releaseMBeanServer(TEST_MBEAN_SERVER);
TEST_MBEAN_SERVER = null;
}
}
@Before
public void beforeTest() throws Exception {
initCore("solrconfig-basic.xml", "schema.xml");
final SolrCore core = h.getCore();
domain = core.getName();
rootName = PREFIX + TestUtil.randomSimpleString(random(), 5, 10);
coreMetricManager = core.getCoreMetricManager();
metricManager = core.getCoreContainer().getMetricManager();
PluginInfo pluginInfo = createReporterPluginInfo(rootName, true);
metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore(),
pluginInfo, coreMetricManager.getTag());
Map<String, SolrMetricReporter> reporters = metricManager.getReporters(coreMetricManager.getRegistryName());
assertTrue("reporters.size should be > 0, but was + " + reporters.size(), reporters.size() > 0);
String reporterName = pluginInfo.name;
String taggedName = reporterName + "@" + coreMetricManager.getTag();
assertNotNull("reporter " + taggedName + " not present among " + reporters, reporters.get(taggedName));
assertTrue("wrong reporter class: " + reporters.get(taggedName), reporters.get(taggedName) instanceof SolrJmxReporter);
SolrJmxReporter reporter = (SolrJmxReporter) reporters.get(taggedName);
assertNotNull("MBean server not found on reporter", reporter.getMBeanServer());
assertEquals("Wrong MBeanServer found on reporter",
TEST_MBEAN_SERVER,
reporter.getMBeanServer());
}
private PluginInfo createReporterPluginInfo(String rootName, boolean enabled) {
Random random = random();
String className = SolrJmxReporter.class.getName();
String reporterName = PREFIX + TestUtil.randomSimpleString(random, 5, 10);
Map<String, Object> attrs = new HashMap<>();
attrs.put(FieldType.CLASS_NAME, className);
attrs.put(CoreAdminParams.NAME, reporterName);
attrs.put("rootName", rootName);
attrs.put("enabled", enabled);
try {
String agentId = (String) TEST_MBEAN_SERVER.getAttribute
(new ObjectName("JMImplementation:type=MBeanServerDelegate"),
"MBeanServerId");
attrs.put("agentId", agentId);
} catch (Exception e) {
throw new RuntimeException("Unable to determine agentId of MBeanServer: " + e.getMessage(), e);
}
boolean shouldOverrideDomain = random.nextBoolean();
if (shouldOverrideDomain) {
domain = PREFIX + TestUtil.randomSimpleString(random);
attrs.put("domain", domain);
}
return new PluginInfo(TestUtil.randomUnicodeString(random), attrs);
}
@After
public void afterTest() throws Exception {
if (null == metricManager) {
return; // test failed to init, nothing to cleanup
}
metricManager.closeReporters(coreMetricManager.getRegistryName());
// sanity check there are no longer any registered beans in our domain....
assertEquals(Collections.emptySet(),
TEST_MBEAN_SERVER.queryMBeans(ObjectName.getInstance(domain + ":*"), null));
coreMetricManager.close();
deleteCore();
}
@Test
public void testReportMetrics() throws Exception {
Random random = random();
Map<String, Counter> registered = new HashMap<>();
String scope = PREFIX + SolrMetricTestUtils.getRandomScope(random, true);
SolrInfoBean.Category category = SolrMetricTestUtils.getRandomCategory(random, true);
int iterations = TestUtil.nextInt(random, 0, MAX_ITERATIONS);
for (int i = 0; i < iterations; ++i) {
Map<String, Counter> metrics = SolrMetricTestUtils.getRandomMetricsWithReplacements(random, registered);
SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(metricManager, category, scope, metrics);
coreMetricManager.registerMetricProducer(scope, producer);
registered.putAll(metrics);
//waitForListener();
Set<ObjectInstance> objects = TEST_MBEAN_SERVER.queryMBeans(null, null);
assertEquals(registered.size(), objects.stream().
filter(o -> scope.equals(o.getObjectName().getKeyProperty("scope")) &&
rootName.equals(o.getObjectName().getDomain())).count());
}
}
@Test
public void testReloadCore() throws Exception {
Random random = random();
String scope = PREFIX + SolrMetricTestUtils.getRandomScope(random, true);
SolrInfoBean.Category category = SolrMetricTestUtils.getRandomCategory(random, true);
Map<String, Counter> metrics = SolrMetricTestUtils.getRandomMetrics(random, true);
SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(metricManager, category, scope, metrics);
coreMetricManager.registerMetricProducer(scope, producer);
Set<ObjectInstance> objects = TEST_MBEAN_SERVER.queryMBeans(null, null);
assertEquals(metrics.size(), objects.stream().
filter(o -> scope.equals(o.getObjectName().getKeyProperty("scope")) &&
o.getObjectName().getDomain().equals(rootName)).count());
h.getCoreContainer().reload(h.getCore().getName());
PluginInfo pluginInfo = createReporterPluginInfo(rootName, true);
metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore(),
pluginInfo, String.valueOf(coreMetricManager.getCore().hashCode()));
coreMetricManager.registerMetricProducer(scope, producer);
objects = TEST_MBEAN_SERVER.queryMBeans(null, null);
assertEquals(metrics.size(), objects.stream().
filter(o -> scope.equals(o.getObjectName().getKeyProperty("scope")) &&
rootName.equals(o.getObjectName().getDomain())).count());
}
private static boolean stopped = false;
@Test
public void testClosedCore() throws Exception {
Set<ObjectInstance> objects = TEST_MBEAN_SERVER.queryMBeans(new ObjectName("*:category=CORE,name=indexDir,*"), null);
assertEquals("Unexpected number of indexDir beans: " + objects.toString(), 1, objects.size());
final ObjectInstance inst = objects.iterator().next();
stopped = false;
try {
Thread t = new Thread() {
public void run() {
while (!stopped) {
try {
Object value = TEST_MBEAN_SERVER.getAttribute(inst.getObjectName(), "Value");
assertNotNull(value);
} catch (InstanceNotFoundException x) {
// no longer present
break;
} catch (Exception e) {
fail("Unexpected error retrieving attribute: " + e.toString());
}
}
}
};
t.start();
Thread.sleep(500);
h.getCoreContainer().unload(h.getCore().getName());
Thread.sleep(2000);
objects = TEST_MBEAN_SERVER.queryMBeans(new ObjectName("*:category=CORE,name=indexDir,*"), null);
assertEquals("Unexpected number of beans after core closed: " + objects, 0, objects.size());
} finally {
stopped = true;
}
}
@Test
public void testEnabled() throws Exception {
String root1 = PREFIX + TestUtil.randomSimpleString(random(), 5, 10);
PluginInfo pluginInfo1 = createReporterPluginInfo(root1, true);
metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore(),
pluginInfo1, coreMetricManager.getTag());
String root2 = PREFIX + TestUtil.randomSimpleString(random(), 5, 10);
assertFalse(root2.equals(root1));
PluginInfo pluginInfo2 = createReporterPluginInfo(root2, false);
metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore(),
pluginInfo2, coreMetricManager.getTag());
Map<String, SolrMetricReporter> reporters = metricManager.getReporters(coreMetricManager.getRegistryName());
assertTrue(reporters.containsKey(pluginInfo1.name + "@" + coreMetricManager.getTag()));
assertTrue(reporters.containsKey(pluginInfo2.name + "@" + coreMetricManager.getTag()));
String scope = PREFIX + SolrMetricTestUtils.getRandomScope(random(), true);
SolrInfoBean.Category category = SolrMetricTestUtils.getRandomCategory(random(), true);
Map<String, Counter> metrics = SolrMetricTestUtils.getRandomMetrics(random(), true);
SolrMetricProducer producer = SolrMetricTestUtils.getProducerOf(metricManager, category, scope, metrics);
coreMetricManager.registerMetricProducer(scope, producer);
Set<ObjectInstance> objects = TEST_MBEAN_SERVER.queryMBeans(null, null);
assertEquals(metrics.size(), objects.stream().
filter(o -> scope.equals(o.getObjectName().getKeyProperty("scope")) &&
root1.equals(o.getObjectName().getDomain())).count());
assertEquals(0, objects.stream().
filter(o -> scope.equals(o.getObjectName().getKeyProperty("scope")) &&
root2.equals(o.getObjectName().getDomain())).count());
}
}