You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2017/04/11 17:39:13 UTC

[7/7] lucene-solr:master: SOLR-9959: SolrInfoMBean-s category and hierarchy cleanup.

SOLR-9959: SolrInfoMBean-s category and hierarchy cleanup.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/e30cc70f
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/e30cc70f
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/e30cc70f

Branch: refs/heads/master
Commit: e30cc70fddcdd6fddb5eedf9f38e77fcb3f33bd1
Parents: e386ec9
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Tue Apr 11 19:22:23 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Tue Apr 11 19:22:23 2017 +0200

----------------------------------------------------------------------
 .../.idea/libraries/Solr_DIH_core_library.xml   |  10 +
 .../dataimporthandler/dataimporthandler.iml     |   3 +-
 lucene/tools/junit4/cached-timehints.txt        |   2 +-
 solr/CHANGES.txt                                |  17 +
 .../plugin/AnalyticsStatisticsCollector.java    |  31 +-
 .../handler/component/AnalyticsComponent.java   |  16 +-
 .../handler/dataimport/DataImportHandler.java   |  57 +--
 .../org/apache/solr/core/CoreContainer.java     |  65 +--
 .../org/apache/solr/core/DirectoryFactory.java  |   8 -
 .../apache/solr/core/HdfsDirectoryFactory.java  |  10 +-
 .../org/apache/solr/core/JmxMonitoredMap.java   | 478 -------------------
 .../java/org/apache/solr/core/PluginBag.java    |   4 +-
 .../java/org/apache/solr/core/SolrConfig.java   |  52 +-
 .../src/java/org/apache/solr/core/SolrCore.java | 171 +++----
 .../java/org/apache/solr/core/SolrInfoBean.java |  95 ++++
 .../org/apache/solr/core/SolrInfoMBean.java     |  76 ---
 .../apache/solr/core/SolrInfoMBeanWrapper.java  |  62 ---
 .../apache/solr/core/SolrResourceLoader.java    |  18 +-
 .../org/apache/solr/core/SolrXmlConfig.java     |  36 +-
 .../apache/solr/handler/AnalyzeEvaluator.java   |   3 -
 .../solr/handler/MoreLikeThisHandler.java       |  10 -
 .../apache/solr/handler/RealTimeGetHandler.java |   6 -
 .../apache/solr/handler/ReplicationHandler.java | 109 +++--
 .../apache/solr/handler/RequestHandlerBase.java |  62 +--
 .../apache/solr/handler/SolrConfigHandler.java  |   6 -
 .../solr/handler/StandardRequestHandler.java    |  11 -
 .../solr/handler/admin/CoreAdminHandler.java    |   2 +-
 .../solr/handler/admin/LukeRequestHandler.java  |  10 -
 .../handler/admin/MetricsCollectorHandler.java  |   2 +-
 .../solr/handler/admin/MetricsHandler.java      |  42 +-
 .../solr/handler/admin/PluginInfoHandler.java   |  27 +-
 .../handler/admin/SolrInfoMBeanHandler.java     |  32 +-
 .../solr/handler/admin/SystemInfoHandler.java   |  66 +--
 .../solr/handler/component/DebugComponent.java  |   8 +-
 .../solr/handler/component/ExpandComponent.java |  15 +-
 .../solr/handler/component/FacetComponent.java  |   8 +-
 .../handler/component/HighlightComponent.java   |   8 +-
 .../component/HttpShardHandlerFactory.java      |   6 +-
 .../component/MoreLikeThisComponent.java        |   8 +-
 .../solr/handler/component/QueryComponent.java  |   8 +-
 .../component/QueryElevationComponent.java      |  14 +-
 .../handler/component/RealTimeGetComponent.java |  10 +-
 .../solr/handler/component/SearchComponent.java |  31 +-
 .../handler/component/SpellCheckComponent.java  |   2 +-
 .../solr/handler/component/StatsComponent.java  |   2 +-
 .../handler/component/SuggestComponent.java     |  27 +-
 .../solr/highlight/DefaultSolrHighlighter.java  |  30 +-
 .../apache/solr/highlight/GapFragmenter.java    |   2 +-
 .../solr/highlight/HighlightingPluginBase.java  |  41 +-
 .../apache/solr/highlight/HtmlFormatter.java    |   2 +-
 .../apache/solr/highlight/RegexFragmenter.java  |   2 +-
 .../solr/highlight/SimpleFragListBuilder.java   |   2 +-
 .../solr/highlight/SingleFragListBuilder.java   |   2 +-
 .../solr/highlight/SolrBoundaryScanner.java     |   6 +-
 .../org/apache/solr/highlight/SolrEncoder.java  |   4 +-
 .../apache/solr/highlight/SolrFormatter.java    |   4 +-
 .../solr/highlight/SolrFragListBuilder.java     |   4 +-
 .../apache/solr/highlight/SolrFragmenter.java   |   4 +-
 .../solr/highlight/SolrFragmentsBuilder.java    |   6 +-
 .../solr/highlight/WeightedFragListBuilder.java |   2 +-
 .../solr/metrics/AltBufferPoolMetricSet.java    |  47 ++
 .../org/apache/solr/metrics/MetricsMap.java     | 184 +++++++
 .../solr/metrics/OperatingSystemMetricSet.java  |  66 +--
 .../solr/metrics/SolrCoreMetricManager.java     |  27 +-
 .../org/apache/solr/metrics/SolrMetricInfo.java |  23 +-
 .../apache/solr/metrics/SolrMetricManager.java  | 144 +++++-
 .../apache/solr/metrics/SolrMetricReporter.java |  12 +
 .../metrics/reporters/JmxObjectNameFactory.java |  63 ++-
 .../metrics/reporters/ReporterClientCache.java  |  84 ++++
 .../metrics/reporters/SolrGangliaReporter.java  |  48 +-
 .../metrics/reporters/SolrGraphiteReporter.java |  46 +-
 .../solr/metrics/reporters/SolrJmxReporter.java | 206 ++++++--
 .../metrics/reporters/SolrSlf4jReporter.java    |  29 +-
 .../reporters/solr/SolrClusterReporter.java     |  28 +-
 .../reporters/solr/SolrShardReporter.java       |  17 +-
 .../apache/solr/request/SolrRequestHandler.java |   4 +-
 .../org/apache/solr/search/FastLRUCache.java    | 126 ++---
 .../java/org/apache/solr/search/LFUCache.java   | 147 +++---
 .../java/org/apache/solr/search/LRUCache.java   |  82 ++--
 .../org/apache/solr/search/QParserPlugin.java   |  22 +-
 .../java/org/apache/solr/search/SolrCache.java  |   5 +-
 .../org/apache/solr/search/SolrCacheBase.java   |   7 +-
 .../apache/solr/search/SolrFieldCacheBean.java  |  77 +++
 .../apache/solr/search/SolrFieldCacheMBean.java |  78 ---
 .../apache/solr/search/SolrIndexSearcher.java   |  76 ++-
 .../apache/solr/search/facet/FacetModule.java   |   6 -
 .../apache/solr/servlet/SolrDispatchFilter.java |  13 +-
 .../apache/solr/store/blockcache/Metrics.java   | 124 ++---
 .../solr/store/hdfs/HdfsLocalityReporter.java   | 141 +++---
 .../solr/update/DirectUpdateHandler2.java       | 116 ++---
 .../org/apache/solr/update/HdfsUpdateLog.java   |   4 +-
 .../java/org/apache/solr/update/PeerSync.java   |  10 +-
 .../org/apache/solr/update/SolrIndexWriter.java |  26 +-
 .../org/apache/solr/update/UpdateHandler.java   |  18 +-
 .../java/org/apache/solr/update/UpdateLog.java  |  16 +-
 .../apache/solr/update/UpdateShardHandler.java  |  45 +-
 .../src/java/org/apache/solr/util/JmxUtil.java  |   3 -
 ...entedPoolingHttpClientConnectionManager.java |   8 +-
 .../org/apache/solr/util/stats/MetricUtils.java | 439 ++++++++++++-----
 .../src/test-files/solr/solr-jmxreporter.xml    |  43 ++
 .../src/test-files/solr/solr-solrreporter.xml   |   4 +
 .../org/apache/solr/BasicFunctionalityTest.java |  17 +-
 .../test/org/apache/solr/CursorPagingTest.java  |  22 +-
 .../test/org/apache/solr/SolrInfoBeanTest.java  | 124 +++++
 .../test/org/apache/solr/SolrInfoMBeanTest.java | 118 -----
 .../solr/cloud/BasicDistributedZkTest.java      |  24 +-
 .../test/org/apache/solr/cloud/BasicZkTest.java |  15 +-
 .../cloud/CollectionsAPIDistributedZkTest.java  |  36 +-
 .../solr/cloud/ReplicationFactorTest.java       |   9 -
 .../cloud/TestRandomRequestDistribution.java    |  19 +-
 .../solr/core/ExitableDirectoryReaderTest.java  |  26 +-
 .../solr/core/HdfsDirectoryFactoryTest.java     |  29 +-
 .../test/org/apache/solr/core/MockInfoBean.java |  71 +++
 .../org/apache/solr/core/MockInfoMBean.java     |  69 ---
 .../core/MockQuerySenderListenerReqHandler.java |  15 +-
 .../apache/solr/core/RequestHandlersTest.java   |  21 +-
 .../test/org/apache/solr/core/SolrCoreTest.java |   4 +-
 .../apache/solr/core/TestJmxIntegration.java    |  94 ++--
 .../apache/solr/core/TestJmxMonitoredMap.java   | 217 ---------
 .../apache/solr/core/TestSolrDynamicMBean.java  |  87 ----
 .../solr/handler/admin/MBeansHandlerTest.java   |  14 +-
 .../solr/handler/admin/MetricsHandlerTest.java  |  15 +
 .../solr/handler/admin/StatsReloadRaceTest.java |  40 +-
 .../handler/admin/SystemInfoHandlerTest.java    |   8 +-
 .../component/ResourceSharingTestComponent.java |   5 -
 .../org/apache/solr/metrics/JvmMetricsTest.java |  53 +-
 .../solr/metrics/SolrCoreMetricManagerTest.java |   6 +-
 .../solr/metrics/SolrMetricManagerTest.java     |  44 +-
 .../solr/metrics/SolrMetricReporterTest.java    |   1 +
 .../solr/metrics/SolrMetricTestUtils.java       |  12 +-
 .../metrics/SolrMetricsIntegrationTest.java     |  17 +-
 .../reporters/SolrGangliaReporterTest.java      |   2 +-
 .../reporters/SolrGraphiteReporterTest.java     |   4 +-
 .../metrics/reporters/SolrJmxReporterTest.java  |  66 ++-
 .../reporters/SolrSlf4jReporterTest.java        |   2 +-
 .../reporters/solr/SolrCloudReportersTest.java  |   7 +-
 .../apache/solr/search/MockSearchComponent.java |   6 -
 .../apache/solr/search/TestFastLRUCache.java    |  32 +-
 .../apache/solr/search/TestIndexSearcher.java   |   9 +-
 .../org/apache/solr/search/TestLFUCache.java    |  21 +-
 .../org/apache/solr/search/TestLRUCache.java    |  16 +-
 .../solr/search/TestReRankQParserPlugin.java    |  15 +-
 .../apache/solr/search/TestSolr4Spatial2.java   |  11 +-
 .../solr/search/TestSolrFieldCacheBean.java     |  97 ++++
 .../solr/search/TestSolrFieldCacheMBean.java    |  83 ----
 .../apache/solr/search/TestSolrQueryParser.java |  38 +-
 .../apache/solr/search/join/BJQParserTest.java  |  28 +-
 .../solr/search/join/TestScoreJoinQPScore.java  |  52 +-
 .../solr/store/blockcache/BufferStoreTest.java  |  15 +-
 .../apache/solr/util/stats/MetricUtilsTest.java |  11 +-
 .../client/solrj/impl/CloudSolrClientTest.java  |  24 +-
 .../java/org/apache/solr/SolrTestCaseJ4.java    |  14 +
 .../cloud/AbstractFullDistribZkTestBase.java    |   8 -
 .../apache/solr/cloud/MiniSolrCloudCluster.java |   5 +
 .../java/org/apache/solr/util/TestHarness.java  |   4 +-
 solr/webapp/web/css/angular/plugins.css         |  10 +-
 solr/webapp/web/partials/plugins.html           |   2 +-
 157 files changed, 3248 insertions(+), 3087 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/dev-tools/idea/.idea/libraries/Solr_DIH_core_library.xml
