/*
* 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.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import java.rmi.registry.LocateRegistry;
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.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class SolrJmxReporterTest extends SolrTestCaseJ4 {
private static final int MAX_ITERATIONS = 20;
private static int jmxPort;
private String domain;
private SolrCoreMetricManager coreMetricManager;
private SolrMetricManager metricManager;
private SolrJmxReporter reporter;
private MBeanServer mBeanServer;
private String reporterName;
private String rootName;
@BeforeClass
public static void init() throws Exception {
jmxPort = getNextAvailablePort();
assertFalse(jmxPort == -1);
LocateRegistry.createRegistry(jmxPort);
}
@Before
public void beforeTest() throws Exception {
initCore("solrconfig-basic.xml", "schema.xml");
final SolrCore core = h.getCore();
domain = core.getName();
rootName = TestUtil.randomSimpleString(random(), 5, 10);
coreMetricManager = core.getCoreMetricManager();
metricManager = core.getCoreContainer().getMetricManager();
PluginInfo pluginInfo = createReporterPluginInfo(rootName, true);
metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore().getResourceLoader(),
pluginInfo, coreMetricManager.getTag());
Map<String, SolrMetricReporter> reporters = metricManager.getReporters(coreMetricManager.getRegistryName());
assertTrue("reporters.size should be > 0, but was + " + reporters.size(), reporters.size() > 0);
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);
reporter = (SolrJmxReporter) reporters.get(taggedName);
mBeanServer = reporter.getMBeanServer();
assertNotNull("MBean server not found.", mBeanServer);
}
private PluginInfo createReporterPluginInfo(String rootName, boolean enabled) {
Random random = random();
String className = SolrJmxReporter.class.getName();
String reporterName = 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);
attrs.put("serviceUrl", "service:jmx:rmi:///jndi/rmi://localhost:" + jmxPort + "/solrjmx");
boolean shouldOverrideDomain = random.nextBoolean();
if (shouldOverrideDomain) {
domain = TestUtil.randomSimpleString(random);
attrs.put("domain", domain);
}
return new PluginInfo(TestUtil.randomUnicodeString(random), attrs);
}
@After
public void afterTest() throws Exception {
metricManager.closeReporters(coreMetricManager.getRegistryName());
Set<ObjectInstance> objects =
mBeanServer.queryMBeans(ObjectName.getInstance(domain + ":*"), null);
assertTrue(objects.isEmpty());
coreMetricManager.close();
deleteCore();
}
@Test
public void testReportMetrics() throws Exception {
Random random = random();
Map<String, Counter> registered = new HashMap<>();
String scope = 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 = mBeanServer.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 = 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 = mBeanServer.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().getResourceLoader(),
pluginInfo, String.valueOf(coreMetricManager.getCore().hashCode()));
coreMetricManager.registerMetricProducer(scope, producer);
objects = mBeanServer.queryMBeans(null, null);
assertEquals(metrics.size(), objects.stream().
filter(o -> scope.equals(o.getObjectName().getKeyProperty("scope")) &&
rootName.equals(o.getObjectName().getDomain())).count());
}
@Test
public void testEnabled() throws Exception {
String root1 = TestUtil.randomSimpleString(random(), 5, 10);
PluginInfo pluginInfo1 = createReporterPluginInfo(root1, true);
metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore().getResourceLoader(),
pluginInfo1, coreMetricManager.getTag());
String root2 = TestUtil.randomSimpleString(random(), 5, 10);
assertFalse(root2.equals(root1));
PluginInfo pluginInfo2 = createReporterPluginInfo(root2, false);
metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore().getResourceLoader(),
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 = 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 = mBeanServer.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());
}
}