This is an automated email from the ASF dual-hosted git repository.
mlbiscoc pushed a commit to branch feature/SOLR-17458
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/feature/SOLR-17458 by this
push:
new fdf3038c3ff SOLR-17827: Remove JXM, SLF4J and Graphite reporters
(#3443)
fdf3038c3ff is described below
commit fdf3038c3ffc1f162925bd81d966f4bc2fba9e9e
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 | 2 +
.../src/java/org/apache/solr/util/TestHarness.java | 12 +-
16 files changed, 4 insertions(+), 2671 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 18fdcf8be57..20b16b53726 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.HttpClientUtil;
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;
@@ -742,8 +738,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(
@@ -773,36 +768,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 3ae2e6a0810..10704c19fe2 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.HttpSolrClient;
@@ -42,7 +39,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;
@@ -131,14 +127,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
@@ -148,62 +136,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 3c69e27773c..b64f200e2df 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
@@ -114,6 +114,8 @@ Users who that don't need to vary JAR access on a per-core
basis have several op
* The `addHttpRequestToContext` option in `solrconfig.xml` has been removed;
it's obsolete.
Nowadays, the HTTP request is available via internal APIs:
`SolrQueryRequest.getHttpSolrCall().getReq()`.
+* 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
* There is no longer a distinction between trusted and untrusted configSets;
all configSets are now considered trusted. To ensure security, Solr should be
properly protected using authentication and authorization mechanisms, allowing
only authorized users with administrative privileges to publish them.
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"))