----------------------------------------------------------------------
diff --git a/dev-tools/idea/.idea/libraries/Solr_DIH_core_library.xml b/dev-tools/idea/.idea/libraries/Solr_DIH_core_library.xml
new file mode 100644
index 0000000..d363b92
--- /dev/null
+++ b/dev-tools/idea/.idea/libraries/Solr_DIH_core_library.xml
@@ -0,0 +1,10 @@
+<component name="libraryTable">
+  <library name="Solr DIH core library">
+    <CLASSES>
+      <root url="file://$PROJECT_DIR$/solr/contrib/dataimporthandler/lib" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+    <jarDirectory url="file://$PROJECT_DIR$/solr/contrib/dataimporthandler/lib" recursive="false" />
+  </library>
+</component>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/dev-tools/idea/solr/contrib/dataimporthandler/dataimporthandler.iml
----------------------------------------------------------------------
diff --git a/dev-tools/idea/solr/contrib/dataimporthandler/dataimporthandler.iml b/dev-tools/idea/solr/contrib/dataimporthandler/dataimporthandler.iml
index 6268247..8240ff2 100644
--- a/dev-tools/idea/solr/contrib/dataimporthandler/dataimporthandler.iml
+++ b/dev-tools/idea/solr/contrib/dataimporthandler/dataimporthandler.iml
@@ -16,9 +16,10 @@
     <orderEntry type="library" scope="TEST" name="HSQLDB" level="project" />
     <orderEntry type="library" scope="TEST" name="Derby" level="project" />
     <orderEntry type="library" scope="TEST" name="Solr DIH test library" level="project" />
-    <orderEntry type="library" scope="TEST" name="Solr example library" level="project" />
+    <orderEntry type="library" name="Solr example library" level="project" />
     <orderEntry type="library" name="Solr core library" level="project" />
     <orderEntry type="library" name="Solrj library" level="project" />
+    <orderEntry type="library" name="Solr DIH core library" level="project" />
     <orderEntry type="module" scope="TEST" module-name="lucene-test-framework" />
     <orderEntry type="module" scope="TEST" module-name="solr-test-framework" />
     <orderEntry type="module" module-name="solr-core" />

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/lucene/tools/junit4/cached-timehints.txt
----------------------------------------------------------------------
diff --git a/lucene/tools/junit4/cached-timehints.txt b/lucene/tools/junit4/cached-timehints.txt
index f2b8974..cb3da99 100644
--- a/lucene/tools/junit4/cached-timehints.txt
+++ b/lucene/tools/junit4/cached-timehints.txt
@@ -813,7 +813,7 @@ org.apache.solr.EchoParamsTest=136,170,349,124,140,142,284
 org.apache.solr.MinimalSchemaTest=304,316,467,304,297,755,309
 org.apache.solr.OutputWriterTest=302,276,265,314,244,211,268
 org.apache.solr.SampleTest=339,290,266,243,333,414,355
-org.apache.solr.SolrInfoMBeanTest=1090,1132,644,629,637,1023,735
+org.apache.solr.SolrInfoBeanTest=1090,1132,644,629,637,1023,735
 org.apache.solr.TestDistributedGrouping=13095,9478,8420,9633,10692,9265,10893
 org.apache.solr.TestDistributedSearch=11199,9886,16211,11367,11325,10717,10392
 org.apache.solr.TestDocumentBuilder=10,10,9,13,10,9,10

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 7752a16..128e386 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -52,6 +52,19 @@ Upgrading from Solr 6.x
 
 * Deprecated method getNumericType() has been removed from FieldType. Use getNumberType() instead
 
+* MBean names and attributes now follow hierarchical names used in metrics. This is reflected also in
+  /admin/mbeans and /admin/plugins output, and can be observed in the UI Plugins tab, because now all these
+  APIs get their data from the metrics API. The old (mostly flat) JMX view has been removed.
+
+* <jmx> element in solrconfig.xml is no longer supported. Equivalent functionality can be configured in
+  solr.xml using <metrics><reporter ...> element and SolrJmxReporter implementation. Limited back-compatibility
+  is offered by automatically adding a default instance of SolrJmxReporter if it's missing, AND when a local
+  MBean server is found (which can be activated either via ENABLE_REMOTE_JMX_OPTS in solr.in.sh or via system
+  properties, eg. -Dcom.sun.management.jmxremote). This default instance exports all Solr metrics from all
+  registries as hierarchical MBeans. This behavior can be also disabled by specifying a SolrJmxReporter
+  configuration with a boolean init arg "enabled" set to "false". For a more fine-grained control users
+  should explicitly specify at least one SolrJmxReporter configuration.
+
 New Features
 ----------------------
 * SOLR-9857, SOLR-9858: Collect aggregated metrics from nodes and shard leaders in overseer. (ab)
@@ -96,6 +109,10 @@ Other Changes
 * SOLR-10347: Removed index level boost support from "documents" section of the admin UI (Amrit Sarkar via
   Tom�s Fern�ndez L�bbe)
 
