This is an automated email from the ASF dual-hosted git repository. mlbiscoc pushed a commit to branch feature/SOLR-17458-rebased in repository https://gitbox.apache.org/repos/asf/solr.git
commit 3d35f4defe9708ec7c8c51ed3fa50dd99b898b91 Author: Matthew Biscocho <[email protected]> AuthorDate: Wed Aug 6 17:35:10 2025 -0400 SOLR-17827: Remove JXM, SLF4J and Graphite reporters (#3443) * Deprecate JMX, SLF4J and Graphite reporters * Bring back client reporter cache * Add note to Solr 10 changes --- .../java/org/apache/solr/core/SolrXmlConfig.java | 37 +- .../metrics/reporters/SolrGraphiteReporter.java | 117 ---- .../solr/metrics/reporters/SolrJmxReporter.java | 254 ------- .../solr/metrics/reporters/SolrSlf4jReporter.java | 189 ----- .../metrics/reporters/jmx/JmxMetricsReporter.java | 777 --------------------- .../reporters/jmx/JmxObjectNameFactory.java | 169 ----- .../solr/metrics/reporters/jmx/package-info.java | 22 - .../org/apache/solr/core/TestJmxIntegration.java | 279 -------- .../apache/solr/metrics/SolrMetricManagerTest.java | 71 -- .../solr/metrics/SolrMetricsIntegrationTest.java | 64 -- .../reporters/SolrGraphiteReporterTest.java | 123 ---- .../reporters/SolrJmxReporterCloudTest.java | 128 ---- .../metrics/reporters/SolrJmxReporterTest.java | 316 --------- .../metrics/reporters/SolrSlf4jReporterTest.java | 115 --- .../pages/major-changes-in-solr-10.adoc | 3 +- .../src/java/org/apache/solr/util/TestHarness.java | 12 +- 16 files changed, 4 insertions(+), 2672 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java index 1206dea0d3a..84506708f6b 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java +++ b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java @@ -27,7 +27,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -37,7 +36,6 @@ import java.util.Set; import java.util.function.Consumer; import java.util.regex.Pattern; import java.util.stream.Collectors; -import javax.management.MBeanServer; import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.cloud.ClusterSingleton; import org.apache.solr.cluster.placement.PlacementPluginFactory; @@ -49,13 +47,11 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.Utils; import org.apache.solr.logging.LogWatcherConfig; -import org.apache.solr.metrics.reporters.SolrJmxReporter; import org.apache.solr.search.CacheConfig; import org.apache.solr.servlet.SolrDispatchFilter; import org.apache.solr.update.UpdateShardHandlerConfig; import org.apache.solr.util.DOMConfigNode; import org.apache.solr.util.DataConfigNode; -import org.apache.solr.util.JmxUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.InputSource; @@ -737,8 +733,7 @@ public class SolrXmlConfig { : Integer.parseInt(threadsCachingIntervalSeconds.toString()))); } - PluginInfo[] reporterPlugins = getMetricReporterPluginInfos(metrics); - return builder.setMetricReporterPlugins(reporterPlugins).build(); + return builder.build(); } private static Map<String, CacheConfig> getCachesConfig( @@ -768,36 +763,6 @@ public class SolrXmlConfig { return o; } - private static PluginInfo[] getMetricReporterPluginInfos(ConfigNode metrics) { - List<PluginInfo> configs = new ArrayList<>(); - boolean hasJmxReporter = false; - for (ConfigNode node : metrics.getAll("reporter")) { - PluginInfo info = getPluginInfo(node); - if (info == null) { - continue; - } - String clazz = info.className; - if (clazz != null && clazz.equals(SolrJmxReporter.class.getName())) { - hasJmxReporter = true; - } - configs.add(info); - } - - // if there's an MBean server running but there was no JMX reporter then add a default one - MBeanServer mBeanServer = JmxUtil.findFirstMBeanServer(); - if (mBeanServer != null && !hasJmxReporter) { - log.debug( - "MBean server found: {}, but no JMX reporters were configured - adding default JMX reporter.", - mBeanServer); - Map<String, Object> attributes = new HashMap<>(); - attributes.put("name", "default"); - attributes.put("class", SolrJmxReporter.class.getName()); - PluginInfo defaultPlugin = new PluginInfo("reporter", attributes); - configs.add(defaultPlugin); - } - return configs.toArray(new PluginInfo[0]); - } - /** * Deprecated as of 9.3, will be removed in 10.0 * diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/SolrGraphiteReporter.java b/solr/core/src/java/org/apache/solr/metrics/reporters/SolrGraphiteReporter.java deleted file mode 100644 index b63fbbcd28b..00000000000 --- a/solr/core/src/java/org/apache/solr/metrics/reporters/SolrGraphiteReporter.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 com.codahale.metrics.MetricFilter; -import com.codahale.metrics.graphite.Graphite; -import com.codahale.metrics.graphite.GraphiteReporter; -import com.codahale.metrics.graphite.GraphiteSender; -import com.codahale.metrics.graphite.PickledGraphite; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import org.apache.solr.metrics.FilteringSolrMetricReporter; -import org.apache.solr.metrics.SolrMetricManager; - -/** Metrics reporter that wraps {@link com.codahale.metrics.graphite.GraphiteReporter}. */ -public class SolrGraphiteReporter extends FilteringSolrMetricReporter { - - private String host = null; - private int port = -1; - private boolean pickled = false; - private String instancePrefix = null; - private GraphiteReporter reporter = null; - - private static final ReporterClientCache<GraphiteSender> serviceRegistry = - new ReporterClientCache<>(); - - /** - * Create a Graphite reporter for metrics managed in a named registry. - * - * @param metricManager metric manager instance that manages the selected registry - * @param registryName registry to use, one of registries managed by {@link SolrMetricManager} - */ - public SolrGraphiteReporter(SolrMetricManager metricManager, String registryName) { - super(metricManager, registryName); - } - - public void setHost(String host) { - this.host = host; - } - - public void setPort(int port) { - this.port = port; - } - - public void setPrefix(String prefix) { - this.instancePrefix = prefix; - } - - public void setPickled(boolean pickled) { - this.pickled = pickled; - } - - @Override - protected void doInit() { - if (reporter != null) { - throw new IllegalStateException("Already started once?"); - } - GraphiteSender graphite; - String id = host + ":" + port + ":" + pickled; - if (pickled) { - graphite = new PickledGraphite(host, port); - } else { - graphite = new Graphite(host, port); - } - if (instancePrefix == null) { - instancePrefix = registryName; - } else { - instancePrefix = instancePrefix + "." + registryName; - } - GraphiteReporter.Builder builder = - GraphiteReporter.forRegistry(metricManager.registry(registryName)) - .prefixedWith(instancePrefix) - .convertRatesTo(TimeUnit.SECONDS) - .convertDurationsTo(TimeUnit.MILLISECONDS); - final MetricFilter filter = newMetricFilter(); - builder = builder.filter(filter); - reporter = builder.build(graphite); - reporter.start(period, TimeUnit.SECONDS); - } - - @Override - protected void validate() throws IllegalStateException { - if (host == null) { - throw new IllegalStateException( - "Init argument 'host' must be set to a valid Graphite server name."); - } - if (port == -1) { - throw new IllegalStateException( - "Init argument 'port' must be set to a valid Graphite server port."); - } - if (period < 1) { - throw new IllegalStateException( - "Init argument 'period' is in time unit 'seconds' and must be at least 1."); - } - } - - @Override - public void close() throws IOException { - if (reporter != null) { - reporter.close(); - } - } -} diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/SolrJmxReporter.java b/solr/core/src/java/org/apache/solr/metrics/reporters/SolrJmxReporter.java deleted file mode 100644 index bbcaa8a494a..00000000000 --- a/solr/core/src/java/org/apache/solr/metrics/reporters/SolrJmxReporter.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * 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 com.codahale.metrics.MetricFilter; -import com.codahale.metrics.MetricRegistry; -import java.lang.invoke.MethodHandles; -import java.util.Locale; -import javax.management.MBeanServer; -import org.apache.solr.metrics.FilteringSolrMetricReporter; -import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.SolrMetricReporter; -import org.apache.solr.metrics.reporters.jmx.JmxMetricsReporter; -import org.apache.solr.metrics.reporters.jmx.JmxObjectNameFactory; -import org.apache.solr.util.JmxUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A {@link SolrMetricReporter} that finds (or creates) a MBeanServer from the given configuration - * and registers metrics to it with JMX. - * - * <p>NOTE: {@link com.codahale.metrics.jmx.JmxReporter} that this class uses exports only newly - * added metrics (it doesn't process already existing metrics in a registry) - */ -// NOCOMMIT: This JMX reporter looks to be wrapped over a Dropwizard registry. We need to migrate -// this to OTEL. Maybe we can look at available otel shims for JMX? -public class SolrJmxReporter extends FilteringSolrMetricReporter { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private static final ReporterClientCache<MBeanServer> serviceRegistry = - new ReporterClientCache<>(); - - private String domain; - private String agentId; - private String serviceUrl; - private String rootName; - - private MetricRegistry registry; - private MBeanServer mBeanServer; - private JmxMetricsReporter reporter; - private String instanceTag; - private boolean started; - - /** - * Creates a new instance of {@link SolrJmxReporter}. - * - * @param registryName name of the registry to report - */ - public SolrJmxReporter(SolrMetricManager metricManager, String registryName) { - super(metricManager, registryName); - period = 0; // setting to zero to indicate not applicable - setDomain(registryName); - } - - @Override - protected synchronized void doInit() { - if (serviceUrl != null && agentId != null) { - mBeanServer = JmxUtil.findFirstMBeanServer(); - log.warn( - "No more than one of serviceUrl({}) and agentId({}) should be configured, using first MBeanServer {} instead of configuration.", - serviceUrl, - agentId, - mBeanServer); - } else if (serviceUrl != null) { - // reuse existing services - mBeanServer = - serviceRegistry.getOrCreate( - serviceUrl, () -> JmxUtil.findMBeanServerForServiceUrl(serviceUrl)); - } else if (agentId != null) { - mBeanServer = JmxUtil.findMBeanServerForAgentId(agentId); - } else { - mBeanServer = JmxUtil.findFirstMBeanServer(); - log.debug( - "No serviceUrl or agentId was configured, using first MBeanServer: {}", mBeanServer); - } - - if (mBeanServer == null) { - log.warn("No JMX server found. Not exposing Solr metrics via JMX."); - return; - } - - if (domain == null || domain.isEmpty()) { - domain = registryName; - } - String fullDomain = domain; - if (rootName != null && !rootName.isEmpty()) { - fullDomain = rootName + "." + domain; - } - JmxObjectNameFactory jmxObjectNameFactory = - new JmxObjectNameFactory(pluginInfo.name, fullDomain); - registry = metricManager.registry(registryName); - - final MetricFilter filter = newMetricFilter(); - instanceTag = Integer.toHexString(this.hashCode()); - reporter = - JmxMetricsReporter.forRegistry(registry) - .registerWith(mBeanServer) - .inDomain(fullDomain) - .filter(filter) - .createsObjectNamesWith(jmxObjectNameFactory) - .withTag(instanceTag) - .build(); - reporter.start(); - started = true; - log.debug( - "JMX monitoring for '{}' (registry '{}') enabled at server: {}", - fullDomain, - registryName, - mBeanServer); - } - - /** For unit tests. */ - public String getInstanceTag() { - return instanceTag; - } - - /** Stops the reporter from publishing metrics. */ - @Override - public synchronized void close() { - log.debug("Closing reporter {} for registry {}/{}", this, registryName, registry); - started = false; - if (reporter != null) { - reporter.close(); - reporter = null; - } - } - - /** - * Validates that the reporter has been correctly configured. Note that all configurable arguments - * are currently optional. - * - * @throws IllegalStateException if the reporter is not properly configured - */ - @Override - protected void validate() throws IllegalStateException { - if (period != 0) { - throw new IllegalStateException( - "Init argument 'period' is not supported for " + getClass().getCanonicalName()); - } - } - - /** - * Set root name of the JMX hierarchy for this reporter. Default (null or empty) is none, ie. the - * hierarchy will start from the domain name. - * - * @param rootName root name of the JMX name hierarchy, or null or empty for default. - */ - public void setRootName(String rootName) { - this.rootName = rootName; - } - - /** - * Sets the domain with which MBeans are published. If none is set, the domain defaults to the - * name of the registry. - * - * @param domain the domain - */ - public void setDomain(String domain) { - if (domain != null) { - this.domain = domain; - } else { - this.domain = registryName; - } - } - - /** - * Sets the service url for a JMX server. Note that this configuration is optional. - * - * @param serviceUrl the service url - */ - public void setServiceUrl(String serviceUrl) { - this.serviceUrl = serviceUrl; - } - - /** - * Sets the agent id for a JMX server. Note that this configuration is optional. - * - * @param agentId the agent id - */ - public void setAgentId(String agentId) { - this.agentId = agentId; - } - - /** Return configured agentId or null. */ - public String getAgentId() { - return agentId; - } - - /** Return configured serviceUrl or null. */ - public String getServiceUrl() { - return serviceUrl; - } - - /** Return configured domain or null. */ - public String getDomain() { - return domain; - } - - /** - * Return the reporter's MBeanServer. - * - * @return the reporter's MBeanServer - */ - public MBeanServer getMBeanServer() { - return mBeanServer; - } - - /** - * For unit tests. - * - * @return true if this reporter is going to report metrics to JMX. - */ - public boolean isActive() { - return reporter != null; - } - - /** - * For unit tests. - * - * @return true if this reporter has been started and is reporting metrics to JMX. - */ - public boolean isStarted() { - return started; - } - - @Override - public String toString() { - return String.format( - Locale.ENGLISH, - "[%s@%s: rootName = %s, domain = %s, service url = %s, agent id = %s]", - getClass().getName(), - Integer.toHexString(hashCode()), - rootName, - domain, - serviceUrl, - agentId); - } -} diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/SolrSlf4jReporter.java b/solr/core/src/java/org/apache/solr/metrics/reporters/SolrSlf4jReporter.java deleted file mode 100644 index 117d414085f..00000000000 --- a/solr/core/src/java/org/apache/solr/metrics/reporters/SolrSlf4jReporter.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * 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 com.codahale.metrics.Counter; -import com.codahale.metrics.Gauge; -import com.codahale.metrics.Histogram; -import com.codahale.metrics.Meter; -import com.codahale.metrics.MetricFilter; -import com.codahale.metrics.ScheduledReporter; -import com.codahale.metrics.Slf4jReporter; -import com.codahale.metrics.Timer; -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.util.Map; -import java.util.SortedMap; -import java.util.concurrent.TimeUnit; -import org.apache.solr.metrics.FilteringSolrMetricReporter; -import org.apache.solr.metrics.SolrMetricManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -/** - * Metrics reporter that wraps {@link com.codahale.metrics.Slf4jReporter}. The following init - * arguments are supported: - * - * <ul> - * <li><code>period</code>: (optional, int) number of seconds between reports, default is 60, - * <li><code>prefix</code>: (optional, str) prefix for metric names, in addition to registry name. - * Default is none, ie. just registry name. - * <li><code>filter</code>: (optional, str) if not empty only metric names that start with this - * value will be reported, default is all metrics from a registry, - * <li><code>logger</code>: (optional, str) logger name to use. Default is the metrics group, eg. - * <code>solr.jvm</code>, <code>solr.core</code>, etc - * </ul> - */ -// NOCOMMIT: Will we still be supporting this? Need to understand how Slf4j works and if it is even -// possible to wrap OTEL into this like dropwizard. -public class SolrSlf4jReporter extends FilteringSolrMetricReporter { - - @SuppressWarnings("unused") // we need this to pass validate-source-patterns - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private String instancePrefix = null; - private String logger = null; - private Map<String, String> mdcContext; - private Slf4jReporterWrapper reporter; - private boolean active; - - // this wrapper allows us to set MDC context - unfortunately it's not possible to - // simply override {@link Slf4jReporter#report()} because its constructor is private - private class Slf4jReporterWrapper extends ScheduledReporter { - final Slf4jReporter delegate; - final Map<String, String> mdcContext; - - Slf4jReporterWrapper( - String logger, - Map<String, String> mdcContext, - Slf4jReporter delegate, - TimeUnit rateUnit, - TimeUnit durationUnit) { - super(metricManager.registry(registryName), logger, null, rateUnit, durationUnit); - this.delegate = delegate; - this.mdcContext = mdcContext; - } - - @Override - public void report() { - // set up MDC - MDC.setContextMap(mdcContext); - try { - delegate.report(); - } finally { - // clear MDC - MDC.clear(); - } - } - - @Override - @SuppressWarnings( - "rawtypes") // super uses raw Gauge, so we're stuck with it until DropWizard 5.0 - public void report( - SortedMap<String, Gauge> gauges, - SortedMap<String, Counter> counters, - SortedMap<String, Histogram> histograms, - SortedMap<String, Meter> meters, - SortedMap<String, Timer> timers) { - throw new UnsupportedOperationException("this method should never be called here!"); - } - - @Override - public void close() { - super.close(); - delegate.close(); - } - } - - /** - * Create a SLF4J reporter for metrics managed in a named registry. - * - * @param metricManager metric manager instance that manages the selected registry - * @param registryName registry to use, one of registries managed by {@link SolrMetricManager} - */ - public SolrSlf4jReporter(SolrMetricManager metricManager, String registryName) { - super(metricManager, registryName); - } - - public void setPrefix(String prefix) { - this.instancePrefix = prefix; - } - - public void setLogger(String logger) { - this.logger = logger; - } - - @Override - protected void doInit() { - mdcContext = MDC.getCopyOfContextMap(); - mdcContext.put("registry", "m:" + registryName); - Slf4jReporter.Builder builder = - Slf4jReporter.forRegistry(metricManager.registry(registryName)) - .convertRatesTo(TimeUnit.SECONDS) - .convertDurationsTo(TimeUnit.MILLISECONDS); - - final MetricFilter filter = newMetricFilter(); - builder = builder.filter(filter); - if (instancePrefix != null) { - builder = builder.prefixedWith(instancePrefix); - } - if (logger == null || logger.isEmpty()) { - // construct logger name from Group - if (pluginInfo.attributes.containsKey("group")) { - logger = SolrMetricManager.enforcePrefix(pluginInfo.attributes.get("group")); - } else if (pluginInfo.attributes.containsKey("registry")) { - String reg = SolrMetricManager.enforcePrefix(pluginInfo.attributes.get("registry")); - String[] names = reg.split("\\."); - if (names.length < 2) { - logger = reg; - } else { - logger = names[0] + "." + names[1]; - } - } - } - builder = builder.outputTo(LoggerFactory.getLogger(logger)); - // build BUT don't start - scheduled execution is handled by the wrapper - Slf4jReporter delegate = builder.build(); - reporter = - new Slf4jReporterWrapper( - logger, mdcContext, delegate, TimeUnit.SECONDS, TimeUnit.MILLISECONDS); - reporter.start(period, TimeUnit.SECONDS); - active = true; - } - - @Override - protected void validate() throws IllegalStateException { - if (period < 1) { - throw new IllegalStateException( - "Init argument 'period' is in time unit 'seconds' and must be at least 1."); - } - } - - @Override - public void close() throws IOException { - if (reporter != null) { - reporter.close(); - } - active = false; - } - - // for unit tests - boolean isActive() { - return active; - } -} diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/JmxMetricsReporter.java b/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/JmxMetricsReporter.java deleted file mode 100644 index bd9eb1b2b21..00000000000 --- a/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/JmxMetricsReporter.java +++ /dev/null @@ -1,777 +0,0 @@ -/* - * 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.jmx; - -import com.codahale.metrics.Counter; -import com.codahale.metrics.Gauge; -import com.codahale.metrics.Histogram; -import com.codahale.metrics.Meter; -import com.codahale.metrics.Metered; -import com.codahale.metrics.Metric; -import com.codahale.metrics.MetricFilter; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.MetricRegistryListener; -import com.codahale.metrics.Reporter; -import com.codahale.metrics.Timer; -import com.codahale.metrics.jmx.DefaultObjectNameFactory; -import com.codahale.metrics.jmx.ObjectNameFactory; -import java.io.Closeable; -import java.lang.invoke.MethodHandles; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import javax.management.Attribute; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.JMException; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.Query; -import javax.management.QueryExp; -import org.apache.solr.metrics.MetricsMap; -import org.apache.solr.metrics.SolrMetricManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This is a modified copy of Dropwizard's {@link com.codahale.metrics.jmx.JmxReporter} and classes - * that it internally uses, with a few important differences: - * - * <ul> - * <li>this class knows that it can directly use {@link MetricsMap} as a dynamic MBean. - * <li>this class allows us to "tag" MBean instances so that we can later unregister only - * instances registered with the same tag. - * <li>this class processes all metrics already existing in the registry at the time when reporter - * is started. - * </ul> - */ -public class JmxMetricsReporter implements Reporter, Closeable { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - public static final String INSTANCE_TAG = "_instanceTag"; - - public static Builder forRegistry(MetricRegistry registry) { - return new Builder(registry); - } - - /** Builder for the {@link JmxMetricsReporter} class. */ - public static class Builder { - private final MetricRegistry registry; - private MBeanServer mBeanServer; - private TimeUnit rateUnit; - private TimeUnit durationUnit; - private ObjectNameFactory objectNameFactory; - private MetricFilter filter = MetricFilter.ALL; - private String domain; - private String tag; - - private Builder(MetricRegistry registry) { - this.registry = registry; - this.rateUnit = TimeUnit.SECONDS; - this.durationUnit = TimeUnit.MILLISECONDS; - this.domain = "metrics"; - this.objectNameFactory = new DefaultObjectNameFactory(); - } - - /** - * Register MBeans with the given {@link MBeanServer}. - * - * @param mBeanServer an {@link MBeanServer} - * @return {@code this} - */ - public Builder registerWith(MBeanServer mBeanServer) { - this.mBeanServer = mBeanServer; - return this; - } - - /** - * Convert rates to the given time unit. - * - * @param rateUnit a unit of time - * @return {@code this} - */ - public Builder convertRatesTo(TimeUnit rateUnit) { - this.rateUnit = rateUnit; - return this; - } - - public Builder createsObjectNamesWith(ObjectNameFactory onFactory) { - if (onFactory == null) { - throw new IllegalArgumentException("null objectNameFactory"); - } - this.objectNameFactory = onFactory; - return this; - } - - /** - * Convert durations to the given time unit. - * - * @param durationUnit a unit of time - * @return {@code this} - */ - public Builder convertDurationsTo(TimeUnit durationUnit) { - this.durationUnit = durationUnit; - return this; - } - - /** - * Only report metrics which match the given filter. - * - * @param filter a {@link MetricFilter} - * @return {@code this} - */ - public Builder filter(MetricFilter filter) { - this.filter = filter; - return this; - } - - public Builder inDomain(String domain) { - this.domain = domain; - return this; - } - - public Builder withTag(String tag) { - this.tag = tag; - return this; - } - - public JmxMetricsReporter build() { - if (tag == null) { - tag = Integer.toHexString(this.hashCode()); - } - return new JmxMetricsReporter( - mBeanServer, domain, registry, filter, rateUnit, durationUnit, objectNameFactory, tag); - } - } - - // MBean interfaces and base classes - public interface MetricMBean { - ObjectName objectName(); - - // this strange-looking method name is used for producing "_instanceTag" attribute name - String get_instanceTag(); - } - - private abstract static class AbstractBean implements MetricMBean { - private final ObjectName objectName; - private final String instanceTag; - - AbstractBean(ObjectName objectName, String instanceTag) { - this.objectName = objectName; - this.instanceTag = instanceTag; - } - - @Override - public String get_instanceTag() { - return instanceTag; - } - - @Override - public ObjectName objectName() { - return objectName; - } - } - - public interface JmxGaugeMBean extends MetricMBean { - Object getValue(); - } - - private static class JmxGauge extends AbstractBean implements JmxGaugeMBean { - private final Gauge<?> metric; - - private JmxGauge(Gauge<?> metric, ObjectName objectName, String tag) { - super(objectName, tag); - this.metric = metric; - } - - @Override - public Object getValue() { - return metric.getValue(); - } - } - - public interface JmxCounterMBean extends MetricMBean { - long getCount(); - } - - private static class JmxCounter extends AbstractBean implements JmxCounterMBean { - private final Counter metric; - - private JmxCounter(Counter metric, ObjectName objectName, String tag) { - super(objectName, tag); - this.metric = metric; - } - - @Override - public long getCount() { - return metric.getCount(); - } - } - - public interface JmxHistogramMBean extends MetricMBean { - long getCount(); - - long getMin(); - - long getMax(); - - double getMean(); - - double getStdDev(); - - double get50thPercentile(); - - double get75thPercentile(); - - double get95thPercentile(); - - double get98thPercentile(); - - double get99thPercentile(); - - double get999thPercentile(); - - long[] values(); - - long getSnapshotSize(); - } - - private static class JmxHistogram extends AbstractBean implements JmxHistogramMBean { - private final Histogram metric; - - private JmxHistogram(Histogram metric, ObjectName objectName, String tag) { - super(objectName, tag); - this.metric = metric; - } - - @Override - public double get50thPercentile() { - return metric.getSnapshot().getMedian(); - } - - @Override - public long getCount() { - return metric.getCount(); - } - - @Override - public long getMin() { - return metric.getSnapshot().getMin(); - } - - @Override - public long getMax() { - return metric.getSnapshot().getMax(); - } - - @Override - public double getMean() { - return metric.getSnapshot().getMean(); - } - - @Override - public double getStdDev() { - return metric.getSnapshot().getStdDev(); - } - - @Override - public double get75thPercentile() { - return metric.getSnapshot().get75thPercentile(); - } - - @Override - public double get95thPercentile() { - return metric.getSnapshot().get95thPercentile(); - } - - @Override - public double get98thPercentile() { - return metric.getSnapshot().get98thPercentile(); - } - - @Override - public double get99thPercentile() { - return metric.getSnapshot().get99thPercentile(); - } - - @Override - public double get999thPercentile() { - return metric.getSnapshot().get999thPercentile(); - } - - @Override - public long[] values() { - return metric.getSnapshot().getValues(); - } - - @Override - public long getSnapshotSize() { - return metric.getSnapshot().size(); - } - } - - public interface JmxMeterMBean extends MetricMBean { - long getCount(); - - double getMeanRate(); - - double getOneMinuteRate(); - - double getFiveMinuteRate(); - - double getFifteenMinuteRate(); - - String getRateUnit(); - } - - private static class JmxMeter extends AbstractBean implements JmxMeterMBean { - private final Metered metric; - private final double rateFactor; - private final String rateUnit; - - private JmxMeter(Metered metric, ObjectName objectName, TimeUnit rateUnit, String tag) { - super(objectName, tag); - this.metric = metric; - this.rateFactor = rateUnit.toSeconds(1); - this.rateUnit = ("events/" + calculateRateUnit(rateUnit)).intern(); - } - - @Override - public long getCount() { - return metric.getCount(); - } - - @Override - public double getMeanRate() { - return metric.getMeanRate() * rateFactor; - } - - @Override - public double getOneMinuteRate() { - return metric.getOneMinuteRate() * rateFactor; - } - - @Override - public double getFiveMinuteRate() { - return metric.getFiveMinuteRate() * rateFactor; - } - - @Override - public double getFifteenMinuteRate() { - return metric.getFifteenMinuteRate() * rateFactor; - } - - @Override - public String getRateUnit() { - return rateUnit; - } - - private String calculateRateUnit(TimeUnit unit) { - final String s = unit.toString().toLowerCase(Locale.US); - return s.substring(0, s.length() - 1); - } - } - - public interface JmxTimerMBean extends JmxMeterMBean { - double getMin(); - - double getMax(); - - double getMean(); - - double getStdDev(); - - double get50thPercentile(); - - double get75thPercentile(); - - double get95thPercentile(); - - double get98thPercentile(); - - double get99thPercentile(); - - double get999thPercentile(); - - long[] values(); - - String getDurationUnit(); - } - - private static class JmxTimer extends JmxMeter implements JmxTimerMBean { - private final Timer metric; - private final double durationFactor; - private final String durationUnit; - - private JmxTimer( - Timer metric, ObjectName objectName, TimeUnit rateUnit, TimeUnit durationUnit, String tag) { - super(metric, objectName, rateUnit, tag); - this.metric = metric; - this.durationFactor = 1.0 / durationUnit.toNanos(1); - this.durationUnit = durationUnit.toString().toLowerCase(Locale.US); - } - - @Override - public double get50thPercentile() { - return metric.getSnapshot().getMedian() * durationFactor; - } - - @Override - public double getMin() { - return metric.getSnapshot().getMin() * durationFactor; - } - - @Override - public double getMax() { - return metric.getSnapshot().getMax() * durationFactor; - } - - @Override - public double getMean() { - return metric.getSnapshot().getMean() * durationFactor; - } - - @Override - public double getStdDev() { - return metric.getSnapshot().getStdDev() * durationFactor; - } - - @Override - public double get75thPercentile() { - return metric.getSnapshot().get75thPercentile() * durationFactor; - } - - @Override - public double get95thPercentile() { - return metric.getSnapshot().get95thPercentile() * durationFactor; - } - - @Override - public double get98thPercentile() { - return metric.getSnapshot().get98thPercentile() * durationFactor; - } - - @Override - public double get99thPercentile() { - return metric.getSnapshot().get99thPercentile() * durationFactor; - } - - @Override - public double get999thPercentile() { - return metric.getSnapshot().get999thPercentile() * durationFactor; - } - - @Override - public long[] values() { - return metric.getSnapshot().getValues(); - } - - @Override - public String getDurationUnit() { - return durationUnit; - } - } - - private static class JmxListener implements MetricRegistryListener { - - private final String name; - private final MBeanServer mBeanServer; - private final MetricFilter filter; - private final TimeUnit rateUnit; - private final TimeUnit durationUnit; - private final Map<ObjectName, ObjectName> registered; - private final ObjectNameFactory objectNameFactory; - private final String tag; - private final QueryExp exp; - - private JmxListener( - MBeanServer mBeanServer, - String name, - MetricFilter filter, - TimeUnit rateUnit, - TimeUnit durationUnit, - ObjectNameFactory objectNameFactory, - String tag) { - this.mBeanServer = mBeanServer; - this.name = name; - this.filter = filter; - this.rateUnit = rateUnit; - this.durationUnit = durationUnit; - this.registered = new ConcurrentHashMap<>(); - this.objectNameFactory = objectNameFactory; - this.tag = tag; - this.exp = Query.eq(Query.attr(INSTANCE_TAG), Query.value(tag)); - } - - private void registerMBean(Object mBean, ObjectName objectName) - throws InstanceAlreadyExistsException, JMException { - // remove previous bean if exists - if (mBeanServer.isRegistered(objectName)) { - if (log.isDebugEnabled()) { - Set<ObjectInstance> objects = mBeanServer.queryMBeans(objectName, null); - if (log.isDebugEnabled()) { - log.debug( - "## removing existing {} bean(s) for {}, current tag={}:", - objects.size(), - objectName.getCanonicalName(), - tag); - } - for (ObjectInstance inst : objects) { - if (log.isDebugEnabled()) { - log.debug( - "## - tag={}", mBeanServer.getAttribute(inst.getObjectName(), INSTANCE_TAG)); - } - } - } - mBeanServer.unregisterMBean(objectName); - } - ObjectInstance objectInstance = mBeanServer.registerMBean(mBean, objectName); - if (objectInstance != null) { - // the websphere mbeanserver rewrites the objectname to include - // cell, node & server info - // make sure we capture the new objectName for unregistration - registered.put(objectName, objectInstance.getObjectName()); - } else { - registered.put(objectName, objectName); - } - if (log.isDebugEnabled()) { - log.debug( - "## registered {}, tag={}", objectInstance.getObjectName().getCanonicalName(), tag); - } - } - - private void unregisterMBean(ObjectName originalObjectName) - throws InstanceNotFoundException, MBeanRegistrationException { - ObjectName objectName = registered.remove(originalObjectName); - if (objectName == null) { - objectName = originalObjectName; - } - Set<ObjectInstance> objects = mBeanServer.queryMBeans(objectName, exp); - for (ObjectInstance o : objects) { - if (log.isDebugEnabled()) { - log.debug("## Unregistered {}, tag={}", o.getObjectName().getCanonicalName(), tag); - } - mBeanServer.unregisterMBean(o.getObjectName()); - } - } - - @Override - public void onGaugeAdded(String name, Gauge<?> gauge) { - try { - if (filter.matches(name, gauge)) { - final ObjectName objectName = createName("gauges", name); - if (gauge instanceof SolrMetricManager.GaugeWrapper - && ((SolrMetricManager.GaugeWrapper<?>) gauge).getGauge() instanceof MetricsMap mm) { - mm.setAttribute(new Attribute(INSTANCE_TAG, tag)); - // don't wrap it in a JmxGauge, it already supports all necessary JMX attributes - registerMBean(mm, objectName); - } else { - registerMBean(new JmxGauge(gauge, objectName, tag), objectName); - } - } - } catch (InstanceAlreadyExistsException e) { - log.debug("Unable to register gauge", e); - } catch (JMException e) { - log.warn("Unable to register gauge", e); - } - } - - @Override - public void onGaugeRemoved(String name) { - try { - final ObjectName objectName = createName("gauges", name); - unregisterMBean(objectName); - } catch (InstanceNotFoundException e) { - log.debug("Unable to unregister gauge", e); - } catch (MBeanRegistrationException e) { - log.warn("Unable to unregister gauge", e); - } - } - - @Override - public void onCounterAdded(String name, Counter counter) { - try { - if (filter.matches(name, counter)) { - final ObjectName objectName = createName("counters", name); - registerMBean(new JmxCounter(counter, objectName, tag), objectName); - } - } catch (InstanceAlreadyExistsException e) { - log.debug("Unable to register counter", e); - } catch (JMException e) { - log.warn("Unable to register counter", e); - } - } - - @Override - public void onCounterRemoved(String name) { - try { - final ObjectName objectName = createName("counters", name); - unregisterMBean(objectName); - } catch (InstanceNotFoundException e) { - log.debug("Unable to unregister counter", e); - } catch (MBeanRegistrationException e) { - log.warn("Unable to unregister counter", e); - } - } - - @Override - public void onHistogramAdded(String name, Histogram histogram) { - try { - if (filter.matches(name, histogram)) { - final ObjectName objectName = createName("histograms", name); - registerMBean(new JmxHistogram(histogram, objectName, tag), objectName); - } - } catch (InstanceAlreadyExistsException e) { - log.debug("Unable to register histogram", e); - } catch (JMException e) { - log.warn("Unable to register histogram", e); - } - } - - @Override - public void onHistogramRemoved(String name) { - try { - final ObjectName objectName = createName("histograms", name); - unregisterMBean(objectName); - } catch (InstanceNotFoundException e) { - log.debug("Unable to unregister histogram", e); - } catch (MBeanRegistrationException e) { - log.warn("Unable to unregister histogram", e); - } - } - - @Override - public void onMeterAdded(String name, Meter meter) { - try { - if (filter.matches(name, meter)) { - final ObjectName objectName = createName("meters", name); - registerMBean(new JmxMeter(meter, objectName, rateUnit, tag), objectName); - } - } catch (InstanceAlreadyExistsException e) { - log.debug("Unable to register meter", e); - } catch (JMException e) { - log.warn("Unable to register meter", e); - } - } - - @Override - public void onMeterRemoved(String name) { - try { - final ObjectName objectName = createName("meters", name); - unregisterMBean(objectName); - } catch (InstanceNotFoundException e) { - log.debug("Unable to unregister meter", e); - } catch (MBeanRegistrationException e) { - log.warn("Unable to unregister meter", e); - } - } - - @Override - public void onTimerAdded(String name, Timer timer) { - try { - if (filter.matches(name, timer)) { - final ObjectName objectName = createName("timers", name); - registerMBean(new JmxTimer(timer, objectName, rateUnit, durationUnit, tag), objectName); - } - } catch (InstanceAlreadyExistsException e) { - log.debug("Unable to register timer", e); - } catch (JMException e) { - log.warn("Unable to register timer", e); - } - } - - @Override - public void onTimerRemoved(String name) { - try { - final ObjectName objectName = createName("timers", name); - unregisterMBean(objectName); - } catch (InstanceNotFoundException e) { - log.debug("Unable to unregister timer", e); - } catch (MBeanRegistrationException e) { - log.warn("Unable to unregister timer", e); - } - } - - private ObjectName createName(String type, String name) { - return objectNameFactory.createName(type, this.name, name); - } - - void unregisterAll() { - for (ObjectName name : registered.keySet()) { - try { - unregisterMBean(name); - } catch (InstanceNotFoundException e) { - log.debug("Unable to unregister metric", e); - } catch (MBeanRegistrationException e) { - log.warn("Unable to unregister metric", e); - } - } - registered.clear(); - } - } - - private final MetricRegistry registry; - private final JmxListener listener; - - private JmxMetricsReporter( - MBeanServer mBeanServer, - String domain, - MetricRegistry registry, - MetricFilter filter, - TimeUnit rateUnit, - TimeUnit durationUnit, - ObjectNameFactory objectNameFactory, - String tag) { - this.registry = registry; - this.listener = - new JmxListener( - mBeanServer, domain, filter, rateUnit, durationUnit, objectNameFactory, tag); - } - - public void start() { - registry.addListener(listener); - // process existing metrics - Map<String, Metric> metrics = new HashMap<>(registry.getMetrics()); - metrics.forEach( - (k, v) -> { - if (v instanceof Counter) { - listener.onCounterAdded(k, (Counter) v); - } else if (v instanceof Meter) { - listener.onMeterAdded(k, (Meter) v); - } else if (v instanceof Histogram) { - listener.onHistogramAdded(k, (Histogram) v); - } else if (v instanceof Timer) { - listener.onTimerAdded(k, (Timer) v); - } else if (v instanceof Gauge) { - listener.onGaugeAdded(k, (Gauge<?>) v); - } else { - log.warn("Unknown metric type {} for metric '{}', ignoring", v.getClass().getName(), k); - } - }); - } - - @Override - public void close() { - registry.removeListener(listener); - listener.unregisterAll(); - } -} diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/JmxObjectNameFactory.java b/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/JmxObjectNameFactory.java deleted file mode 100644 index 2b19344f569..00000000000 --- a/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/JmxObjectNameFactory.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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.jmx; - -import com.codahale.metrics.jmx.ObjectNameFactory; -import java.util.Arrays; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import org.apache.solr.metrics.SolrMetricInfo; - -/** Factory to create MBean names for a given metric. */ -public class JmxObjectNameFactory implements ObjectNameFactory { - - private final String domain; - private final String[] subdomains; - private final String reporterName; - private final String[] props; - - /** - * Create ObjectName factory. - * - * @param reporterName name of the reporter - * @param domain JMX domain name - * @param additionalProperties additional properties as key, value pairs. - */ - public JmxObjectNameFactory(String reporterName, String domain, String... additionalProperties) { - this.reporterName = reporterName.replace(":", "_"); - this.domain = domain; - this.subdomains = domain.replace(":", "_").split("\\."); - if (additionalProperties != null && (additionalProperties.length % 2) != 0) { - throw new IllegalArgumentException( - "additionalProperties length must be even: " + Arrays.toString(additionalProperties)); - } - this.props = additionalProperties; - } - - /** Return current domain. */ - public String getDomain() { - return domain; - } - - /** Return current reporterName. */ - public String getReporterName() { - return reporterName; - } - - /** - * Create a hierarchical name. - * - * @param type metric class, eg. "counters", may be null for non-metric MBeans - * @param currentDomain JMX domain - * @param name object name - */ - @Override - public ObjectName createName(String type, String currentDomain, String name) { - SolrMetricInfo metricInfo = SolrMetricInfo.of(name); - String safeName = metricInfo != null ? metricInfo.name : name; - safeName = safeName.replace(":", "_"); - // It turns out that ObjectName(String) mostly preserves key ordering - // as specified in the constructor (except for the 'type' key that ends - // up at top level) - unlike ObjectName(String, Map) constructor - // that seems to have a mind of its own... - StringBuilder sb = new StringBuilder(); - if (domain.equals(currentDomain)) { - if (subdomains != null && subdomains.length > 1) { - // use only first segment as domain - sb.append(subdomains[0]); - sb.append(':'); - // use remaining segments as properties - for (int i = 1; i < subdomains.length; i++) { - if (i > 1) { - sb.append(','); - } - sb.append("dom"); - sb.append(String.valueOf(i)); - sb.append('='); - sb.append(subdomains[i]); - } - sb.append(','); // separate from other properties - } else { - sb.append(currentDomain.replace(":", "_")); - sb.append(':'); - } - } else { - sb.append(currentDomain); - sb.append(':'); - } - if (props != null && props.length > 0) { - boolean added = false; - for (int i = 0; i < props.length; i += 2) { - if (props[i] == null || props[i].isEmpty()) { - continue; - } - if (props[i + 1] == null || props[i + 1].isEmpty()) { - continue; - } - sb.append(','); - sb.append(props[i]); - sb.append('='); - sb.append(props[i + 1]); - added = true; - } - if (added) { - sb.append(','); - } - } - if (metricInfo != null) { - sb.append("category="); - sb.append(metricInfo.category.toString()); - if (metricInfo.scope != null) { - sb.append(",scope="); - sb.append(metricInfo.scope); - } - // we could also split by type, but don't call it 'type' :) - // if (type != null) { - // sb.append(",class="); - // sb.append(type); - // } - sb.append(",name="); - sb.append(safeName); - } else { - // make dotted names into hierarchies - String[] path = safeName.split("\\."); - for (int i = 0; i < path.length - 1; i++) { - if (i > 0) { - sb.append(','); - } - sb.append("name"); - sb.append(String.valueOf(i)); - sb.append('='); - sb.append(path[i]); - } - if (path.length > 1) { - sb.append(','); - } - // split by type - // if (type != null) { - // sb.append("class="); - // sb.append(type); - // } - sb.append("name="); - sb.append(path[path.length - 1]); - } - - ObjectName objectName; - - try { - objectName = new ObjectName(sb.toString()); - } catch (MalformedObjectNameException e) { - throw new RuntimeException(sb.toString(), e); - } - - return objectName; - } -} diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/package-info.java b/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/package-info.java deleted file mode 100644 index 2cdd1d68f8d..00000000000 --- a/solr/core/src/java/org/apache/solr/metrics/reporters/jmx/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -/** - * This package contains components that support {@link - * org.apache.solr.metrics.reporters.SolrJmxReporter}. - */ -package org.apache.solr.metrics.reporters.jmx; diff --git a/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java b/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java deleted file mode 100644 index f162fe31dce..00000000000 --- a/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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.core; - -import com.codahale.metrics.MetricRegistry; -import java.lang.invoke.MethodHandles; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import javax.management.AttributeNotFoundException; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.SolrMetricReporter; -import org.apache.solr.metrics.reporters.SolrJmxReporter; -import org.apache.solr.metrics.reporters.jmx.JmxMetricsReporter; -import org.apache.solr.metrics.reporters.jmx.JmxObjectNameFactory; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Test for JMX Integration - * - * @since solr 1.3 - */ -public class TestJmxIntegration extends SolrTestCaseJ4 { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private static MBeanServer mbeanServer = null; - private static MBeanServer newMbeanServer = null; - private static JmxObjectNameFactory nameFactory = null; - private static String registryName = null; - - @BeforeClass - public static void beforeClass() throws Exception { - // Make sure that at least one MBeanServer is available - // prior to initializing the core - // - // (test configs are set up to use existing server if any, - // otherwise skip JMX) - newMbeanServer = MBeanServerFactory.createMBeanServer(); - - initCore("solrconfig.xml", "schema.xml"); - - // we should be able to see that the core has JmxIntegration enabled - registryName = h.getCore().getCoreMetricManager().getRegistryName(); - SolrMetricManager manager = h.getCoreContainer().getMetricManager(); - Map<String, SolrMetricReporter> reporters = manager.getReporters(registryName); - assertEquals(1, reporters.size()); - SolrMetricReporter reporter = reporters.values().iterator().next(); - assertTrue(reporter instanceof SolrJmxReporter); - SolrJmxReporter jmx = (SolrJmxReporter) reporter; - assertTrue("JMX not enabled", jmx.isActive()); - // and we should be able to see that the reporter - // refers to the JMX server we started - - mbeanServer = jmx.getMBeanServer(); - - assertNotNull("No JMX server found in the reporter", mbeanServer); - - // NOTE: we can't guarantee that "mbeanServer == platformServer" - // the JVM may have multiple MBean servers running when the test started - // and the contract of not specifying one when configuring solr.xml without - // agentId or serviceUrl is that it will use whatever the "first" MBean server - // returned by the JVM is. - - nameFactory = new JmxObjectNameFactory("default", registryName); - } - - @AfterClass - public static void afterClass() { - if (newMbeanServer != null) { - MBeanServerFactory.releaseMBeanServer(newMbeanServer); - } - mbeanServer = null; - newMbeanServer = null; - } - - @Before - public void resetIndex() { - clearIndex(); - assertU("commit", commit()); - } - - @Test - public void testJmxRegistration() throws Exception { - assertTrue("No MBeans found in server", mbeanServer.getMBeanCount() > 0); - - Set<ObjectInstance> objects = mbeanServer.queryMBeans(null, null); - assertFalse("No objects found in mbean server", objects.isEmpty()); - int numDynamicMbeans = 0; - for (ObjectInstance o : objects) { - ObjectName name = o.getObjectName(); - assertNotNull("Null name on: " + o, name); - MBeanInfo mbeanInfo = mbeanServer.getMBeanInfo(name); - if (name.getDomain().equals("solr")) { - numDynamicMbeans++; - MBeanAttributeInfo[] attrs = mbeanInfo.getAttributes(); - if (name.getKeyProperty("name") - .equals("fetcher")) { // no attributes without active replication - continue; - } - assertTrue( - "No Attributes found for mbean: " + o.getObjectName() + ", " + mbeanInfo, - 0 < attrs.length); - for (MBeanAttributeInfo attr : attrs) { - // ensure every advertised attribute is gettable - try { - Object trash = mbeanServer.getAttribute(o.getObjectName(), attr.getName()); - } catch (javax.management.AttributeNotFoundException e) { - throw new RuntimeException( - "Unable to fetch attribute for " + o.getObjectName() + ": " + attr.getName(), e); - } - } - } - } - assertTrue("No MBeans found", 0 < numDynamicMbeans); - } - - @Test - public void testJmxUpdate() throws Exception { - - SolrInfoBean bean = null; - // wait until searcher is registered - for (int i = 0; i < 100; i++) { - bean = h.getCore().getInfoRegistry().get("searcher"); - if (bean != null) break; - Thread.sleep(250); - } - if (bean == null) throw new RuntimeException("searcher was never registered"); - ObjectName searcher = nameFactory.createName("gauge", registryName, "SEARCHER.searcher.*"); - - if (log.isInfoEnabled()) { - log.info("Mbeans in server: {}", mbeanServer.queryNames(null, null)); - } - - assertFalse( - "No mbean found for SolrIndexSearcher", mbeanServer.queryMBeans(searcher, null).isEmpty()); - - ObjectName name = nameFactory.createName("gauge", registryName, "SEARCHER.searcher.numDocs"); - int oldNumDocs = (Integer) mbeanServer.getAttribute(name, "Value"); - assertU(adoc("id", "1")); - assertU("commit", commit()); - int numDocs = (Integer) mbeanServer.getAttribute(name, "Value"); - assertTrue("New numDocs is same as old numDocs as reported by JMX", numDocs > oldNumDocs); - } - - @Test - @SuppressWarnings({"try"}) - public void testJmxOnCoreReload() throws Exception { - // make sure searcher beans are registered - assertQ(req("q", "*:*"), "//result[@numFound='0']"); - - SolrMetricManager mgr = h.getCoreContainer().getMetricManager(); - String registryName = h.getCore().getCoreMetricManager().getRegistryName(); - String coreName = h.getCore().getName(); - String coreHashCode = Integer.toHexString(h.getCore().hashCode()); - Map<String, SolrMetricReporter> reporters = mgr.getReporters(registryName); - // take first JMX reporter - SolrJmxReporter reporter = null; - for (Map.Entry<String, SolrMetricReporter> e : reporters.entrySet()) { - if (e.getKey().endsWith(coreHashCode) && e.getValue() instanceof SolrJmxReporter) { - reporter = (SolrJmxReporter) e.getValue(); - break; - } - } - assertNotNull("could not find JMX reporter for " + registryName, reporter); - String tag = reporter.getInstanceTag(); - - Set<ObjectInstance> oldBeans = mbeanServer.queryMBeans(null, null); - int oldNumberOfObjects = 0; - for (ObjectInstance bean : oldBeans) { - try { - if (tag.equals( - mbeanServer.getAttribute(bean.getObjectName(), JmxMetricsReporter.INSTANCE_TAG))) { - oldNumberOfObjects++; - } - } catch (AttributeNotFoundException e) { - // expected - } - } - - int totalCoreMetrics = mgr.registry(registryName).getMetrics().size(); - log.info( - "Before Reload: size of all core metrics: {} MBeans: {}", - totalCoreMetrics, - oldNumberOfObjects); - assertEquals( - "Number of registered MBeans is not the same as the number of core metrics", - totalCoreMetrics, - oldNumberOfObjects); - h.getCoreContainer().reload(coreName); - assertQ(req("q", "*:*"), "//result[@numFound='0']"); - - reporters = mgr.getReporters(registryName); - coreHashCode = Integer.toHexString(h.getCore().hashCode()); - // take first JMX reporter - reporter = null; - for (Map.Entry<String, SolrMetricReporter> e : reporters.entrySet()) { - if (e.getKey().endsWith(coreHashCode) && e.getValue() instanceof SolrJmxReporter) { - reporter = (SolrJmxReporter) e.getValue(); - break; - } - } - assertNotNull("could not find JMX reporter for " + registryName, reporter); - tag = reporter.getInstanceTag(); - - Set<ObjectInstance> newBeans = mbeanServer.queryMBeans(null, null); - int newNumberOfObjects = 0; - Set<String> metricNames = new TreeSet<>(); - Set<String> beanNames = new TreeSet<>(); - try (SolrCore core = h.getCoreContainer().getCore(coreName)) { - MetricRegistry registry = mgr.registry(registryName); - metricNames.addAll(registry.getNames()); - totalCoreMetrics = registry.getMetrics().size(); - for (ObjectInstance bean : newBeans) { - try { - if (tag.equals( - mbeanServer.getAttribute(bean.getObjectName(), JmxMetricsReporter.INSTANCE_TAG))) { - String[] name = bean.getObjectName().toString().substring(32).split(","); - StringBuilder sb = new StringBuilder(); - for (String n : name) { - if (sb.length() > 0) { - sb.append("."); - } - sb.append(n.split("=")[1]); - } - beanNames.add(sb.toString()); - newNumberOfObjects++; - } - } catch (AttributeNotFoundException e) { - // expected - } - } - } - - log.info( - "After Reload: size of all core metrics: {} MBeans: {}", - totalCoreMetrics, - newNumberOfObjects); - if (totalCoreMetrics != newNumberOfObjects) { - Set<String> errors = new TreeSet<>(beanNames); - errors.removeAll(metricNames); - log.error("Unexpected bean names: {}", errors); - errors = new TreeSet<>(metricNames); - errors.removeAll(beanNames); - log.error("Unexpected metric names: {}", errors); - fail( - "Number of registered MBeans is not the same as the number of core metrics: " - + totalCoreMetrics - + " != " - + newNumberOfObjects); - } - } -} diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java index 2c8f51aec6d..d5701d15111 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java @@ -47,8 +47,6 @@ import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.util.NamedList; import org.apache.solr.core.PluginInfo; import org.apache.solr.core.SolrInfoBean; -import org.apache.solr.core.SolrResourceLoader; -import org.apache.solr.metrics.reporters.MockMetricReporter; import org.junit.Before; import org.junit.Test; @@ -219,74 +217,6 @@ public class SolrMetricManagerTest extends SolrTestCaseJ4 { assertEquals("solr.core." + name + ".collection1.shard1.replica1", result); } - @Test - public void testReporters() throws Exception { - - try (SolrResourceLoader loader = new SolrResourceLoader(createTempDir())) { - SolrMetricManager metricManager = new SolrMetricManager(); - - PluginInfo[] plugins = - new PluginInfo[] { - createPluginInfo("universal_foo", null, null), - createPluginInfo("multigroup_foo", "jvm, node, core", null), - createPluginInfo("multiregistry_foo", null, "solr.node, solr.core.collection1"), - createPluginInfo("specific_foo", null, "solr.core.collection1"), - createPluginInfo("node_foo", "node", null), - createPluginInfo("core_foo", "core", null) - }; - String tag = "xyz"; - metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.node); - Map<String, SolrMetricReporter> reporters = - metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)); - - assertEquals(4, reporters.size()); - assertTrue(reporters.containsKey("universal_foo@" + tag)); - assertTrue(reporters.containsKey("multigroup_foo@" + tag)); - assertTrue(reporters.containsKey("node_foo@" + tag)); - assertTrue(reporters.containsKey("multiregistry_foo@" + tag)); - - metricManager.loadReporters( - plugins, loader, null, null, tag, SolrInfoBean.Group.core, "collection1"); - reporters = - metricManager.getReporters( - SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, "collection1")); - - assertEquals(5, reporters.size()); - assertTrue(reporters.containsKey("universal_foo@" + tag)); - assertTrue(reporters.containsKey("multigroup_foo@" + tag)); - assertTrue(reporters.containsKey("specific_foo@" + tag)); - assertTrue(reporters.containsKey("core_foo@" + tag)); - assertTrue(reporters.containsKey("multiregistry_foo@" + tag)); - - metricManager.loadReporters(plugins, loader, null, null, tag, SolrInfoBean.Group.jvm); - reporters = - metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm)); - - assertEquals(2, reporters.size()); - assertTrue(reporters.containsKey("universal_foo@" + tag)); - assertTrue(reporters.containsKey("multigroup_foo@" + tag)); - - metricManager.removeRegistry("solr.jvm"); - reporters = - metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm)); - - assertEquals(0, reporters.size()); - - metricManager.removeRegistry("solr.node"); - reporters = - metricManager.getReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)); - - assertEquals(0, reporters.size()); - - metricManager.removeRegistry("solr.core.collection1"); - reporters = - metricManager.getReporters( - SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, "collection1")); - - assertEquals(0, reporters.size()); - } - } - @Test public void testDefaultCloudReporterPeriodUnchanged() { assertEquals(60, SolrMetricManager.DEFAULT_CLOUD_REPORTER_PERIOD); @@ -295,7 +225,6 @@ public class SolrMetricManagerTest extends SolrTestCaseJ4 { private PluginInfo createPluginInfo(String name, String group, String registry) { Map<String, String> attrs = new HashMap<>(); attrs.put("name", name); - attrs.put("class", MockMetricReporter.class.getName()); if (group != null) { attrs.put("group", group); } diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java index e6e7e7c949a..b62f56745a8 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java @@ -20,17 +20,14 @@ package org.apache.solr.metrics; import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.Timer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; import org.apache.http.client.HttpClient; import org.apache.lucene.tests.util.LuceneTestCase; -import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.impl.HttpClientUtil; @@ -43,7 +40,6 @@ import org.apache.solr.core.PluginInfo; import org.apache.solr.core.SolrInfoBean; import org.apache.solr.core.SolrXmlConfig; import org.apache.solr.embedded.JettySolrRunner; -import org.apache.solr.metrics.reporters.MockMetricReporter; import org.apache.solr.util.JmxUtil; import org.apache.solr.util.TestHarness; import org.hamcrest.number.OrderingComparison; @@ -132,14 +128,6 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 { assertTrue( "Reporter '" + MULTIREGISTRY + "' missing in solr.node", reporters.containsKey(MULTIREGISTRY)); - SolrMetricReporter reporter = reporters.get(REPORTER_NAMES[0]); - assertTrue( - "Reporter " + reporter + " is not an instance of " + MockMetricReporter.class.getName(), - reporter instanceof MockMetricReporter); - reporter = reporters.get(UNIVERSAL); - assertTrue( - "Reporter " + reporter + " is not an instance of " + MockMetricReporter.class.getName(), - reporter instanceof MockMetricReporter); } @After @@ -149,62 +137,10 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 { } SolrCoreMetricManager coreMetricManager = h.getCore().getCoreMetricManager(); - Map<String, SolrMetricReporter> reporters = - metricManager.getReporters(coreMetricManager.getRegistryName()); - Gauge<?> gauge = (Gauge<?>) coreMetricManager.getRegistry().getMetrics().get("CORE.indexDir"); assertNotNull(gauge.getValue()); deleteCore(); // closes TestHarness which closes CoreContainer which closes SolrCore assertEquals(metricManager.nullString(), gauge.getValue()); - - for (String reporterName : RENAMED_REPORTERS) { - SolrMetricReporter reporter = reporters.get(reporterName + "@" + tag); - MockMetricReporter mockReporter = (MockMetricReporter) reporter; - assertTrue( - "Reporter " + reporterName + " was not closed: " + mockReporter, mockReporter.didClose); - } - } - - @Test - public void testConfigureReporter() throws Exception { - Random random = random(); - - String metricName = - SolrMetricManager.mkName(METRIC_NAME, HANDLER_CATEGORY.toString(), HANDLER_NAME); - SolrCoreMetricManager coreMetricManager = h.getCore().getCoreMetricManager(); - Timer timer = metricManager.timer(null, coreMetricManager.getRegistryName(), metricName); - - long initialCount = timer.getCount(); - - int iterations = TestUtil.nextInt(random, 0, MAX_ITERATIONS); - for (int i = 0; i < iterations; ++i) { - h.query(req("*")); - } - - long finalCount = timer.getCount(); - assertEquals("metric counter incorrect", iterations, finalCount - initialCount); - Map<String, SolrMetricReporter> reporters = - metricManager.getReporters(coreMetricManager.getRegistryName()); - assertEquals(RENAMED_REPORTERS.length + jmxReporter, reporters.size()); - - // SPECIFIC and MULTIREGISTRY were skipped because they were - // specific to collection1 - for (String reporterName : RENAMED_REPORTERS) { - SolrMetricReporter reporter = reporters.get(reporterName + "@" + tag); - assertNotNull("Reporter " + reporterName + " was not found.", reporter); - assertTrue(reporter instanceof MockMetricReporter); - - MockMetricReporter mockReporter = (MockMetricReporter) reporter; - assertTrue( - "Reporter " + reporterName + " was not initialized: " + mockReporter, - mockReporter.didInit); - assertTrue( - "Reporter " + reporterName + " was not validated: " + mockReporter, - mockReporter.didValidate); - assertFalse( - "Reporter " + reporterName + " was incorrectly closed: " + mockReporter, - mockReporter.didClose); - } } @Test diff --git a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrGraphiteReporterTest.java b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrGraphiteReporterTest.java deleted file mode 100644 index da26b845ef0..00000000000 --- a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrGraphiteReporterTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.ServerSocket; -import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.core.CoreContainer; -import org.apache.solr.core.NodeConfig; -import org.apache.solr.core.SolrXmlConfig; -import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.SolrMetricReporter; -import org.apache.solr.util.JmxUtil; -import org.apache.solr.util.TestHarness; -import org.junit.Test; - -/** */ -public class SolrGraphiteReporterTest extends SolrTestCaseJ4 { - - @Test - public void testReporter() throws Exception { - int jmxReporter = JmxUtil.findFirstMBeanServer() != null ? 1 : 0; - Path home = TEST_HOME(); - // define these properties, they are used in solrconfig.xml - System.setProperty("solr.test.sys.prop1", "propone"); - System.setProperty("solr.test.sys.prop2", "proptwo"); - - MockGraphite mock = new MockGraphite(); - try { - mock.start(); - Thread.sleep(1000); - // define the port where MockGraphite is running - System.setProperty("mock-graphite-port", String.valueOf(mock.port)); - String solrXml = - Files.readString(home.resolve("solr-graphitereporter.xml"), StandardCharsets.UTF_8); - NodeConfig cfg = SolrXmlConfig.fromString(home, solrXml); - CoreContainer cc = - createCoreContainer( - cfg, - new TestHarness.TestCoresLocator( - DEFAULT_TEST_CORENAME, - initAndGetDataDir().toString(), - "solrconfig.xml", - "schema.xml")); - - h.coreName = DEFAULT_TEST_CORENAME; - SolrMetricManager metricManager = cc.getMetricManager(); - Map<String, SolrMetricReporter> reporters = metricManager.getReporters("solr.node"); - assertEquals(1 + jmxReporter, reporters.size()); - SolrMetricReporter reporter = reporters.get("test"); - assertNotNull(reporter); - assertTrue(reporter instanceof SolrGraphiteReporter); - Thread.sleep(5000); - assertTrue(mock.lines.size() >= 3); - String[] frozenLines = mock.lines.toArray(new String[0]); - for (String line : frozenLines) { - assertTrue(line, line.startsWith("test.solr.node.CONTAINER.cores.")); - } - } finally { - mock.close(); - } - } - - private static class MockGraphite extends Thread { - private List<String> lines = new ArrayList<>(); - private ServerSocket server = null; - private int port; - private boolean stop; - - MockGraphite() throws Exception { - server = new ServerSocket(0); - port = server.getLocalPort(); - stop = false; - } - - @Override - public void run() { - while (!stop) { - try { - Socket s = server.accept(); - BufferedReader br = - new BufferedReader(new InputStreamReader(s.getInputStream(), StandardCharsets.UTF_8)); - String line; - while ((line = br.readLine()) != null) { - lines.add(line); - } - } catch (Exception e) { - stop = true; - } - } - } - - public void close() throws Exception { - stop = true; - if (server != null) { - server.close(); - } - } - } -} diff --git a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterCloudTest.java b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterCloudTest.java deleted file mode 100644 index 00a201c2beb..00000000000 --- a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterCloudTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 java.lang.invoke.MethodHandles; -import java.lang.management.ManagementFactory; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.management.MBeanServer; -import javax.management.ObjectInstance; -import javax.management.Query; -import javax.management.QueryExp; -import org.apache.solr.client.solrj.impl.CloudSolrClient; -import org.apache.solr.client.solrj.request.CollectionAdminRequest; -import org.apache.solr.cloud.SolrCloudTestCase; -import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.params.CommonParams; -import org.apache.solr.embedded.JettySolrRunner; -import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.SolrMetricReporter; -import org.apache.solr.metrics.reporters.jmx.JmxMetricsReporter; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** */ -public class SolrJmxReporterCloudTest extends SolrCloudTestCase { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private static MBeanServer mBeanServer; - private static String COLLECTION = SolrJmxReporterCloudTest.class.getSimpleName() + "_collection"; - - @BeforeClass - public static void setupCluster() throws Exception { - // make sure there's an MBeanServer - mBeanServer = ManagementFactory.getPlatformMBeanServer(); - configureCluster(1).addConfig("conf", configset("cloud-minimal")).configure(); - CollectionAdminRequest.createCollection(COLLECTION, "conf", 2, 1) - .process(cluster.getSolrClient()); - } - - @AfterClass - public static void releaseMBeanServer() { - mBeanServer = null; - } - - @Test - public void testJmxReporter() throws Exception { - CollectionAdminRequest.reloadCollection(COLLECTION).processAndWait(cluster.getSolrClient(), 60); - CloudSolrClient solrClient = cluster.getSolrClient(); - // index some docs - for (int i = 0; i < 100; i++) { - SolrInputDocument doc = new SolrInputDocument(); - doc.addField("id", "id-" + i); - solrClient.add(COLLECTION, doc); - } - solrClient.commit(COLLECTION); - // make sure searcher is present - solrClient.query(COLLECTION, params(CommonParams.Q, "*:*")); - - for (JettySolrRunner runner : cluster.getJettySolrRunners()) { - SolrMetricManager manager = runner.getCoreContainer().getMetricManager(); - for (String registry : manager.registryNames()) { - Map<String, SolrMetricReporter> reporters = manager.getReporters(registry); - long jmxReporters = - reporters.entrySet().stream() - .filter(e -> e.getValue() instanceof SolrJmxReporter) - .count(); - reporters.forEach( - (k, v) -> { - if (!(v instanceof SolrJmxReporter)) { - return; - } - if (!((SolrJmxReporter) v).getDomain().startsWith("solr.core")) { - return; - } - if (!((SolrJmxReporter) v).isActive()) { - return; - } - QueryExp exp = - Query.eq( - Query.attr(JmxMetricsReporter.INSTANCE_TAG), - Query.value(Integer.toHexString(v.hashCode()))); - Set<ObjectInstance> beans = mBeanServer.queryMBeans(null, exp); - if (((SolrJmxReporter) v).isStarted() && beans.isEmpty() && jmxReporters < 2) { - if (log.isInfoEnabled()) { - log.info("DocCollection: {}", getCollectionState(COLLECTION)); - } - fail( - "JMX reporter " - + k - + " for registry " - + registry - + " failed to register any beans!"); - } else { - Set<String> categories = new HashSet<>(); - beans.forEach( - bean -> { - String cat = bean.getObjectName().getKeyProperty("category"); - if (cat != null) { - categories.add(cat); - } - }); - log.info("Registered categories: {}", categories); - assertTrue("Too few categories: " + categories, categories.size() > 5); - } - }); - } - } - } -} diff --git a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterTest.java b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterTest.java deleted file mode 100644 index 25e433b934e..00000000000 --- a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrJmxReporterTest.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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 com.codahale.metrics.Counter; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import org.apache.lucene.tests.util.LuceneTestCase; -import org.apache.lucene.tests.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; - -// NOCOMMIT: All tests failing because of migration for some core metrics missing from JMX. See -// comment on SolrJmxReporter for what we could do. [email protected](bugUrl = "https://issues.apache.org/jira/browse/SOLR-17458") -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() { - TEST_MBEAN_SERVER = MBeanServerFactory.createMBeanServer(); - PREFIX = getSimpleClassName() + "-"; - } - - @AfterClass - public static void shutdown() { - 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 clean up - } - - 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() { - 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(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(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()); - } - - @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(); - final AtomicBoolean running = new AtomicBoolean(true); - Thread testThread = - new Thread( - () -> { - while (running.get()) { - 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); - } - } - }, - "TestMBeanThread"); - try { - testThread.start(); - // This should be enough time for the - Thread.sleep(500); - } finally { - running.set(false); - testThread.join(); - } - - 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()); - } - - @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); - assertNotEquals(root2, 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(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()); - } -} diff --git a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrSlf4jReporterTest.java b/solr/core/src/test/org/apache/solr/metrics/reporters/SolrSlf4jReporterTest.java deleted file mode 100644 index f76f4678dbf..00000000000 --- a/solr/core/src/test/org/apache/solr/metrics/reporters/SolrSlf4jReporterTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 java.lang.invoke.MethodHandles; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; -import org.apache.lucene.tests.util.LuceneTestCase; -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.common.SolrDocumentList; -import org.apache.solr.core.CoreContainer; -import org.apache.solr.core.NodeConfig; -import org.apache.solr.core.SolrXmlConfig; -import org.apache.solr.logging.LogWatcher; -import org.apache.solr.logging.LogWatcherConfig; -import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.SolrMetricReporter; -import org.apache.solr.util.TestHarness; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** */ -// NOCOMMIT: Need to see if we are still supporting this and if it is possible to wrap otel metrics -// into slf4j like dropwizard does. [email protected](bugUrl = "https://issues.apache.org/jira/browse/SOLR-17458") -public class SolrSlf4jReporterTest extends SolrTestCaseJ4 { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - @Test - public void testReporter() throws Exception { - ensureLoggingConfiguredAppropriately(); - Path home = TEST_HOME(); - // define these properties, they are used in solrconfig.xml - System.setProperty("solr.test.sys.prop1", "propone"); - System.setProperty("solr.test.sys.prop2", "proptwo"); - - String solrXml = - Files.readString(home.resolve("solr-slf4jreporter.xml"), StandardCharsets.UTF_8); - NodeConfig cfg = SolrXmlConfig.fromString(home, solrXml); - CoreContainer cc = - createCoreContainer( - cfg, - new TestHarness.TestCoresLocator( - DEFAULT_TEST_CORENAME, - initAndGetDataDir().toString(), - "solrconfig.xml", - "schema.xml")); - - h.coreName = DEFAULT_TEST_CORENAME; - SolrMetricManager metricManager = cc.getMetricManager(); - Map<String, SolrMetricReporter> reporters = metricManager.getReporters("solr.node"); - assertTrue(reporters.toString(), reporters.size() >= 2); - SolrMetricReporter reporter1 = reporters.get("test1"); - assertNotNull(reporter1); - assertTrue(reporter1 instanceof SolrSlf4jReporter); - SolrMetricReporter reporter2 = reporters.get("test2"); - assertNotNull(reporter2); - assertTrue(reporter2 instanceof SolrSlf4jReporter); - - LogWatcherConfig watcherCfg = new LogWatcherConfig(true, null, null, 100); - LogWatcher<?> watcher = LogWatcher.newRegisteredLogWatcher(watcherCfg, null); - watcher.setThreshold("INFO"); - - watcher.reset(); - int cnt = 20; - boolean active; - do { - Thread.sleep(1000); - cnt--; - active = - ((SolrSlf4jReporter) reporter1).isActive() && ((SolrSlf4jReporter) reporter2).isActive(); - } while (!active && cnt > 0); - if (!active) { - fail("One or more reporters didn't become active in 20 seconds"); - } - Thread.sleep(10000); - - SolrDocumentList history = watcher.getHistory(-1, null); - // dot-separated names are treated like class names and collapsed - // in regular log output, but here we get the full name - if (history.stream().filter(d -> "solr.node".equals(d.getFirstValue("logger"))).count() == 0) { - fail("No 'solr.node' logs in: " + history); - } - if (history.stream().filter(d -> "foobar".equals(d.getFirstValue("logger"))).count() == 0) { - fail("No 'foobar' logs in: " + history); - } - if (history.stream().filter(d -> "collection1".equals(d.getFirstValue("core"))).count() == 0) { - fail("No 'solr.core' or MDC context in logs: " + history); - } - } - - private static void ensureLoggingConfiguredAppropriately() { - if (!log.isInfoEnabled()) { - fail("Test requires that log-level is at-least INFO, but INFO is disabled"); - } - } -} diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc index 1821dadbf8e..5b3b74e53df 100644 --- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc +++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc @@ -112,7 +112,7 @@ If only one node is exposed to a client, and if the client uses the bin/solr exp === Modern NLP Models from Apache OpenNLP with Solr -Solr now lets you access models encoded in ONNX format, commonly sourced from HuggingFace. +Solr now lets you access models encoded in ONNX format, commonly sourced from HuggingFace. The DocumentCategorizerUpdateProcessorFactorythat lets you perform sentiment and other classification tasks on fields. It is available as part of the `analysis-extras` module. @@ -168,6 +168,7 @@ Nowadays, the HTTP request is available via internal APIs: `SolrQueryRequest.get * BlobHandler and the `.system` collection have been removed in favour of FileStore API. (SOLR-17851). +* JMX, SLF4J and Graphite metric reporters have been removed. Users should migrate to using OTLP or the /admin/metrics endpoint with external tools to get metrics to their preferred backend. === Security diff --git a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java index 2e18bf4c33b..300aa7c3185 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java +++ b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java @@ -34,13 +34,11 @@ import org.apache.solr.core.CorePropertiesLocator; import org.apache.solr.core.CoresLocator; import org.apache.solr.core.MetricsConfig; import org.apache.solr.core.NodeConfig; -import org.apache.solr.core.PluginInfo; import org.apache.solr.core.SolrConfig; import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrXmlConfig; import org.apache.solr.handler.UpdateRequestHandler; import org.apache.solr.logging.MDCSnapshot; -import org.apache.solr.metrics.reporters.SolrJmxReporter; import org.apache.solr.request.LocalSolrQueryRequest; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; @@ -195,15 +193,7 @@ public class TestHarness extends BaseTestHarness { .setZkHost(System.getProperty("zkHost")) .build(); - // universal default metric reporter - Map<String, Object> attributes = new HashMap<>(); - attributes.put("name", "default"); - attributes.put("class", SolrJmxReporter.class.getName()); - PluginInfo defaultPlugin = new PluginInfo("reporter", attributes); - MetricsConfig metricsConfig = - new MetricsConfig.MetricsConfigBuilder() - .setMetricReporterPlugins(new PluginInfo[] {defaultPlugin}) - .build(); + MetricsConfig metricsConfig = new MetricsConfig.MetricsConfigBuilder().build(); return new NodeConfig.NodeConfigBuilder("testNode", solrHome) .setUseSchemaCache(Boolean.getBoolean("shareSchema"))