+* SOLR-9959: SolrInfoMBean category and hierarchy cleanup. Per-component statistics are now obtained from
+  the metrics API, legacy JMX support has been replaced with SolrJmxReporter functionality. Several reporter
+  improvements (support for multiple prefix filters, "enabled" flag, reuse of service clients). (ab)
+
 ----------------------
 
 ==================  6.6.0 ==================

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
index b22dcb5..657768f 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
@@ -16,11 +16,11 @@
  */
 package org.apache.solr.analytics.plugin;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
 
 import com.codahale.metrics.Timer;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.util.stats.MetricUtils;
 
 public class AnalyticsStatisticsCollector {
@@ -85,17 +85,20 @@ public class AnalyticsStatisticsCollector {
     currentTimer.stop();
   }
 
-  public NamedList<Object> getStatistics() {
-    NamedList<Object> lst = new SimpleOrderedMap<>();
-    lst.add("requests", numRequests.longValue());
-    lst.add("analyticsRequests", numAnalyticsRequests.longValue());
-    lst.add("statsRequests", numStatsRequests.longValue());
-    lst.add("statsCollected", numCollectedStats.longValue());
-    lst.add("fieldFacets", numFieldFacets.longValue());
-    lst.add("rangeFacets", numRangeFacets.longValue());
-    lst.add("queryFacets", numQueryFacets.longValue());
-    lst.add("queriesInQueryFacets", numQueries.longValue());
-    MetricUtils.addMetrics(lst, requestTimes);
-    return lst;
+  public Map<String, Object> getStatistics() {
+
+    Map<String, Object> map = new HashMap<>();
+    MetricUtils.convertTimer("", requestTimes, false, false, (k, v) -> {
+      map.putAll((Map<String, Object>)v);
+    });
+    map.put("requests", numRequests.longValue());
+    map.put("analyticsRequests", numAnalyticsRequests.longValue());
+    map.put("statsRequests", numStatsRequests.longValue());
+    map.put("statsCollected", numCollectedStats.longValue());
+    map.put("fieldFacets", numFieldFacets.longValue());
+    map.put("rangeFacets", numRangeFacets.longValue());
+    map.put("queryFacets", numQueryFacets.longValue());
+    map.put("queriesInQueryFacets", numQueries.longValue());
+    return map;
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java b/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
index f33b6c7..505533b 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
@@ -22,9 +22,11 @@ import org.apache.solr.analytics.plugin.AnalyticsStatisticsCollector;
 import org.apache.solr.analytics.request.AnalyticsStats;
 import org.apache.solr.analytics.util.AnalyticsParams;
 import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.NamedList;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
 
-public class AnalyticsComponent extends SearchComponent {
+public class AnalyticsComponent extends SearchComponent implements SolrMetricProducer {
   public static final String COMPONENT_NAME = "analytics";
   private final AnalyticsStatisticsCollector analyticsCollector = new AnalyticsStatisticsCollector();;
 
@@ -80,12 +82,8 @@ public class AnalyticsComponent extends SearchComponent {
   }
 
   @Override
-  public String getVersion() {
-    return getClass().getPackage().getSpecificationVersion();
-  }
-
-  @Override
-  public NamedList getStatistics() {
-    return analyticsCollector.getStatistics();
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsMap metrics = new MetricsMap((detailed, map) -> map.putAll(analyticsCollector.getStatistics()));
+    manager.registerGauge(this, registry, metrics, true, getClass().getSimpleName(), getCategory().toString(), scope);
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java
index 0766c7f..faea3ba 100644
--- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java
+++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java
@@ -26,12 +26,13 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.ContentStreamBase;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.common.util.ContentStream;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrResourceLoader;
 import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.response.RawResponseWriter;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
@@ -74,6 +75,8 @@ public class DataImportHandler extends RequestHandlerBase implements
 
   private String myName = "dataimport";
 
+  private MetricsMap metrics;
+
   private static final String PARAM_WRITER_IMPL = "writerImpl";
   private static final String DEFAULT_WRITER_NAME = "SolrWriter";
 
@@ -260,41 +263,33 @@ public class DataImportHandler extends RequestHandlerBase implements
       };
     }
   }
-  
-  @Override
-  @SuppressWarnings("unchecked")
-  public NamedList getStatistics() {
-    if (importer == null)
-      return super.getStatistics();
 
-    DocBuilder.Statistics cumulative = importer.cumulativeStatistics;
-    SimpleOrderedMap result = new SimpleOrderedMap();
-
-    result.add("Status", importer.getStatus().toString());
+  @Override
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+    super.initializeMetrics(manager, registryName, scope);
+    metrics = new MetricsMap((detailed, map) -> {
+      if (importer != null) {
+        DocBuilder.Statistics cumulative = importer.cumulativeStatistics;
 
-    if (importer.docBuilder != null) {
-      DocBuilder.Statistics running = importer.docBuilder.importStatistics;
-      result.add("Documents Processed", running.docCount);
-      result.add("Requests made to DataSource", running.queryCount);
-      result.add("Rows Fetched", running.rowsCount);
-      result.add("Documents Deleted", running.deletedDocCount);
-      result.add("Documents Skipped", running.skipDocCount);
-    }
+        map.put("Status", importer.getStatus().toString());
 
-    result.add(DataImporter.MSG.TOTAL_DOC_PROCESSED, cumulative.docCount);
-    result.add(DataImporter.MSG.TOTAL_QUERIES_EXECUTED, cumulative.queryCount);
-    result.add(DataImporter.MSG.TOTAL_ROWS_EXECUTED, cumulative.rowsCount);
-    result.add(DataImporter.MSG.TOTAL_DOCS_DELETED, cumulative.deletedDocCount);
-    result.add(DataImporter.MSG.TOTAL_DOCS_SKIPPED, cumulative.skipDocCount);
+        if (importer.docBuilder != null) {
+          DocBuilder.Statistics running = importer.docBuilder.importStatistics;
+          map.put("Documents Processed", running.docCount);
+          map.put("Requests made to DataSource", running.queryCount);
+          map.put("Rows Fetched", running.rowsCount);
+          map.put("Documents Deleted", running.deletedDocCount);
+          map.put("Documents Skipped", running.skipDocCount);
+        }
 
-    NamedList requestStatistics = super.getStatistics();
-    if (requestStatistics != null) {
-      for (int i = 0; i < requestStatistics.size(); i++) {
-        result.add(requestStatistics.getName(i), requestStatistics.getVal(i));
+        map.put(DataImporter.MSG.TOTAL_DOC_PROCESSED, cumulative.docCount);
+        map.put(DataImporter.MSG.TOTAL_QUERIES_EXECUTED, cumulative.queryCount);
+        map.put(DataImporter.MSG.TOTAL_ROWS_EXECUTED, cumulative.rowsCount);
+        map.put(DataImporter.MSG.TOTAL_DOCS_DELETED, cumulative.deletedDocCount);
+        map.put(DataImporter.MSG.TOTAL_DOCS_SKIPPED, cumulative.skipDocCount);
       }
-    }
-
-    return result;
+    });
+    manager.registerGauge(this, registryName, metrics, true, "importer", getCategory().toString(), scope);
   }
 
   // //////////////////////SolrInfoMBeans methods //////////////////////

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 1ef036a..f1e28dd 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -81,6 +81,7 @@ import org.apache.solr.metrics.SolrCoreMetricManager;
 import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.metrics.SolrMetricProducer;
 import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.search.SolrFieldCacheBean;
 import org.apache.solr.security.AuthenticationPlugin;
 import org.apache.solr.security.AuthorizationPlugin;
 import org.apache.solr.security.HttpClientBuilderPlugin;
@@ -482,18 +483,18 @@ public class CoreContainer {
     metricManager = new SolrMetricManager();
 
     coreContainerWorkExecutor = MetricUtils.instrumentedExecutorService(
-        coreContainerWorkExecutor,
-        metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoMBean.Group.node)),
-        SolrMetricManager.mkName("coreContainerWorkExecutor", SolrInfoMBean.Category.CONTAINER.toString(), "threadPool"));
+        coreContainerWorkExecutor, null,
+        metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)),
+        SolrMetricManager.mkName("coreContainerWorkExecutor", SolrInfoBean.Category.CONTAINER.toString(), "threadPool"));
 
     shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
     if (shardHandlerFactory instanceof SolrMetricProducer) {
       SolrMetricProducer metricProducer = (SolrMetricProducer) shardHandlerFactory;
-      metricProducer.initializeMetrics(metricManager, SolrInfoMBean.Group.node.toString(), "httpShardHandler");
+      metricProducer.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), "httpShardHandler");
     }
 
     updateShardHandler = new UpdateShardHandler(cfg.getUpdateShardHandlerConfig());
-    updateShardHandler.initializeMetrics(metricManager, SolrInfoMBean.Group.node.toString(), "updateShardHandler");
+    updateShardHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), "updateShardHandler");
 
     transientCoreCache = TransientSolrCoreCacheFactory.newInstance(loader, this);
 
@@ -520,14 +521,14 @@ public class CoreContainer {
     // may want to add some configuration here in the future
     metricsCollectorHandler.init(null);
     containerHandlers.put(AUTHZ_PATH, securityConfHandler);
-    securityConfHandler.initializeMetrics(metricManager, SolrInfoMBean.Group.node.toString(), AUTHZ_PATH);
+    securityConfHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), AUTHZ_PATH);
     containerHandlers.put(AUTHC_PATH, securityConfHandler);
     if(pkiAuthenticationPlugin != null)
       containerHandlers.put(PKIAuthenticationPlugin.PATH, pkiAuthenticationPlugin.getRequestHandler());
 
-    metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoMBean.Group.node);
-    metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoMBean.Group.jvm);
-    metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoMBean.Group.jetty);
+    metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoBean.Group.node);
+    metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoBean.Group.jvm);
+    metricManager.loadReporters(cfg.getMetricReporterPlugins(), loader, null, SolrInfoBean.Group.jetty);
 
     coreConfigService = ConfigSetService.createConfigSetService(cfg, loader, zkSys.zkController);
 
@@ -535,17 +536,25 @@ public class CoreContainer {
 
     // initialize gauges for reporting the number of cores and disk total/free
 
-    String registryName = SolrMetricManager.getRegistryName(SolrInfoMBean.Group.node);
-    metricManager.registerGauge(registryName, () -> solrCores.getCores().size(),
-        true, "loaded", SolrInfoMBean.Category.CONTAINER.toString(), "cores");
-    metricManager.registerGauge(registryName, () -> solrCores.getLoadedCoreNames().size() - solrCores.getCores().size(),
-        true, "lazy",SolrInfoMBean.Category.CONTAINER.toString(), "cores");
-    metricManager.registerGauge(registryName, () -> solrCores.getAllCoreNames().size() - solrCores.getLoadedCoreNames().size(),
-        true, "unloaded",SolrInfoMBean.Category.CONTAINER.toString(), "cores");
-    metricManager.registerGauge(registryName, () -> cfg.getCoreRootDirectory().toFile().getTotalSpace(),
-        true, "totalSpace", SolrInfoMBean.Category.CONTAINER.toString(), "fs");
-    metricManager.registerGauge(registryName, () -> cfg.getCoreRootDirectory().toFile().getUsableSpace(),
-        true, "usableSpace", SolrInfoMBean.Category.CONTAINER.toString(), "fs");
+    String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.node);
+    metricManager.registerGauge(null, registryName, () -> solrCores.getCores().size(),
+        true, "loaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
+    metricManager.registerGauge(null, registryName, () -> solrCores.getLoadedCoreNames().size() - solrCores.getCores().size(),
+        true, "lazy", SolrInfoBean.Category.CONTAINER.toString(), "cores");
+    metricManager.registerGauge(null, registryName, () -> solrCores.getAllCoreNames().size() - solrCores.getLoadedCoreNames().size(),
+        true, "unloaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
+    metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toFile().getTotalSpace(),
+        true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
+    metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toFile().getUsableSpace(),
+        true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
+    // add version information
+    metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getSpecificationVersion(),
+        true, "specification", SolrInfoBean.Category.CONTAINER.toString(), "version");
+    metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getImplementationVersion(),
+        true, "implementation", SolrInfoBean.Category.CONTAINER.toString(), "version");
+
+    SolrFieldCacheBean fieldCacheBean = new SolrFieldCacheBean();
+    fieldCacheBean.initializeMetrics(metricManager, registryName, null);
 
     if (isZooKeeperAware()) {
       metricManager.loadClusterReporters(cfg.getMetricReporterPlugins(), this);
@@ -555,9 +564,9 @@ public class CoreContainer {
     ExecutorService coreLoadExecutor = MetricUtils.instrumentedExecutorService(
         ExecutorUtil.newMDCAwareFixedThreadPool(
             cfg.getCoreLoadThreadCount(isZooKeeperAware()),
-            new DefaultSolrThreadFactory("coreLoadExecutor")),
-        metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoMBean.Group.node)),
-        SolrMetricManager.mkName("coreLoadExecutor",SolrInfoMBean.Category.CONTAINER.toString(), "threadPool"));
+            new DefaultSolrThreadFactory("coreLoadExecutor")), null,
+        metricManager.registry(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node)),
+        SolrMetricManager.mkName("coreLoadExecutor", SolrInfoBean.Category.CONTAINER.toString(), "threadPool"));
     final List<Future<SolrCore>> futures = new ArrayList<>();
     try {
       List<CoreDescriptor> cds = coresLocator.discover(this);
@@ -685,14 +694,16 @@ public class CoreContainer {
 
     ExecutorUtil.shutdownAndAwaitTermination(coreContainerWorkExecutor);
     if (metricManager != null) {
-      metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoMBean.Group.node));
+      metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node));
+      metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm));
+      metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jetty));
     }
 
     if (isZooKeeperAware()) {
       cancelCoreRecoveries();
       zkSys.zkController.publishNodeAsDown(zkSys.zkController.getNodeName());
       if (metricManager != null) {
-        metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoMBean.Group.cluster));
+        metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.cluster));
       }
     }
 
@@ -1058,7 +1069,7 @@ public class CoreContainer {
   private void resetIndexDirectory(CoreDescriptor dcore, ConfigSet coreConfig) {
     SolrConfig config = coreConfig.getSolrConfig();
 
-    String registryName = SolrMetricManager.getRegistryName(SolrInfoMBean.Group.core, dcore.getName());
+    String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.core, dcore.getName());
     DirectoryFactory df = DirectoryFactory.loadDirectoryFactory(config, this, registryName);
     String dataDir = SolrCore.findDataDir(df, null, config, dcore);
 
@@ -1376,7 +1387,7 @@ public class CoreContainer {
       containerHandlers.put(path, (SolrRequestHandler)handler);
     }
     if (handler instanceof SolrMetricProducer) {
-      ((SolrMetricProducer)handler).initializeMetrics(metricManager, SolrInfoMBean.Group.node.toString(), path);
+      ((SolrMetricProducer)handler).initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), path);
     }
     return handler;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
index cc24e6c..20824ab 100644
--- a/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
+++ b/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.nio.file.NoSuchFileException;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -321,13 +320,6 @@ public abstract class DirectoryFactory implements NamedListInitializedPlugin,
     return cd.getInstanceDir().resolve(cd.getDataDir()).toAbsolutePath().toString();
   }
 
-  /**
-   * Optionally allow the DirectoryFactory to request registration of some MBeans.
-   */
-  public Collection<SolrInfoMBean> offerMBeans() {
-    return Collections.emptySet();
-  }
-
   public void cleanupOldIndexDirectories(final String dataDirPath, final String currentIndexDirPath, boolean afterCoreReload) {
     File dataDir = new File(dataDirPath);
     if (!dataDir.isDirectory()) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java b/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
index db953d3..754fed3 100644
--- a/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
+++ b/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
@@ -22,7 +22,6 @@ import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.net.URLEncoder;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -51,6 +50,8 @@ import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.common.util.NamedList;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
 import org.apache.solr.store.blockcache.BlockCache;
 import org.apache.solr.store.blockcache.BlockDirectory;
 import org.apache.solr.store.blockcache.BlockDirectoryCache;
@@ -70,7 +71,7 @@ import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.RemovalListener;
 import com.google.common.cache.RemovalNotification;
 
-public class HdfsDirectoryFactory extends CachingDirectoryFactory implements SolrCoreAware {
+public class HdfsDirectoryFactory extends CachingDirectoryFactory implements SolrCoreAware, SolrMetricProducer {
   private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   
   public static final String BLOCKCACHE_SLAB_COUNT = "solr.hdfs.blockcache.slab.count";
@@ -493,8 +494,9 @@ public class HdfsDirectoryFactory extends CachingDirectoryFactory implements Sol
   }
 
   @Override
-  public Collection<SolrInfoMBean> offerMBeans() {
-    return Arrays.<SolrInfoMBean>asList(MetricsHolder.metrics, LocalityHolder.reporter);
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsHolder.metrics.initializeMetrics(manager, registry, scope);
+    LocalityHolder.reporter.initializeMetrics(manager, registry, scope);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java b/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java
deleted file mode 100644
index 4fb0dcd..0000000
--- a/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java
+++ /dev/null
@@ -1,478 +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 javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.DynamicMBean;
-import javax.management.InstanceNotFoundException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerFactory;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-import javax.management.Query;
-import javax.management.QueryExp;
-import javax.management.ReflectionException;
-import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXConnectorServerFactory;
-import javax.management.remote.JMXServiceURL;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.lucene.store.AlreadyClosedException;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.core.SolrConfig.JmxConfiguration;
-import org.apache.solr.metrics.reporters.JmxObjectNameFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.solr.common.params.CommonParams.ID;
-import static org.apache.solr.common.params.CommonParams.NAME;
-
-/**
- * <p>
- * Responsible for finding (or creating) a MBeanServer from given configuration
- * and registering all SolrInfoMBean objects with JMX.
- * </p>
- * <p>
- * Please see http://wiki.apache.org/solr/SolrJmx for instructions on usage and configuration
- * </p>
- *
- *
- * @see org.apache.solr.core.SolrConfig.JmxConfiguration
- * @since solr 1.3
- */
-public class JmxMonitoredMap<K, V> extends
-        ConcurrentHashMap<String, SolrInfoMBean> {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
-  private static final String REPORTER_NAME = "_jmx_";
-
-  // set to true to use cached statistics NamedLists between getMBeanInfo calls to work
-  // around over calling getStatistics on MBeanInfos when iterating over all attributes (SOLR-6586)
-  private final boolean useCachedStatsBetweenGetMBeanInfoCalls = Boolean.getBoolean("useCachedStatsBetweenGetMBeanInfoCalls");
-  
-  private final MBeanServer server;
-
-  private final String jmxRootName;
-
-  private final String coreHashCode;
-
-  private final JmxObjectNameFactory nameFactory;
-
-  private final String registryName;
-
-  public JmxMonitoredMap(String coreName, String coreHashCode, String registryName,
-                         final JmxConfiguration jmxConfig) {
-    this.coreHashCode = coreHashCode;
-    this.registryName = registryName;
-    jmxRootName = (null != jmxConfig.rootName ?
-                   jmxConfig.rootName
-                   : ("solr" + (null != coreName ? "/" + coreName : "")));
-      
-    if (jmxConfig.serviceUrl == null) {
-      List<MBeanServer> servers = null;
-
-      if (jmxConfig.agentId == null) {
-        // Try to find the first MBeanServer
-        servers = MBeanServerFactory.findMBeanServer(null);
-      } else if (jmxConfig.agentId != null) {
-        // Try to find the first MBean server with the given agentId
-        servers = MBeanServerFactory.findMBeanServer(jmxConfig.agentId);
-        // throw Exception if no servers were found with the given agentId
-        if (servers == null || servers.isEmpty())
-          throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
-                  "No JMX Servers found with agentId: " + jmxConfig.agentId);
-      }
-
-      if (servers == null || servers.isEmpty()) {
-        server = null;
-        nameFactory = null;
-        log.debug("No JMX servers found, not exposing Solr information with JMX.");
-        return;
-      }
-      server = servers.get(0);
-      log.info("JMX monitoring is enabled. Adding Solr mbeans to JMX Server: "
-               + server);
-    } else {
-      MBeanServer newServer = null;
-      try {
-        // Create a new MBeanServer with the given serviceUrl
-        newServer = MBeanServerFactory.newMBeanServer();
-        JMXConnectorServer connector = JMXConnectorServerFactory
-                .newJMXConnectorServer(new JMXServiceURL(jmxConfig.serviceUrl),
-                        null, newServer);
-        connector.start();
-        log.info("JMX monitoring is enabled at " + jmxConfig.serviceUrl);
-      } catch (Exception e) {
-        // Release the reference
-        throw new RuntimeException("Could not start JMX monitoring ", e);
-      }
-      server = newServer;
-    }
-    nameFactory = new JmxObjectNameFactory(REPORTER_NAME + coreHashCode, registryName);
-  }
-
-  /**
-   * Clears the map and unregisters all SolrInfoMBeans in the map from
-   * MBeanServer
-   */
-  @Override
-  public void clear() {
-    if (server != null) {
-      QueryExp exp = Query.or(Query.eq(Query.attr("coreHashCode"), Query.value(coreHashCode)),
-                            Query.eq(Query.attr("reporter"), Query.value(REPORTER_NAME + coreHashCode)));
-      
-      Set<ObjectName> objectNames = null;
-      try {
-        objectNames = server.queryNames(null, exp);
-      } catch (Exception e) {
-        log.warn("Exception querying for mbeans", e);
-      }
-      
-      if (objectNames != null)  {
-        for (ObjectName name : objectNames) {
-          try {
-            server.unregisterMBean(name);
-          } catch (InstanceNotFoundException ie) {
-            // ignore - someone else already deleted this one
-          } catch (Exception e) {
-            log.warn("Exception un-registering mbean {}", name, e);
-          }
-        }
-      }
-    }
-
-    super.clear();
-  }
-
-  /**
-   * Adds the SolrInfoMBean to the map and registers the given SolrInfoMBean
-   * instance with the MBeanServer defined for this core. If a SolrInfoMBean is
-   * already registered with the MBeanServer then it is unregistered and then
-   * re-registered.
-   *
-   * @param key      the JMX type name for this SolrInfoMBean
-   * @param infoBean the SolrInfoMBean instance to be registered
-   */
-  @Override
-  public SolrInfoMBean put(String key, SolrInfoMBean infoBean) {
-    if (server != null && infoBean != null) {
-      try {
-        // back-compat name
-        ObjectName name = getObjectName(key, infoBean);
-        if (server.isRegistered(name))
-          server.unregisterMBean(name);
-        SolrDynamicMBean mbean = new SolrDynamicMBean(coreHashCode, infoBean, useCachedStatsBetweenGetMBeanInfoCalls);
-        server.registerMBean(mbean, name);
-        // now register it also under new name
-        String beanName = createBeanName(infoBean, key);
-        name = nameFactory.createName(null, registryName, beanName);
-        if (server.isRegistered(name))
-          server.unregisterMBean(name);
-        server.registerMBean(mbean, name);
-      } catch (Exception e) {
-        log.warn( "Failed to register info bean: key=" + key + ", infoBean=" + infoBean, e);
-      }
-    }
-
-    return super.put(key, infoBean);
-  }
-
-  private String createBeanName(SolrInfoMBean infoBean, String key) {
-    if (infoBean.getCategory() == null) {
-      throw new IllegalArgumentException("SolrInfoMBean.category must never be null: " + infoBean);
-    }
-    StringBuilder sb = new StringBuilder();
-    sb.append(infoBean.getCategory().toString());
-    sb.append('.');
-    sb.append(key);
-    sb.append('.');
-    sb.append(infoBean.getName());
-    return sb.toString();
-  }
-
-  /**
-   * Removes the SolrInfoMBean object at the given key and unregisters it from
-   * MBeanServer
-   *
-   * @param key the JMX type name for this SolrInfoMBean
-   */
-  @Override
-  public SolrInfoMBean remove(Object key) {
-    SolrInfoMBean infoBean = get(key);
-    if (infoBean != null) {
-      try {
-        unregister((String) key, infoBean);
-      } catch (RuntimeException e) {
-        log.warn( "Failed to unregister info bean: " + key, e);
-      }
-    }
-    return super.remove(key);
-  }
-
-  private void unregister(String key, SolrInfoMBean infoBean) {
-    if (server == null)
-      return;
-
-    try {
-      // remove legacy name
-      ObjectName name = getObjectName(key, infoBean);
-      if (server.isRegistered(name) && coreHashCode.equals(server.getAttribute(name, "coreHashCode"))) {
-        server.unregisterMBean(name);
-      }
-      // remove new name
-      String beanName = createBeanName(infoBean, key);
-      name = nameFactory.createName(null, registryName, beanName);
-      if (server.isRegistered(name)) {
-        server.unregisterMBean(name);
-      }
-    } catch (Exception e) {
-      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
-              "Failed to unregister info bean: " + key, e);
-    }
-  }
-
-  private ObjectName getObjectName(String key, SolrInfoMBean infoBean)
-          throws MalformedObjectNameException {
-    Hashtable<String, String> map = new Hashtable<>();
-    map.put("type", key);
-    if (infoBean.getName() != null && !"".equals(infoBean.getName())) {
-      map.put(ID, infoBean.getName());
-    }
-    return ObjectName.getInstance(jmxRootName, map);
-  }
-
-  /** For test verification */
-  public MBeanServer getServer() {
-    return server;
-  }
-
-  /**
-   * DynamicMBean is used to dynamically expose all SolrInfoMBean
-   * getStatistics() NameList keys as String getters.
-   */
-  static class SolrDynamicMBean implements DynamicMBean {
-    private SolrInfoMBean infoBean;
-
-    private HashSet<String> staticStats;
-
-    private String coreHashCode;
-    
-    private volatile NamedList cachedDynamicStats;
-    
-    private boolean useCachedStatsBetweenGetMBeanInfoCalls;
-    
-    public SolrDynamicMBean(String coreHashCode, SolrInfoMBean managedResource) {
-      this(coreHashCode, managedResource, false);
-    }
-
-    public SolrDynamicMBean(String coreHashCode, SolrInfoMBean managedResource, boolean useCachedStatsBetweenGetMBeanInfoCalls) {
-      this.useCachedStatsBetweenGetMBeanInfoCalls = useCachedStatsBetweenGetMBeanInfoCalls;
-      if (managedResource instanceof JmxAugmentedSolrInfoMBean) {
-        final JmxAugmentedSolrInfoMBean jmxSpecific = (JmxAugmentedSolrInfoMBean)managedResource;
-        this.infoBean = new SolrInfoMBeanWrapper(jmxSpecific) {
-          @Override
-          public NamedList getStatistics() { return jmxSpecific.getStatisticsForJmx(); }
-        };
-      } else {
-        this.infoBean = managedResource;
-      }
-      staticStats = new HashSet<>();
-
-      // For which getters are already available in SolrInfoMBean
-      staticStats.add(NAME);
-      staticStats.add("version");
-      staticStats.add("description");
-      staticStats.add("category");
-      staticStats.add("source");
-      this.coreHashCode = coreHashCode;
-    }
-
-    @Override
-    public MBeanInfo getMBeanInfo() {
-      ArrayList<MBeanAttributeInfo> attrInfoList = new ArrayList<>();
-
-      for (String stat : staticStats) {
-        attrInfoList.add(new MBeanAttributeInfo(stat, String.class.getName(),
-                null, true, false, false));
-      }
-
-      // add core's hashcode
-      attrInfoList.add(new MBeanAttributeInfo("coreHashCode", String.class.getName(),
-                null, true, false, false));
-
-      try {
-        NamedList dynamicStats = infoBean.getStatistics();
-        
-        if (useCachedStatsBetweenGetMBeanInfoCalls) {
-          cachedDynamicStats = dynamicStats;
-        }
-        
-        if (dynamicStats != null) {
-          for (int i = 0; i < dynamicStats.size(); i++) {
-            String name = dynamicStats.getName(i);
-            if (staticStats.contains(name)) {
-              continue;
-            }
-            Class type = dynamicStats.get(name).getClass();
-            OpenType typeBox = determineType(type);
-            if (type.equals(String.class) || typeBox == null) {
-              attrInfoList.add(new MBeanAttributeInfo(dynamicStats.getName(i),
-                  String.class.getName(), null, true, false, false));
-            } else {
-              attrInfoList.add(new OpenMBeanAttributeInfoSupport(
-                  dynamicStats.getName(i), dynamicStats.getName(i), typeBox,
-                  true, false, false));
-            }
-          }
-        }
-      } catch (Exception e) {
-        // don't log issue if the core is closing
-        if (!(SolrException.getRootCause(e) instanceof AlreadyClosedException))
-          log.warn("Could not getStatistics on info bean {}", infoBean.getName(), e);
-      }
-
-      MBeanAttributeInfo[] attrInfoArr = attrInfoList
-              .toArray(new MBeanAttributeInfo[attrInfoList.size()]);
-      return new MBeanInfo(getClass().getName(), infoBean
-              .getDescription(), attrInfoArr, null, null, null);
-    }
-
-    private OpenType determineType(Class type) {
-      try {
-        for (Field field : SimpleType.class.getFields()) {
-          if (field.getType().equals(SimpleType.class)) {
-            SimpleType candidate = (SimpleType) field.get(SimpleType.class);
-            if (candidate.getTypeName().equals(type.getName())) {
-              return candidate;
-            }
-          }
-        }
-      } catch (Exception e) {
-        throw new RuntimeException(e);
-      }
-      return null;
-    }
-
-    @Override
-    public Object getAttribute(String attribute)
-            throws AttributeNotFoundException, MBeanException, ReflectionException {
-      Object val;
-      if ("coreHashCode".equals(attribute)) {
-        val = coreHashCode;
-      } else if (staticStats.contains(attribute) && attribute != null
-              && attribute.length() > 0) {
-        try {
-          String getter = "get" + attribute.substring(0, 1).toUpperCase(Locale.ROOT)
-                  + attribute.substring(1);
-          Method meth = infoBean.getClass().getMethod(getter);
-          val = meth.invoke(infoBean);
-        } catch (Exception e) {
-          throw new AttributeNotFoundException(attribute);
-        }
-      } else {
-        NamedList stats = null;
-        if (useCachedStatsBetweenGetMBeanInfoCalls) {
-          NamedList cachedStats = this.cachedDynamicStats;
-          if (cachedStats != null) {
-            stats = cachedStats;
-          }
-        }
-        if (stats == null) {
-          stats = infoBean.getStatistics();
-        }
-        val = stats.get(attribute);
-      }
-
-      if (val != null) {
-        // It's String or one of the simple types, just return it as JMX suggests direct support for such types
-        for (String simpleTypeName : SimpleType.ALLOWED_CLASSNAMES_LIST) {
-          if (val.getClass().getName().equals(simpleTypeName)) {
-            return val;
-          }
-        }
-        // It's an arbitrary object which could be something complex and odd, return its toString, assuming that is
-        // a workable representation of the object
-        return val.toString();
-      }
-      return null;
-    }
-
-    @Override
-    public AttributeList getAttributes(String[] attributes) {
-      AttributeList list = new AttributeList();
-      for (String attribute : attributes) {
-        try {
-          list.add(new Attribute(attribute, getAttribute(attribute)));
-        } catch (Exception e) {
-          log.warn("Could not get attribute " + attribute);
-        }
-      }
-
-      return list;
-    }
-
-    @Override
-    public void setAttribute(Attribute attribute)
-            throws AttributeNotFoundException, InvalidAttributeValueException,
-            MBeanException, ReflectionException {
-      throw new UnsupportedOperationException("Operation not Supported");
-    }
-
-    @Override
-    public AttributeList setAttributes(AttributeList attributes) {
-      throw new UnsupportedOperationException("Operation not Supported");
-    }
-
-    @Override
-    public Object invoke(String actionName, Object[] params, String[] signature)
-            throws MBeanException, ReflectionException {
-      throw new UnsupportedOperationException("Operation not Supported");
-    }
-  }
-
-  /**
-   * SolrInfoMBean that provides JMX-specific statistics.  Used, for example,
-   * if generating full statistics is expensive; the expensive statistics can
-   * be generated normally for use with the web ui, while an abbreviated version
-   * are generated for period jmx use.
-   */
-  public interface JmxAugmentedSolrInfoMBean extends SolrInfoMBean {
-    /**
-     * JMX-specific statistics
-     */
-    public NamedList getStatisticsForJmx();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/PluginBag.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/PluginBag.java b/solr/core/src/java/org/apache/solr/core/PluginBag.java
index 65978f3..b916ad2 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginBag.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginBag.java
@@ -294,8 +294,8 @@ public class PluginBag<T> implements AutoCloseable {
 
   private void registerMBean(Object inst, SolrCore core, String pluginKey) {
     if (core == null) return;
-    if (inst instanceof SolrInfoMBean) {
-      SolrInfoMBean mBean = (SolrInfoMBean) inst;
+    if (inst instanceof SolrInfoBean) {
+      SolrInfoBean mBean = (SolrInfoBean) inst;
       String name = (inst instanceof SolrRequestHandler) ? pluginKey : mBean.getName();
       core.registerInfoBean(name, mBean);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/SolrConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrConfig.java b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
index a244420..4e7ab48 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
@@ -276,18 +276,12 @@ public class SolrConfig extends Config implements MapSerializable {
     hashSetInverseLoadFactor = 1.0f / getFloat("//HashDocSet/@loadFactor", 0.75f);
     hashDocSetMaxSize = getInt("//HashDocSet/@maxSize", 3000);
 
-    httpCachingConfig = new HttpCachingConfig(this);
+    if (get("jmx", null) != null) {
+      log.warn("solrconfig.xml: <jmx> is no longer supported, use solr.xml:/metrics/reporter section instead");
+    }
 
-    Node jmx = getNode("jmx", false);
-    if (jmx != null) {
-      jmxConfig = new JmxConfiguration(true,
-          get("jmx/@agentId", null),
-          get("jmx/@serviceUrl", null),
-          get("jmx/@rootName", null));
+    httpCachingConfig = new HttpCachingConfig(this);
 
-    } else {
-      jmxConfig = new JmxConfiguration(false, null, null, null);
-    }
     maxWarmingSearchers = getInt("query/maxWarmingSearchers", 1);
     slowQueryThresholdMillis = getInt("query/slowQueryThresholdMillis", -1);
     for (SolrPluginInfo plugin : plugins) loadPluginInfo(plugin);
@@ -510,48 +504,12 @@ public class SolrConfig extends Config implements MapSerializable {
   protected String dataDir;
   public final int slowQueryThresholdMillis;  // threshold above which a query is considered slow
 
-  //JMX configuration
-  public final JmxConfiguration jmxConfig;
-
   private final HttpCachingConfig httpCachingConfig;
 
   public HttpCachingConfig getHttpCachingConfig() {
     return httpCachingConfig;
   }
 
-  public static class JmxConfiguration implements MapSerializable {
-    public boolean enabled = false;
-    public String agentId;
-    public String serviceUrl;
-    public String rootName;
-
-    public JmxConfiguration(boolean enabled,
-                            String agentId,
-                            String serviceUrl,
-                            String rootName) {
-      this.enabled = enabled;
-      this.agentId = agentId;
-      this.serviceUrl = serviceUrl;
-      this.rootName = rootName;
-
-      if (agentId != null && serviceUrl != null) {
-        throw new SolrException
-            (SolrException.ErrorCode.SERVER_ERROR,
-                "Incorrect JMX Configuration in solrconfig.xml, " +
-                    "both agentId and serviceUrl cannot be specified at the same time");
-      }
-
-    }
-
-    @Override
-    public Map<String, Object> toMap(Map<String, Object> map) {
-      map.put("agentId", agentId);
-      map.put("serviceUrl", serviceUrl);
-      map.put("rootName", rootName);
-      return map;
-    }
-  }
-
   public static class HttpCachingConfig implements MapSerializable {
 
     /**
@@ -858,7 +816,6 @@ public class SolrConfig extends Config implements MapSerializable {
     m.put("queryResultMaxDocsCached", queryResultMaxDocsCached);
     m.put("enableLazyFieldLoading", enableLazyFieldLoading);
     m.put("maxBooleanClauses", booleanQueryMaxClauseCount);
-    if (jmxConfig != null) result.put("jmx", jmxConfig);
     for (SolrPluginInfo plugin : plugins) {
       List<PluginInfo> infos = getPluginInfos(plugin.clazz.getName());
       if (infos == null || infos.isEmpty()) continue;
@@ -884,7 +841,6 @@ public class SolrConfig extends Config implements MapSerializable {
 
 
     addCacheConfig(m, filterCacheConfig, queryResultCacheConfig, documentCacheConfig, fieldValueCacheConfig);
-    if (jmxConfig != null) result.put("jmx", jmxConfig);
     m = new LinkedHashMap();
     result.put("requestDispatcher", m);
     m.put("handleSelect", handleSelect);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/SolrCore.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index a6ba2dc..f099452 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -27,7 +27,6 @@ import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Constructor;
-import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
@@ -58,6 +57,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
 
 import com.codahale.metrics.Counter;
+import com.codahale.metrics.MetricRegistry;
 import com.codahale.metrics.Timer;
 import com.google.common.collect.MapMaker;
 import org.apache.commons.io.FileUtils;
@@ -133,7 +133,7 @@ import org.apache.solr.schema.IndexSchemaFactory;
 import org.apache.solr.schema.ManagedIndexSchema;
 import org.apache.solr.schema.SimilarityFactory;
 import org.apache.solr.search.QParserPlugin;
-import org.apache.solr.search.SolrFieldCacheMBean;
+import org.apache.solr.search.SolrFieldCacheBean;
 import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.search.ValueSourceParser;
 import org.apache.solr.search.stats.LocalStatsCache;
@@ -171,7 +171,7 @@ import static org.apache.solr.common.params.CommonParams.PATH;
 /**
  *
  */
-public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closeable {
+public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeable {
 
   public static final String version="1.0";
 
@@ -202,7 +202,7 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
   private final PluginBag<UpdateRequestProcessorFactory> updateProcessors = new PluginBag<>(UpdateRequestProcessorFactory.class, this, true);
   private final Map<String,UpdateRequestProcessorChain> updateProcessorChains;
   private final SolrCoreMetricManager coreMetricManager;
-  private final Map<String, SolrInfoMBean> infoRegistry;
+  private final Map<String, SolrInfoBean> infoRegistry = new ConcurrentHashMap<>();
   private final IndexDeletionPolicyWrapper solrDelPolicy;
   private final SolrSnapshotMetaDataManager snapshotMgr;
   private final DirectoryFactory directoryFactory;
@@ -222,6 +222,12 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
   private Counter newSearcherMaxReachedCounter;
   private Counter newSearcherOtherErrorsCounter;
 
+  private Set<String> metricNames = new HashSet<>();
+
+  public Set<String> getMetricNames() {
+    return metricNames;
+  }
+
   public Date getStartTimeStamp() { return startTime; }
 
   private final Map<IndexReader.CacheKey, IndexFingerprint> perSegmentFingerprintCache = new MapMaker().weakKeys().makeMap();
@@ -448,14 +454,14 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
   }
 
   /**
-   * Returns a Map of name vs SolrInfoMBean objects. The returned map is an instance of
+   * Returns a Map of name vs SolrInfoBean objects. The returned map is an instance of
    * a ConcurrentHashMap and therefore no synchronization is needed for putting, removing
    * or iterating over it.
    *
-   * @return the Info Registry map which contains SolrInfoMBean objects keyed by name
+   * @return the Info Registry map which contains SolrInfoBean objects keyed by name
    * @since solr 1.3
    */
-  public Map<String, SolrInfoMBean> getInfoRegistry() {
+  public Map<String, SolrInfoBean> getInfoRegistry() {
     return infoRegistry;
   }
 
@@ -905,9 +911,12 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
     // initialize searcher-related metrics
     initializeMetrics(metricManager, coreMetricManager.getRegistryName(), null);
 
-    // Initialize JMX
-    this.infoRegistry = initInfoRegistry(name, config);
-    infoRegistry.put("fieldCache", new SolrFieldCacheMBean());
+    SolrFieldCacheBean solrFieldCacheBean = new SolrFieldCacheBean();
+    // this is registered at the CONTAINER level because it's not core-specific - for now we
+    // also register it here for back-compat
+    solrFieldCacheBean.initializeMetrics(metricManager, coreMetricManager.getRegistryName(), "core");
+    infoRegistry.put("fieldCache", solrFieldCacheBean);
+
 
     initSchema(config, schema);
 
@@ -998,15 +1007,9 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
     // from the core.
     resourceLoader.inform(infoRegistry);
 
-    // Allow the directory factory to register MBeans as well
-    for (SolrInfoMBean bean : directoryFactory.offerMBeans()) {
-      log.debug("Registering JMX bean [{}] from directory factory.", bean.getName());
-      // Not worried about concurrency, so no reason to use putIfAbsent
-      if (infoRegistry.containsKey(bean.getName())){
-        log.debug("Ignoring JMX bean [{}] due to name conflict.", bean.getName());
-      } else {
-        infoRegistry.put(bean.getName(), bean);
-      }
+    // Allow the directory factory to report metrics
+    if (directoryFactory instanceof SolrMetricProducer) {
+      ((SolrMetricProducer)directoryFactory).initializeMetrics(metricManager, coreMetricManager.getRegistryName(), "directoryFactory");
     }
 
     // seed version buckets with max from index during core initialization ... requires a searcher!
@@ -1126,34 +1129,46 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
 
   @Override
   public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
-    newSearcherCounter = manager.counter(registry, "new", Category.SEARCHER.toString());
-    newSearcherTimer = manager.timer(registry, "time", Category.SEARCHER.toString(), "new");
-    newSearcherWarmupTimer = manager.timer(registry, "warmup", Category.SEARCHER.toString(), "new");
-    newSearcherMaxReachedCounter = manager.counter(registry, "maxReached", Category.SEARCHER.toString(), "new");
-    newSearcherOtherErrorsCounter = manager.counter(registry, "errors", Category.SEARCHER.toString(), "new");
-
-    manager.registerGauge(registry, () -> name == null ? "(null)" : name, true, "coreName", Category.CORE.toString());
-    manager.registerGauge(registry, () -> startTime, true, "startTime", Category.CORE.toString());
-    manager.registerGauge(registry, () -> getOpenCount(), true, "refCount", Category.CORE.toString());
-    manager.registerGauge(registry, () -> resourceLoader.getInstancePath().toString(), true, "instanceDir", Category.CORE.toString());
-    manager.registerGauge(registry, () -> getIndexDir(), true, "indexDir", Category.CORE.toString());
-    manager.registerGauge(registry, () -> getIndexSize(), true, "sizeInBytes", Category.INDEX.toString());
-    manager.registerGauge(registry, () -> NumberUtils.readableSize(getIndexSize()), true, "size", Category.INDEX.toString());
-    manager.registerGauge(registry, () -> coreDescriptor.getCoreContainer().getCoreNames(this), true, "aliases", Category.CORE.toString());
+    newSearcherCounter = manager.counter(this, registry, "new", Category.SEARCHER.toString());
+    newSearcherTimer = manager.timer(this, registry, "time", Category.SEARCHER.toString(), "new");
+    newSearcherWarmupTimer = manager.timer(this, registry, "warmup", Category.SEARCHER.toString(), "new");
+    newSearcherMaxReachedCounter = manager.counter(this, registry, "maxReached", Category.SEARCHER.toString(), "new");
+    newSearcherOtherErrorsCounter = manager.counter(this, registry, "errors", Category.SEARCHER.toString(), "new");
+
+    manager.registerGauge(this, registry, () -> name == null ? "(null)" : name, true, "coreName", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> startTime, true, "startTime", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> getOpenCount(), true, "refCount", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> resourceLoader.getInstancePath().toString(), true, "instanceDir", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> getIndexDir(), true, "indexDir", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> getIndexSize(), true, "sizeInBytes", Category.INDEX.toString());
+    manager.registerGauge(this, registry, () -> NumberUtils.readableSize(getIndexSize()), true, "size", Category.INDEX.toString());
+    if (coreDescriptor != null && coreDescriptor.getCoreContainer() != null) {
+      manager.registerGauge(this, registry, () -> coreDescriptor.getCoreContainer().getCoreNames(this), true, "aliases", Category.CORE.toString());
+      final CloudDescriptor cd = coreDescriptor.getCloudDescriptor();
+      if (cd != null) {
+        manager.registerGauge(this, registry, () -> {
+          if (cd.getCollectionName() != null) {
+            return cd.getCollectionName();
+          } else {
+            return "_notset_";
+          }
+        }, true, "collection", Category.CORE.toString());
+
+        manager.registerGauge(this, registry, () -> {
+          if (cd.getShardId() != null) {
+            return cd.getShardId();
+          } else {
+            return "_auto_";
+          }
+        }, true, "shard", Category.CORE.toString());
+      }
+    }
+
     // initialize disk total / free metrics
     Path dataDirPath = Paths.get(dataDir);
     File dataDirFile = dataDirPath.toFile();
-    manager.registerGauge(registry, () -> dataDirFile.getTotalSpace(), true, "totalSpace", Category.CORE.toString(), "fs");
-    manager.registerGauge(registry, () -> dataDirFile.getUsableSpace(), true, "usableSpace", Category.CORE.toString(), "fs");
-  }
-
-  private Map<String,SolrInfoMBean> initInfoRegistry(String name, SolrConfig config) {
-    if (config.jmxConfig.enabled) {
-      return new JmxMonitoredMap<String, SolrInfoMBean>(name, coreMetricManager.getRegistryName(), String.valueOf(this.hashCode()), config.jmxConfig);
-    } else  {
-      log.debug("JMX monitoring not detected for core: " + name);
-      return new ConcurrentHashMap<>();
-    }
+    manager.registerGauge(this, registry, () -> dataDirFile.getTotalSpace(), true, "totalSpace", Category.CORE.toString(), "fs");
+    manager.registerGauge(this, registry, () -> dataDirFile.getUsableSpace(), true, "usableSpace", Category.CORE.toString(), "fs");
   }
 
   private void checkVersionFieldExistsInSchema(IndexSchema schema, CoreDescriptor coreDescriptor) {
@@ -2685,6 +2700,9 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
     for (PluginInfo info : pluginInfos) {
       T o = createInitInstance(info,type, type.getSimpleName(), defClassName);
       registry.put(info.name, o);
+      if (o instanceof SolrMetricProducer) {
+        coreMetricManager.registerMetricProducer(type.getSimpleName() + "." + info.name, (SolrMetricProducer)o);
+      }
       if(info.isDefault()){
         def = o;
       }
@@ -2692,6 +2710,12 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
     return def;
   }
 
+  public void initDefaultPlugin(Object plugin, Class type) {
+    if (plugin instanceof SolrMetricProducer) {
+      coreMetricManager.registerMetricProducer(type.getSimpleName() + ".default", (SolrMetricProducer)plugin);
+    }
+  }
+
   /**For a given List of PluginInfo return the instances as a List
    * @param defClassName The default classname if PluginInfo#className == null
    * @return The instances initialized
@@ -2775,15 +2799,10 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
   }
 
   /////////////////////////////////////////////////////////////////////
-  // SolrInfoMBean stuff: Statistics and Module Info
+  // SolrInfoBean stuff: Statistics and Module Info
   /////////////////////////////////////////////////////////////////////
 
   @Override
-  public String getVersion() {
-    return SolrCore.version;
-  }
-
-  @Override
   public String getDescription() {
     return "SolrCore";
   }
@@ -2794,48 +2813,8 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
   }
 
   @Override
-  public String getSource() {
-    return null;
-  }
-
-  @Override
-  public URL[] getDocs() {
-    return null;
-  }
-
-  @Override
-  public NamedList getStatistics() {
-    NamedList<Object> lst = new SimpleOrderedMap<>(8);
-    lst.add("coreName", name==null ? "(null)" : name);
-    lst.add("startTime", startTime);
-    lst.add("refCount", getOpenCount());
-    lst.add("instanceDir", resourceLoader.getInstancePath());
-    lst.add("indexDir", getIndexDir());
-    long size = getIndexSize();
-    lst.add("sizeInBytes", size);
-    lst.add("size", NumberUtils.readableSize(size));
-
-    CoreDescriptor cd = getCoreDescriptor();
-    if (cd != null) {
-      if (null != cd && cd.getCoreContainer() != null) {
-        lst.add("aliases", getCoreDescriptor().getCoreContainer().getCoreNames(this));
-      }
-      CloudDescriptor cloudDesc = cd.getCloudDescriptor();
-      if (cloudDesc != null) {
-        String collection = cloudDesc.getCollectionName();
-        if (collection == null) {
-          collection = "_notset_";
-        }
-        lst.add("collection", collection);
-        String shard = cloudDesc.getShardId();
-        if (shard == null) {
-          shard = "_auto_";
-        }
-        lst.add("shard", shard);
-      }
-    }
-
-    return lst;
+  public MetricRegistry getMetricRegistry() {
+    return coreMetricManager.getRegistry();
   }
 
   public Codec getCodec() {
@@ -2983,11 +2962,11 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
     };
   }
 
-  public void registerInfoBean(String name, SolrInfoMBean solrInfoMBean) {
-    infoRegistry.put(name, solrInfoMBean);
+  public void registerInfoBean(String name, SolrInfoBean solrInfoBean) {
+    infoRegistry.put(name, solrInfoBean);
 
-    if (solrInfoMBean instanceof SolrMetricProducer) {
-      SolrMetricProducer producer = (SolrMetricProducer) solrInfoMBean;
+    if (solrInfoBean instanceof SolrMetricProducer) {
+      SolrMetricProducer producer = (SolrMetricProducer) solrInfoBean;
       coreMetricManager.registerMetricProducer(name, producer);
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/SolrInfoBean.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrInfoBean.java b/solr/core/src/java/org/apache/solr/core/SolrInfoBean.java
new file mode 100644
index 0000000..472b15e
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/core/SolrInfoBean.java
@@ -0,0 +1,95 @@
+/*
+ * 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 java.util.Map;
+import java.util.Set;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.util.stats.MetricUtils;
+
+/**
+ * Interface for getting various ui friendly strings
+ * for use by objects which are 'pluggable' to make server administration
+ * easier.
+ */
+public interface SolrInfoBean {
+
+  /**
+   * Category of Solr component.
+   */
+  enum Category { CONTAINER, ADMIN, CORE, QUERY, UPDATE, CACHE, HIGHLIGHTER, QUERYPARSER, SPELLCHECKER,
+    SEARCHER, REPLICATION, TLOG, INDEX, DIRECTORY, HTTP, OTHER }
+
+  /**
+   * Top-level group of beans or metrics for a subsystem.
+   */
+  enum Group { jvm, jetty, node, core, collection, shard, cluster, overseer }
+
+  /**
+   * Simple common usage name, e.g. BasicQueryHandler,
+   * or fully qualified class name.
+   */
+  String getName();
+  /** Simple one or two line description */
+  String getDescription();
+  /** Category of this component */
+  Category getCategory();
+
+  /** Optionally return a snapshot of metrics that this component reports, or null.
+   * Default implementation requires that both {@link #getMetricNames()} and
+   * {@link #getMetricRegistry()} return non-null values.
+   */
+  default Map<String, Object> getMetricsSnapshot() {
+    if (getMetricRegistry() == null || getMetricNames() == null) {
+      return null;
+    }
+    return MetricUtils.convertMetrics(getMetricRegistry(), getMetricNames());
+  }
+
+  /**
+   * Modifiable set of metric names that this component reports (default is null,
+   * which means none). If not null then this set is used by {@link #registerMetricName(String)}
+   * to capture what metrics names are reported from this component.
+   */
+  default Set<String> getMetricNames() {
+    return null;
+  }
+
+  /**
+   * An instance of {@link MetricRegistry} that this component uses for metrics reporting
+   * (default is null, which means no registry).
+   */
+  default MetricRegistry getMetricRegistry() {
+    return null;
+  }
+
+  /** Register a metric name that this component reports. This method is called by various
+   * metric registration methods in {@link org.apache.solr.metrics.SolrMetricManager} in order
+   * to capture what metric names are reported from this component (which in turn is called
+   * from {@link org.apache.solr.metrics.SolrMetricProducer#initializeMetrics(SolrMetricManager, String, String)}).
+   * <p>Default implementation registers all metrics added by a component. Implementations may
+   * override this to avoid reporting some or all metrics returned by {@link #getMetricsSnapshot()}</p>
+   */
+  default void registerMetricName(String name) {
+    Set<String> names = getMetricNames();
+    if (names != null) {
+      names.add(name);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/SolrInfoMBean.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrInfoMBean.java b/solr/core/src/java/org/apache/solr/core/SolrInfoMBean.java
deleted file mode 100644
index 63bdef0..0000000
--- a/solr/core/src/java/org/apache/solr/core/SolrInfoMBean.java
+++ /dev/null
@@ -1,76 +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 java.net.URL;
-
-import org.apache.solr.common.util.NamedList;
-
-/**
- * MBean interface for getting various ui friendly strings and URLs
- * for use by objects which are 'pluggable' to make server administration
- * easier.
- *
- *
- */
-public interface SolrInfoMBean {
-
-  /**
-   * Category of Solr component.
-   */
-  enum Category { CONTAINER, ADMIN, CORE, QUERY, UPDATE, CACHE, HIGHLIGHTER, QUERYPARSER, SPELLCHECKER,
-    SEARCHER, REPLICATION, TLOG, INDEX, DIRECTORY, HTTP, OTHER }
-
-  /**
-   * Top-level group of beans or metrics for a subsystem.
-   */
-  enum Group { jvm, jetty, node, core, collection, shard, cluster, overseer }
-
-  /**
-   * Simple common usage name, e.g. BasicQueryHandler,
-   * or fully qualified clas name.
-   */
-  public String getName();
-  /** Simple common usage version, e.g. 2.0 */
-  public String getVersion();
-  /** Simple one or two line description */
-  public String getDescription();
-  /** Purpose of this Class */
-  public Category getCategory();
-  /** CVS Source, SVN Source, etc */
-  public String getSource();
-  /**
-   * Documentation URL list.
-   *
-   * <p>
-   * Suggested documentation URLs: Homepage for sponsoring project,
-   * FAQ on class usage, Design doc for class, Wiki, bug reporting URL, etc...
-   * </p>
-   */
-  public URL[] getDocs();
-  /**
-   * Any statistics this instance would like to be publicly available via
-   * the Solr Administration interface.
-   *
-   * <p>
-   * Any Object type may be stored in the list, but only the
-   * <code>toString()</code> representation will be used.
-   * </p>
-   */
-  public NamedList getStatistics();
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/SolrInfoMBeanWrapper.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrInfoMBeanWrapper.java b/solr/core/src/java/org/apache/solr/core/SolrInfoMBeanWrapper.java
deleted file mode 100644
index 534b884..0000000
--- a/solr/core/src/java/org/apache/solr/core/SolrInfoMBeanWrapper.java
+++ /dev/null
@@ -1,62 +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 java.net.URL;
-
-import org.apache.solr.common.util.NamedList;
-
-/**
- * Wraps a {@link SolrInfoMBean}.
- */
-public class SolrInfoMBeanWrapper implements SolrInfoMBean {
-  private final SolrInfoMBean mbean;
-
-  public SolrInfoMBeanWrapper(SolrInfoMBean mbean) {
-    this.mbean = mbean;
-  }
-
-  /** {@inheritDoc} */
-  @Override
-  public String getName() { return mbean.getName(); }
-
-  /** {@inheritDoc} */
-  @Override
-  public String getVersion() { return mbean.getVersion(); }
-
-  /** {@inheritDoc} */
-  @Override
-  public String getDescription() { return mbean.getDescription(); }
-
-  /** {@inheritDoc} */
-  @Override
-  public Category getCategory() { return mbean.getCategory(); }
-
-  /** {@inheritDoc} */
-  @Override
-  public String getSource() { return mbean.getSource(); }
-
-  /** {@inheritDoc} */
-  @Override
-  public URL[] getDocs() { return mbean.getDocs(); }
-
-  /** {@inheritDoc} */
-  @Override
-  public NamedList getStatistics() { return mbean.getStatistics(); }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e30cc70f/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index d310ff2..2e679cf 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -100,7 +100,7 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
   private String dataDir;
   
   private final List<SolrCoreAware> waitingForCore = Collections.synchronizedList(new ArrayList<SolrCoreAware>());
-  private final List<SolrInfoMBean> infoMBeans = Collections.synchronizedList(new ArrayList<SolrInfoMBean>());
+  private final List<SolrInfoBean> infoMBeans = Collections.synchronizedList(new ArrayList<SolrInfoBean>());
   private final List<ResourceLoaderAware> waitingForResources = Collections.synchronizedList(new ArrayList<ResourceLoaderAware>());
   private static final Charset UTF_8 = StandardCharsets.UTF_8;
 
@@ -664,9 +664,9 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
         assertAwareCompatibility( ResourceLoaderAware.class, obj );
         waitingForResources.add( (ResourceLoaderAware)obj );
       }
-      if (obj instanceof SolrInfoMBean){
+      if (obj instanceof SolrInfoBean){
         //TODO: Assert here?
-        infoMBeans.add((SolrInfoMBean) obj);
+        infoMBeans.add((SolrInfoBean) obj);
       }
     }
 
@@ -722,21 +722,21 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
   }
 
   /**
-   * Register any {@link org.apache.solr.core.SolrInfoMBean}s
+   * Register any {@link SolrInfoBean}s
    * @param infoRegistry The Info Registry
    */
-  public void inform(Map<String, SolrInfoMBean> infoRegistry) {
+  public void inform(Map<String, SolrInfoBean> infoRegistry) {
     // this can currently happen concurrently with requests starting and lazy components
     // loading.  Make sure infoMBeans doesn't change.
 
-    SolrInfoMBean[] arr;
+    SolrInfoBean[] arr;
     synchronized (infoMBeans) {
-      arr = infoMBeans.toArray(new SolrInfoMBean[infoMBeans.size()]);
+      arr = infoMBeans.toArray(new SolrInfoBean[infoMBeans.size()]);
       waitingForResources.clear();
     }
 
 
-    for (SolrInfoMBean bean : arr) {
+    for (SolrInfoBean bean : arr) {
       // Too slow? I suspect not, but we may need
       // to start tracking this in a Set.
       if (!infoRegistry.containsValue(bean)) {
@@ -879,7 +879,7 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
   public void close() throws IOException {
     IOUtils.close(classLoader);
   }
-  public List<SolrInfoMBean> getInfoMBeans(){
+  public List<SolrInfoBean> getInfoMBeans(){
     return Collections.unmodifiableList(infoMBeans);
   }