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 2018/04/03 09:40:57 UTC

[1/2] lucene-solr:branch_7x: SOLR-11882: SolrMetric registries retained references to SolrCores when closed.

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_7x 974c03a6c -> 483914b6a


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingHttpClientConnectionManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingHttpClientConnectionManager.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingHttpClientConnectionManager.java
index 58ec69e..398ab8b 100644
--- a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingHttpClientConnectionManager.java
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingHttpClientConnectionManager.java
@@ -29,16 +29,25 @@ import org.apache.solr.metrics.SolrMetricProducer;
  */
 public class InstrumentedPoolingHttpClientConnectionManager extends PoolingHttpClientConnectionManager implements SolrMetricProducer {
 
+  private SolrMetricManager metricManager;
+  private String registryName;
+
   public InstrumentedPoolingHttpClientConnectionManager(Registry<ConnectionSocketFactory> socketFactoryRegistry) {
     super(socketFactoryRegistry);
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
-    manager.registerGauge(null, registry, () -> getTotalStats().getAvailable(), true, SolrMetricManager.mkName("availableConnections", scope));
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registry;
+    manager.registerGauge(null, registry, () -> getTotalStats().getAvailable(),
+        tag, true, SolrMetricManager.mkName("availableConnections", scope));
     // this acquires a lock on the connection pool; remove if contention sucks
-    manager.registerGauge(null, registry, () -> getTotalStats().getLeased(), true, SolrMetricManager.mkName("leasedConnections", scope));
-    manager.registerGauge(null, registry, () -> getTotalStats().getMax(), true, SolrMetricManager.mkName("maxConnections", scope));
-    manager.registerGauge(null, registry, () -> getTotalStats().getPending(), true, SolrMetricManager.mkName("pendingConnections", scope));
+    manager.registerGauge(null, registry, () -> getTotalStats().getLeased(),
+        tag, true, SolrMetricManager.mkName("leasedConnections", scope));
+    manager.registerGauge(null, registry, () -> getTotalStats().getMax(),
+        tag, true, SolrMetricManager.mkName("maxConnections", scope));
+    manager.registerGauge(null, registry, () -> getTotalStats().getPending(),
+        tag, true, SolrMetricManager.mkName("pendingConnections", scope));
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/CursorPagingTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/CursorPagingTest.java b/solr/core/src/test/org/apache/solr/CursorPagingTest.java
index c1b9935..257b846 100644
--- a/solr/core/src/test/org/apache/solr/CursorPagingTest.java
+++ b/solr/core/src/test/org/apache/solr/CursorPagingTest.java
@@ -32,6 +32,7 @@ import static org.apache.solr.common.params.CursorMarkParams.CURSOR_MARK_START;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.CursorMark; //jdoc
 import org.noggit.ObjectBuilder;
@@ -524,10 +525,10 @@ public class CursorPagingTest extends SolrTestCaseJ4 {
     final Collection<String> allFieldNames = getAllSortFieldNames();
 
     final MetricsMap filterCacheStats =
-        (MetricsMap)h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.filterCache");
+        (MetricsMap)((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.filterCache")).getGauge();
     assertNotNull(filterCacheStats);
     final MetricsMap queryCacheStats =
-        (MetricsMap)h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache");
+        (MetricsMap)((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache")).getGauge();
     assertNotNull(queryCacheStats);
 
     final long preQcIn = (Long) queryCacheStats.getValue().get("inserts");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java b/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
index 72fdf25..8220fd1 100644
--- a/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
+++ b/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
@@ -65,7 +65,7 @@ public class SolrInfoBeanTest extends SolrTestCaseJ4
         try {
           SolrInfoBean info = (SolrInfoBean)clazz.newInstance();
           if (info instanceof SolrMetricProducer) {
-            ((SolrMetricProducer)info).initializeMetrics(metricManager, registry, scope);
+            ((SolrMetricProducer)info).initializeMetrics(metricManager, registry, "foo", scope);
           }
           
           //System.out.println( info.getClass() );

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java b/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java
index aa42664..ca61350 100644
--- a/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java
+++ b/solr/core/src/test/org/apache/solr/core/ExitableDirectoryReaderTest.java
@@ -20,6 +20,7 @@ import java.util.Map;
 
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.response.SolrQueryResponse;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -88,10 +89,10 @@ public class ExitableDirectoryReaderTest extends SolrTestCaseJ4 {
   public void testCacheAssumptions() throws Exception {
     String fq= "name:d*";
     SolrCore core = h.getCore();
-    MetricsMap filterCacheStats = (MetricsMap)core.getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.filterCache");
+    MetricsMap filterCacheStats = (MetricsMap)((SolrMetricManager.GaugeWrapper)core.getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.filterCache")).getGauge();
     long fqInserts = (long) filterCacheStats.getValue().get("inserts");
 
-    MetricsMap queryCacheStats = (MetricsMap)core.getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache");
+    MetricsMap queryCacheStats = (MetricsMap)((SolrMetricManager.GaugeWrapper)core.getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache")).getGauge();
     long qrInserts = (long) queryCacheStats.getValue().get("inserts");
 
     // This gets 0 docs back. Use 10000 instead of 1 for timeAllowed and it gets 100 back and the for loop below
@@ -130,7 +131,7 @@ public class ExitableDirectoryReaderTest extends SolrTestCaseJ4 {
   public void testQueryResults() throws Exception {
     String q = "name:e*";
     SolrCore core = h.getCore();
-    MetricsMap queryCacheStats = (MetricsMap)core.getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache");
+    MetricsMap queryCacheStats = (MetricsMap)((SolrMetricManager.GaugeWrapper)core.getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache")).getGauge();
     Map<String,Object> nl = queryCacheStats.getValue();
     long inserts = (long) nl.get("inserts");
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java b/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
index ed523c4..51f67fc 100644
--- a/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
@@ -191,10 +191,10 @@ public class HdfsDirectoryFactoryTest extends SolrTestCaseJ4 {
     props.put(HdfsDirectoryFactory.NRTCACHINGDIRECTORY_ENABLE, "false");
     props.put(HdfsDirectoryFactory.LOCALITYMETRICS_ENABLED, "true");
     factory.init(new NamedList<>(props));
-    factory.initializeMetrics(metricManager, registry, scope);
+    factory.initializeMetrics(metricManager, registry, "foo", scope);
 
     // get the metrics map for the locality bean
-    MetricsMap metrics = (MetricsMap)metricManager.registry(registry).getMetrics().get("OTHER." + scope + ".hdfsLocality");
+    MetricsMap metrics = (MetricsMap)((SolrMetricManager.GaugeWrapper)metricManager.registry(registry).getMetrics().get("OTHER." + scope + ".hdfsLocality")).getGauge();
     // We haven't done anything, so there should be no data
     Map<String,Object> statistics = metrics.getValue();
     assertEquals("Saw bytes that were not written: " + statistics.get(HdfsLocalityReporter.LOCALITY_BYTES_TOTAL), 0l,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/core/MockInfoBean.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/MockInfoBean.java b/solr/core/src/test/org/apache/solr/core/MockInfoBean.java
index 8ae3552..806c6b8 100644
--- a/solr/core/src/test/org/apache/solr/core/MockInfoBean.java
+++ b/solr/core/src/test/org/apache/solr/core/MockInfoBean.java
@@ -27,6 +27,8 @@ import org.apache.solr.metrics.SolrMetricProducer;
 class MockInfoBean implements SolrInfoBean, SolrMetricProducer {
   Set<String> metricNames = ConcurrentHashMap.newKeySet();
   MetricRegistry registry;
+  SolrMetricManager metricManager;
+  String registryName;
 
   @Override
   public String getName() {
@@ -54,7 +56,9 @@ class MockInfoBean implements SolrInfoBean, SolrMetricProducer {
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
     registry = manager.registry(registryName);
     MetricsMap metricsMap = new MetricsMap((detailed, map) -> {
       map.put("Integer", 123);
@@ -66,6 +70,6 @@ class MockInfoBean implements SolrInfoBean, SolrMetricProducer {
       map.put("String","testing");
       map.put("Object", new Object());
     });
-    manager.registerGauge(this, registryName, metricsMap, true, getClass().getSimpleName(), getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, metricsMap, tag, true, getClass().getSimpleName(), getCategory().toString(), scope);
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/MockQuerySenderListenerReqHandler.java b/solr/core/src/test/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
index bcf6e9f..0b0c7e5 100644
--- a/solr/core/src/test/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
+++ b/solr/core/src/test/org/apache/solr/core/MockQuerySenderListenerReqHandler.java
@@ -42,9 +42,9 @@ public class MockQuerySenderListenerReqHandler extends RequestHandlerBase {
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
-    super.initializeMetrics(manager, registryName, scope);
-    manager.registerGauge(this, registryName, () -> initCounter.intValue(), true, "initCount", getCategory().toString(), scope);
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    super.initializeMetrics(manager, registryName, tag, scope);
+    manager.registerGauge(this, registryName, () -> initCounter.intValue(), tag, true, "initCount", getCategory().toString(), scope);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java b/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java
index 36f41e2..3509f39 100644
--- a/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java
+++ b/solr/core/src/test/org/apache/solr/core/TestJmxIntegration.java
@@ -177,7 +177,7 @@ public class TestJmxIntegration extends SolrTestCaseJ4 {
     SolrMetricManager mgr = h.getCoreContainer().getMetricManager();
     String registryName = h.getCore().getCoreMetricManager().getRegistryName();
     String coreName = h.getCore().getName();
-    String coreHashCode = String.valueOf(h.getCore().hashCode());
+    String coreHashCode = Integer.toHexString(h.getCore().hashCode());
     Map<String, SolrMetricReporter> reporters = mgr.getReporters(registryName);
     // take first JMX reporter
     SolrJmxReporter reporter = null;
@@ -209,7 +209,7 @@ public class TestJmxIntegration extends SolrTestCaseJ4 {
     assertQ(req("q", "*:*"), "//result[@numFound='0']");
 
     reporters = mgr.getReporters(registryName);
-    coreHashCode = String.valueOf(h.getCore().hashCode());
+    coreHashCode = Integer.toHexString(h.getCore().hashCode());
     // take first JMX reporter
     reporter = null;
     for (Map.Entry<String, SolrMetricReporter> e : reporters.entrySet()) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java b/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
index d40bc63..d43f8ca 100644
--- a/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/JvmMetricsTest.java
@@ -103,7 +103,7 @@ public class JvmMetricsTest extends SolrJettyTestBase {
     }
     SolrMetricManager metricManager = jetty.getCoreContainer().getMetricManager();
     Map<String,Metric> metrics = metricManager.registry("solr.jvm").getMetrics();
-    MetricsMap map = (MetricsMap)metrics.get("system.properties");
+    MetricsMap map = (MetricsMap)((SolrMetricManager.GaugeWrapper)metrics.get("system.properties")).getGauge();
     assertNotNull(map);
     Map<String,Object> values = map.getValue();
     System.getProperties().forEach((k, v) -> {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
index f036121..c6b0fa4 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricManagerTest.java
@@ -118,7 +118,7 @@ public class SolrCoreMetricManagerTest extends SolrTestCaseJ4 {
 
     try {
       metricManager.loadReporter(coreMetricManager.getRegistryName(), coreMetricManager.getCore(),
-          pluginInfo, String.valueOf(coreMetricManager.getCore().hashCode()));
+          pluginInfo, coreMetricManager.getTag());
       assertNotNull(pluginInfo);
       Map<String, SolrMetricReporter> reporters = metricManager.getReporters(coreMetricManager.getRegistryName());
       assertTrue("reporters.size should be > 0, but was + " + reporters.size(), reporters.size() > 0);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java
----------------------------------------------------------------------
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 ed9e01a..9e15acf 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricManagerTest.java
@@ -62,10 +62,10 @@ public class SolrMetricManagerTest extends SolrTestCaseJ4 {
     String toName = "to-" + TestUtil.randomSimpleString(r, 1, 10);
     // register test metrics
     for (Map.Entry<String, Counter> entry : metrics1.entrySet()) {
-      metricManager.register(null, fromName, entry.getValue(), false, entry.getKey(), "metrics1");
+      metricManager.registerMetric(null, fromName, entry.getValue(), false, entry.getKey(), "metrics1");
     }
     for (Map.Entry<String, Counter> entry : metrics2.entrySet()) {
-      metricManager.register(null, toName, entry.getValue(), false, entry.getKey(), "metrics2");
+      metricManager.registerMetric(null, toName, entry.getValue(), false, entry.getKey(), "metrics2");
     }
     assertEquals(metrics1.size(), metricManager.registry(fromName).getMetrics().size());
     assertEquals(metrics2.size(), metricManager.registry(toName).getMetrics().size());
@@ -125,13 +125,13 @@ public class SolrMetricManagerTest extends SolrTestCaseJ4 {
     String registryName = TestUtil.randomSimpleString(r, 1, 10);
 
     for (Map.Entry<String, Counter> entry : metrics.entrySet()) {
-      metricManager.register(null, registryName, entry.getValue(), false, entry.getKey(), "foo", "bar");
+      metricManager.registerMetric(null, registryName, entry.getValue(), false, entry.getKey(), "foo", "bar");
     }
     for (Map.Entry<String, Counter> entry : metrics.entrySet()) {
-      metricManager.register(null, registryName, entry.getValue(), false, entry.getKey(), "foo", "baz");
+      metricManager.registerMetric(null, registryName, entry.getValue(), false, entry.getKey(), "foo", "baz");
     }
     for (Map.Entry<String, Counter> entry : metrics.entrySet()) {
-      metricManager.register(null, registryName, entry.getValue(), false, entry.getKey(), "foo");
+      metricManager.registerMetric(null, registryName, entry.getValue(), false, entry.getKey(), "foo");
     }
 
     assertEquals(metrics.size() * 3, metricManager.registry(registryName).getMetrics().size());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java
index c506c1d..c4eae43 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricTestUtils.java
@@ -78,7 +78,7 @@ public final class SolrMetricTestUtils {
   public static SolrMetricProducer getProducerOf(SolrMetricManager metricManager, SolrInfoBean.Category category, String scope, Map<String, Counter> metrics) {
     return new SolrMetricProducer() {
       @Override
-      public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+      public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
         if (category == null) {
           throw new IllegalArgumentException("null category");
         }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java b/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java
index 72fc9ce..9ead65d 100644
--- a/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java
+++ b/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java
@@ -44,7 +44,7 @@ public class TestFastLRUCache extends LuceneTestCase {
 
   public void testPercentageAutowarm() throws IOException {
     FastLRUCache<Object, Object> fastCache = new FastLRUCache<>();
-    fastCache.initializeMetrics(metricManager, registry, scope);
+    fastCache.initializeMetrics(metricManager, registry, "foo", scope);
     MetricsMap metrics = fastCache.getMetricsMap();
     Map<String, String> params = new HashMap<>();
     params.put("size", "100");
@@ -64,7 +64,7 @@ public class TestFastLRUCache extends LuceneTestCase {
     assertEquals(101L, nl.get("inserts"));
     assertEquals(null, fastCache.get(1));  // first item put in should be the first out
     FastLRUCache<Object, Object> fastCacheNew = new FastLRUCache<>();
-    fastCacheNew.initializeMetrics(metricManager, registry, scope);
+    fastCacheNew.initializeMetrics(metricManager, registry, "foo", scope);
     metrics = fastCacheNew.getMetricsMap();
     fastCacheNew.init(params, o, cr);
     fastCacheNew.warm(null, fastCache);
@@ -94,7 +94,7 @@ public class TestFastLRUCache extends LuceneTestCase {
   
   private void doTestPercentageAutowarm(int limit, int percentage, int[] hits, int[]misses) {
     FastLRUCache<Object, Object> fastCache = new FastLRUCache<>();
-    fastCache.initializeMetrics(metricManager, registry, scope);
+    fastCache.initializeMetrics(metricManager, registry, "foo", scope);
     Map<String, String> params = new HashMap<>();
     params.put("size", String.valueOf(limit));
     params.put("initialSize", "10");
@@ -107,7 +107,7 @@ public class TestFastLRUCache extends LuceneTestCase {
     }
 
     FastLRUCache<Object, Object> fastCacheNew = new FastLRUCache<>();
-    fastCacheNew.initializeMetrics(metricManager, registry, scope);
+    fastCacheNew.initializeMetrics(metricManager, registry, "foo", scope);
     fastCacheNew.init(params, o, cr);
     fastCacheNew.warm(null, fastCache);
     fastCacheNew.setState(SolrCache.State.LIVE);
@@ -128,7 +128,7 @@ public class TestFastLRUCache extends LuceneTestCase {
   
   public void testNoAutowarm() throws IOException {
     FastLRUCache<Object, Object> fastCache = new FastLRUCache<>();
-    fastCache.initializeMetrics(metricManager, registry, scope);
+    fastCache.initializeMetrics(metricManager, registry, "foo", scope);
     Map<String, String> params = new HashMap<>();
     params.put("size", "100");
     params.put("initialSize", "10");
@@ -188,7 +188,7 @@ public class TestFastLRUCache extends LuceneTestCase {
   
   public void testSimple() throws IOException {
     FastLRUCache sc = new FastLRUCache();
-    sc.initializeMetrics(metricManager, registry, scope);
+    sc.initializeMetrics(metricManager, registry, "foo", scope);
     Map l = new HashMap();
     l.put("size", "100");
     l.put("initialSize", "10");
@@ -211,7 +211,7 @@ public class TestFastLRUCache extends LuceneTestCase {
 
 
     FastLRUCache scNew = new FastLRUCache();
-    scNew.initializeMetrics(metricManager, registry, scope);
+    scNew.initializeMetrics(metricManager, registry, "foo", scope);
     scNew.init(l, o, cr);
     scNew.warm(null, sc);
     scNew.setState(SolrCache.State.LIVE);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/TestLFUCache.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestLFUCache.java b/solr/core/src/test/org/apache/solr/search/TestLFUCache.java
index 8207522..84aab1b 100644
--- a/solr/core/src/test/org/apache/solr/search/TestLFUCache.java
+++ b/solr/core/src/test/org/apache/solr/search/TestLFUCache.java
@@ -140,9 +140,9 @@ public class TestLFUCache extends SolrTestCaseJ4 {
     LFUCache lfuCache = new LFUCache();
     LFUCache newLFUCache = new LFUCache();
     LFUCache noWarmLFUCache = new LFUCache();
-    lfuCache.initializeMetrics(metricManager, registry, scope + ".lfuCache");
-    newLFUCache.initializeMetrics(metricManager, registry, scope + ".newLFUCache");
-    noWarmLFUCache.initializeMetrics(metricManager, registry, scope + ".noWarmLFUCache");
+    lfuCache.initializeMetrics(metricManager, registry, "foo", scope + ".lfuCache");
+    newLFUCache.initializeMetrics(metricManager, registry, "foo", scope + ".newLFUCache");
+    noWarmLFUCache.initializeMetrics(metricManager, registry, "foo", scope + ".noWarmLFUCache");
     try {
       Map params = new HashMap();
       params.put("size", "100");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/TestLRUCache.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestLRUCache.java b/solr/core/src/test/org/apache/solr/search/TestLRUCache.java
index fa34911..3bec6df 100644
--- a/solr/core/src/test/org/apache/solr/search/TestLRUCache.java
+++ b/solr/core/src/test/org/apache/solr/search/TestLRUCache.java
@@ -101,7 +101,7 @@ public class TestLRUCache extends LuceneTestCase {
   @SuppressWarnings("unchecked")
   public void testNoAutowarm() throws IOException {
     LRUCache<Object, Object> lruCache = new LRUCache<>();
-    lruCache.initializeMetrics(metricManager, registry, scope);
+    lruCache.initializeMetrics(metricManager, registry, "foo", scope);
     Map<String, String> params = new HashMap<>();
     params.put("size", "100");
     params.put("initialSize", "10");
@@ -131,7 +131,7 @@ public class TestLRUCache extends LuceneTestCase {
 
   public void testMaxRamSize() throws Exception {
     LRUCache<String, Accountable> accountableLRUCache = new LRUCache<>();
-    accountableLRUCache.initializeMetrics(metricManager, registry, scope);
+    accountableLRUCache.initializeMetrics(metricManager, registry, "foo", scope);
     Map<String, String> params = new HashMap<>();
     params.put("size", "5");
     params.put("maxRamMB", "1");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java b/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
index 93673d2..129516e 100644
--- a/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
@@ -22,6 +22,7 @@ import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -382,7 +383,7 @@ public class TestReRankQParserPlugin extends SolrTestCaseJ4 {
         "//result/doc[5]/str[@name='id'][.='2']"
     );
 
-    MetricsMap metrics = (MetricsMap)h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache");
+    MetricsMap metrics = (MetricsMap)((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.queryResultCache")).getGauge();
     Map<String,Object> stats = metrics.getValue();
 
     long inserts = (Long) stats.get("inserts");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
index 78d569a..854e9c7 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
@@ -32,6 +32,7 @@ import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.FacetParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.util.SpatialUtils;
 import org.apache.solr.util.TestUtils;
@@ -266,7 +267,7 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
 
     // The tricky thing is verifying the cache works correctly...
 
-    MetricsMap cacheMetrics = (MetricsMap) h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.perSegSpatialFieldCache_" + fieldName);
+    MetricsMap cacheMetrics = (MetricsMap) ((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.perSegSpatialFieldCache_" + fieldName)).getGauge();
     assertEquals("1", cacheMetrics.getValue().get("cumulative_inserts").toString());
     assertEquals("0", cacheMetrics.getValue().get("cumulative_hits").toString());
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/TestSolrFieldCacheBean.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrFieldCacheBean.java b/solr/core/src/test/org/apache/solr/search/TestSolrFieldCacheBean.java
index 3ae9c47..d0ace4b 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrFieldCacheBean.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrFieldCacheBean.java
@@ -74,8 +74,8 @@ public class TestSolrFieldCacheBean extends SolrTestCaseJ4 {
     Random r = random();
     String registryName = TestUtil.randomSimpleString(r, 1, 10);
     SolrMetricManager metricManager = h.getCoreContainer().getMetricManager();
-    mbean.initializeMetrics(metricManager, registryName, null);
-    MetricsMap metricsMap = (MetricsMap)metricManager.registry(registryName).getMetrics().get("CACHE.fieldCache");
+    mbean.initializeMetrics(metricManager, registryName, "foo", null);
+    MetricsMap metricsMap = (MetricsMap)((SolrMetricManager.GaugeWrapper)metricManager.registry(registryName).getMetrics().get("CACHE.fieldCache")).getGauge();
     Map<String, Object> metrics = checkJmx ? metricsMap.getValue(true) : metricsMap.getValue();
     assertTrue(((Number)metrics.get("entries_count")).longValue() > 0);
     assertNotNull(metrics.get("total_size"));
@@ -87,8 +87,8 @@ public class TestSolrFieldCacheBean extends SolrTestCaseJ4 {
     Random r = random();
     String registryName = TestUtil.randomSimpleString(r, 1, 10);
     SolrMetricManager metricManager = h.getCoreContainer().getMetricManager();
-    mbean.initializeMetrics(metricManager, registryName, null);
-    MetricsMap metricsMap = (MetricsMap)metricManager.registry(registryName).getMetrics().get("CACHE.fieldCache");
+    mbean.initializeMetrics(metricManager, registryName, "foo", null);
+    MetricsMap metricsMap = (MetricsMap)((SolrMetricManager.GaugeWrapper)metricManager.registry(registryName).getMetrics().get("CACHE.fieldCache")).getGauge();
     Map<String, Object> metrics = checkJmx ? metricsMap.getValue(true) : metricsMap.getValue();
     assertTrue(((Number)metrics.get("entries_count")).longValue() > 0);
     assertNull(metrics.get("total_size"));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
index 9008595..fda5f14 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
@@ -38,6 +38,7 @@ import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.metrics.MetricsMap;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.parser.QueryParser;
 import org.apache.solr.query.FilterQuery;
 import org.apache.solr.request.SolrQueryRequest;
@@ -421,11 +422,11 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
     assertU(commit());  // arg... commit no longer "commits" unless there has been a change.
 
 
-    final MetricsMap filterCacheStats = (MetricsMap)h.getCore().getCoreMetricManager().getRegistry()
-        .getMetrics().get("CACHE.searcher.filterCache");
+    final MetricsMap filterCacheStats = (MetricsMap)((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry()
+        .getMetrics().get("CACHE.searcher.filterCache")).getGauge();
     assertNotNull(filterCacheStats);
-    final MetricsMap queryCacheStats = (MetricsMap)h.getCore().getCoreMetricManager().getRegistry()
-        .getMetrics().get("CACHE.searcher.queryResultCache");
+    final MetricsMap queryCacheStats = (MetricsMap)((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry()
+        .getMetrics().get("CACHE.searcher.queryResultCache")).getGauge();
 
     assertNotNull(queryCacheStats);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
index 6713af7..97101f1 100644
--- a/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
+++ b/solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
@@ -31,6 +31,7 @@ import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.util.BaseTestHarness;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -289,10 +290,10 @@ public class BJQParserTest extends SolrTestCaseJ4 {
   @Test
   public void testCacheHit() throws IOException {
 
-    MetricsMap parentFilterCache = (MetricsMap)h.getCore().getCoreMetricManager().getRegistry()
-        .getMetrics().get("CACHE.searcher.perSegFilter");
-    MetricsMap filterCache = (MetricsMap)h.getCore().getCoreMetricManager().getRegistry()
-        .getMetrics().get("CACHE.searcher.filterCache");
+    MetricsMap parentFilterCache = (MetricsMap)((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry()
+        .getMetrics().get("CACHE.searcher.perSegFilter")).getGauge();
+    MetricsMap filterCache = (MetricsMap)((SolrMetricManager.GaugeWrapper)h.getCore().getCoreMetricManager().getRegistry()
+        .getMetrics().get("CACHE.searcher.filterCache")).getGauge();
 
 
     Map<String,Object> parentsBefore = parentFilterCache.getValue();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java
index b9a2e78..8ce6a27 100644
--- a/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java
+++ b/solr/core/src/test/org/apache/solr/search/join/TestScoreJoinQPScore.java
@@ -31,6 +31,7 @@ import org.apache.lucene.search.join.ScoreMode;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.response.SolrQueryResponse;
@@ -202,7 +203,7 @@ public class TestScoreJoinQPScore extends SolrTestCaseJ4 {
 
     Map<String, Metric> metrics = h.getCoreContainer().getMetricManager().registry(h.getCore().getCoreMetricManager().getRegistryName()).getMetrics();
 
-    MetricsMap mm = (MetricsMap)metrics.get("CACHE.searcher.queryResultCache");
+    MetricsMap mm = (MetricsMap)((SolrMetricManager.GaugeWrapper)metrics.get("CACHE.searcher.queryResultCache")).getGauge();
     {
       Map<String,Object> statPre = mm.getValue();
       h.query(req("q", "{!join from=movieId_s to=id score=Avg}title:first", "fl", "id", "omitHeader", "true"));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/test/org/apache/solr/store/blockcache/BufferStoreTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/store/blockcache/BufferStoreTest.java b/solr/core/src/test/org/apache/solr/store/blockcache/BufferStoreTest.java
index 534793f..228f5a3 100644
--- a/solr/core/src/test/org/apache/solr/store/blockcache/BufferStoreTest.java
+++ b/solr/core/src/test/org/apache/solr/store/blockcache/BufferStoreTest.java
@@ -40,8 +40,8 @@ public class BufferStoreTest extends LuceneTestCase {
     SolrMetricManager metricManager = new SolrMetricManager();
     String registry = TestUtil.randomSimpleString(random(), 2, 10);
     String scope = TestUtil.randomSimpleString(random(), 2, 10);
-    metrics.initializeMetrics(metricManager, registry, scope);
-    metricsMap = (MetricsMap) metricManager.registry(registry).getMetrics().get("CACHE." + scope + ".hdfsBlockCache");
+    metrics.initializeMetrics(metricManager, registry, "foo", scope);
+    metricsMap = (MetricsMap) ((SolrMetricManager.GaugeWrapper)metricManager.registry(registry).getMetrics().get("CACHE." + scope + ".hdfsBlockCache")).getGauge();
     BufferStore.initNewBuffer(blockSize, blockSize, metrics);
     store = BufferStore.instance(blockSize);
   }


[2/2] lucene-solr:branch_7x: SOLR-11882: SolrMetric registries retained references to SolrCores when closed.

Posted by ab...@apache.org.
SOLR-11882: SolrMetric registries retained references to SolrCores when closed.


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

Branch: refs/heads/branch_7x
Commit: 483914b6a4c5aaa163625169066e8c6bb3942566
Parents: 974c03a
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Tue Apr 3 10:40:52 2018 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Tue Apr 3 10:41:38 2018 +0200

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  6 ++
 .../handler/dataimport/DataImportHandler.java   |  6 +-
 .../org/apache/solr/core/CoreContainer.java     | 45 ++++++++-------
 .../apache/solr/core/HdfsDirectoryFactory.java  |  8 +--
 .../src/java/org/apache/solr/core/SolrCore.java | 41 ++++++++------
 .../java/org/apache/solr/core/SolrInfoBean.java |  2 +-
 .../apache/solr/handler/ReplicationHandler.java | 44 +++++++--------
 .../apache/solr/handler/RequestHandlerBase.java | 12 ++--
 .../solr/handler/admin/CoreAdminHandler.java    |  4 +-
 .../component/HttpShardHandlerFactory.java      |  9 ++-
 .../solr/handler/component/SearchComponent.java |  2 +-
 .../handler/component/SuggestComponent.java     | 11 +++-
 .../solr/highlight/HighlightingPluginBase.java  |  6 +-
 .../solr/metrics/SolrCoreMetricManager.java     |  7 ++-
 .../apache/solr/metrics/SolrMetricManager.java  | 58 ++++++++++++++++++--
 .../apache/solr/metrics/SolrMetricProducer.java | 29 +++++++++-
 .../metrics/reporters/solr/SolrReporter.java    |  2 +-
 .../org/apache/solr/search/FastLRUCache.java    |  9 ++-
 .../java/org/apache/solr/search/LFUCache.java   |  8 ++-
 .../java/org/apache/solr/search/LRUCache.java   | 10 +++-
 .../apache/solr/search/SolrFieldCacheBean.java  |  4 +-
 .../apache/solr/search/SolrIndexSearcher.java   | 37 +++++++------
 .../apache/solr/servlet/SolrDispatchFilter.java | 26 ++++++---
 .../apache/solr/store/blockcache/Metrics.java   |  8 ++-
 .../solr/store/hdfs/HdfsLocalityReporter.java   |  8 ++-
 .../solr/update/DirectUpdateHandler2.java       | 28 ++++++----
 .../java/org/apache/solr/update/PeerSync.java   |  2 +-
 .../org/apache/solr/update/SolrIndexWriter.java | 34 +++++++-----
 .../java/org/apache/solr/update/UpdateLog.java  | 14 +++--
 .../apache/solr/update/UpdateShardHandler.java  |  6 +-
 .../stats/InstrumentedHttpRequestExecutor.java  |  7 ++-
 ...entedPoolingHttpClientConnectionManager.java | 19 +++++--
 .../test/org/apache/solr/CursorPagingTest.java  |  5 +-
 .../test/org/apache/solr/SolrInfoBeanTest.java  |  2 +-
 .../solr/core/ExitableDirectoryReaderTest.java  |  7 ++-
 .../solr/core/HdfsDirectoryFactoryTest.java     |  4 +-
 .../test/org/apache/solr/core/MockInfoBean.java |  8 ++-
 .../core/MockQuerySenderListenerReqHandler.java |  6 +-
 .../apache/solr/core/TestJmxIntegration.java    |  4 +-
 .../org/apache/solr/metrics/JvmMetricsTest.java |  2 +-
 .../solr/metrics/SolrCoreMetricManagerTest.java |  2 +-
 .../solr/metrics/SolrMetricManagerTest.java     | 10 ++--
 .../solr/metrics/SolrMetricTestUtils.java       |  2 +-
 .../apache/solr/search/TestFastLRUCache.java    | 14 ++---
 .../org/apache/solr/search/TestLFUCache.java    |  6 +-
 .../org/apache/solr/search/TestLRUCache.java    |  4 +-
 .../solr/search/TestReRankQParserPlugin.java    |  3 +-
 .../apache/solr/search/TestSolr4Spatial2.java   |  3 +-
 .../solr/search/TestSolrFieldCacheBean.java     |  8 +--
 .../apache/solr/search/TestSolrQueryParser.java |  9 +--
 .../apache/solr/search/join/BJQParserTest.java  |  9 +--
 .../solr/search/join/TestScoreJoinQPScore.java  |  3 +-
 .../solr/store/blockcache/BufferStoreTest.java  |  4 +-
 53 files changed, 401 insertions(+), 226 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index ea895c5..503a9e4 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -83,6 +83,12 @@ Bug Fixes
 * SOLR-12172: Fixed race condition that could cause an invalid set of collection properties to be kept in
   memory when multiple collection property changes are done in a short period of time. (Tomás Fernández Löbbe) 
 
+* SOLR-11882: SolrMetric registries retained references to SolrCores when closed. A
+  change of SolrMetricMAnager.registerGauge and SolrMetricProducer.initializeMetrics
+  method signatures was required to fix it. Third party components may continue to use the old API
+  but should be updated to avoid this bug (Eros Taborelli, Erick Erickson, ab)
+
+
 Optimizations
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/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 faea3ba..046901a 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
@@ -265,8 +265,8 @@ public class DataImportHandler extends RequestHandlerBase implements
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
-    super.initializeMetrics(manager, registryName, scope);
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    super.initializeMetrics(manager, registryName, tag, scope);
     metrics = new MetricsMap((detailed, map) -> {
       if (importer != null) {
         DocBuilder.Statistics cumulative = importer.cumulativeStatistics;
@@ -289,7 +289,7 @@ public class DataImportHandler extends RequestHandlerBase implements
         map.put(DataImporter.MSG.TOTAL_DOCS_SKIPPED, cumulative.skipDocCount);
       }
     });
-    manager.registerGauge(this, registryName, metrics, true, "importer", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, metrics, tag, true, "importer", getCategory().toString(), scope);
   }
 
   // //////////////////////SolrInfoMBeans methods //////////////////////

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/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 39e6a99..78247a0 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -183,6 +183,8 @@ public class CoreContainer {
 
   protected SolrMetricManager metricManager;
 
+  protected String metricTag = Integer.toHexString(hashCode());
+
   protected MetricsHandler metricsHandler;
 
   protected MetricsCollectorHandler metricsCollectorHandler;
@@ -503,11 +505,11 @@ public class CoreContainer {
     shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
     if (shardHandlerFactory instanceof SolrMetricProducer) {
       SolrMetricProducer metricProducer = (SolrMetricProducer) shardHandlerFactory;
-      metricProducer.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), "httpShardHandler");
+      metricProducer.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, "httpShardHandler");
     }
 
     updateShardHandler = new UpdateShardHandler(cfg.getUpdateShardHandlerConfig());
-    updateShardHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), "updateShardHandler");
+    updateShardHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, "updateShardHandler");
 
     solrCores.load(loader);
 
@@ -537,7 +539,7 @@ public class CoreContainer {
     metricsCollectorHandler.init(null);
 
     containerHandlers.put(AUTHZ_PATH, securityConfHandler);
-    securityConfHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), AUTHZ_PATH);
+    securityConfHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, AUTHZ_PATH);
     containerHandlers.put(AUTHC_PATH, securityConfHandler);
     if(pkiAuthenticationPlugin != null)
       containerHandlers.put(PKIAuthenticationPlugin.PATH, pkiAuthenticationPlugin.getRequestHandler());
@@ -554,19 +556,20 @@ public class CoreContainer {
     // initialize gauges for reporting the number of cores and disk total/free
 
     String registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.node);
+    String metricTag = Integer.toHexString(hashCode());
     metricManager.registerGauge(null, registryName, () -> solrCores.getCores().size(),
-        true, "loaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
+        metricTag,true, "loaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
     metricManager.registerGauge(null, registryName, () -> solrCores.getLoadedCoreNames().size() - solrCores.getCores().size(),
-        true, "lazy", SolrInfoBean.Category.CONTAINER.toString(), "cores");
+        metricTag,true, "lazy", SolrInfoBean.Category.CONTAINER.toString(), "cores");
     metricManager.registerGauge(null, registryName, () -> solrCores.getAllCoreNames().size() - solrCores.getLoadedCoreNames().size(),
-        true, "unloaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
+        metricTag,true, "unloaded", SolrInfoBean.Category.CONTAINER.toString(), "cores");
     Path dataHome = cfg.getSolrDataHome() != null ? cfg.getSolrDataHome() : cfg.getCoreRootDirectory();
     metricManager.registerGauge(null, registryName, () -> dataHome.toFile().getTotalSpace(),
-        true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
+        metricTag,true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
     metricManager.registerGauge(null, registryName, () -> dataHome.toFile().getUsableSpace(),
-        true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
+        metricTag,true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs");
     metricManager.registerGauge(null, registryName, () -> dataHome.toAbsolutePath().toString(),
-        true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs");
+        metricTag,true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs");
     metricManager.registerGauge(null, registryName, () -> {
           try {
             return org.apache.lucene.util.IOUtils.spins(dataHome.toAbsolutePath());
@@ -575,13 +578,13 @@ public class CoreContainer {
             return true;
           }
         },
-        true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs");
+        metricTag,true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs");
     metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toFile().getTotalSpace(),
-        true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
+        metricTag,true, "totalSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
     metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toFile().getUsableSpace(),
-        true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
+        metricTag,true, "usableSpace", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
     metricManager.registerGauge(null, registryName, () -> cfg.getCoreRootDirectory().toAbsolutePath().toString(),
-        true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
+        metricTag,true, "path", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
     metricManager.registerGauge(null, registryName, () -> {
           try {
             return org.apache.lucene.util.IOUtils.spins(cfg.getCoreRootDirectory().toAbsolutePath());
@@ -590,15 +593,15 @@ public class CoreContainer {
             return true;
           }
         },
-        true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
+        metricTag,true, "spins", SolrInfoBean.Category.CONTAINER.toString(), "fs", "coreRoot");
     // add version information
     metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getSpecificationVersion(),
-        true, "specification", SolrInfoBean.Category.CONTAINER.toString(), "version");
+        metricTag,true, "specification", SolrInfoBean.Category.CONTAINER.toString(), "version");
     metricManager.registerGauge(null, registryName, () -> this.getClass().getPackage().getImplementationVersion(),
-        true, "implementation", SolrInfoBean.Category.CONTAINER.toString(), "version");
+        metricTag,true, "implementation", SolrInfoBean.Category.CONTAINER.toString(), "version");
 
     SolrFieldCacheBean fieldCacheBean = new SolrFieldCacheBean();
-    fieldCacheBean.initializeMetrics(metricManager, registryName, null);
+    fieldCacheBean.initializeMetrics(metricManager, registryName, metricTag, null);
 
     if (isZooKeeperAware()) {
       metricManager.loadClusterReporters(metricReporters, this);
@@ -687,7 +690,7 @@ public class CoreContainer {
       // initialize this handler here when SolrCloudManager is ready
       autoScalingHandler = new AutoScalingHandler(getZkController().getSolrCloudManager(), loader);
       containerHandlers.put(AutoScalingHandler.HANDLER_PATH, autoScalingHandler);
-      autoScalingHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), AutoScalingHandler.HANDLER_PATH);
+      autoScalingHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, AutoScalingHandler.HANDLER_PATH);
     }
     // This is a bit redundant but these are two distinct concepts for all they're accomplished at the same time.
     status |= LOAD_COMPLETE | INITIAL_CORE_LOAD_COMPLETE;
@@ -740,6 +743,10 @@ public class CoreContainer {
       metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node));
       metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm));
       metricManager.closeReporters(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jetty));
+
+      metricManager.unregisterGauges(SolrMetricManager.getRegistryName(SolrInfoBean.Group.node), metricTag);
+      metricManager.unregisterGauges(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm), metricTag);
+      metricManager.unregisterGauges(SolrMetricManager.getRegistryName(SolrInfoBean.Group.jetty), metricTag);
     }
 
     if (isZooKeeperAware()) {
@@ -1549,7 +1556,7 @@ public class CoreContainer {
       containerHandlers.put(path, (SolrRequestHandler)handler);
     }
     if (handler instanceof SolrMetricProducer) {
-      ((SolrMetricProducer)handler).initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), path);
+      ((SolrMetricProducer)handler).initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), metricTag, path);
     }
     return handler;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/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 4938689..e4b06b7 100644
--- a/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
+++ b/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
@@ -114,7 +114,7 @@ public class HdfsDirectoryFactory extends CachingDirectoryFactory implements Sol
   
   public static Metrics metrics;
   private static Boolean kerberosInit;
-  
+
   // we use this cache for FileSystem instances when we don't have access to a long lived instance
   private com.google.common.cache.Cache<String,FileSystem> tmpFsCache = CacheBuilder.newBuilder()
       .concurrencyLevel(10)
@@ -489,9 +489,9 @@ public class HdfsDirectoryFactory extends CachingDirectoryFactory implements Sol
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
-    MetricsHolder.metrics.initializeMetrics(manager, registry, scope);
-    LocalityHolder.reporter.initializeMetrics(manager, registry, scope);
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    MetricsHolder.metrics.initializeMetrics(manager, registry, tag, scope);
+    LocalityHolder.reporter.initializeMetrics(manager, registry, tag, scope);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/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 f1bae42..83dd2df 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -225,6 +225,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
   private final CoreContainer coreContainer;
 
   private Set<String> metricNames = ConcurrentHashMap.newKeySet();
+  private String metricTag = Integer.toHexString(hashCode());
 
   public Set<String> getMetricNames() {
     return metricNames;
@@ -925,12 +926,12 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
     SolrMetricManager metricManager = coreContainer.getMetricManager();
 
     // initialize searcher-related metrics
-    initializeMetrics(metricManager, coreMetricManager.getRegistryName(), null);
+    initializeMetrics(metricManager, coreMetricManager.getRegistryName(), metricTag, null);
 
     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");
+    solrFieldCacheBean.initializeMetrics(metricManager, coreMetricManager.getRegistryName(), metricTag, "core");
     infoRegistry.put("fieldCache", solrFieldCacheBean);
 
 
@@ -1023,7 +1024,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
 
     // Allow the directory factory to report metrics
     if (directoryFactory instanceof SolrMetricProducer) {
-      ((SolrMetricProducer)directoryFactory).initializeMetrics(metricManager, coreMetricManager.getRegistryName(), "directoryFactory");
+      ((SolrMetricProducer)directoryFactory).initializeMetrics(metricManager, coreMetricManager.getRegistryName(), metricTag, "directoryFactory");
     }
 
     // seed version buckets with max from index during core initialization ... requires a searcher!
@@ -1142,22 +1143,22 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
     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, () -> isClosed() ? "(closed)" : getIndexDir(), true, "indexDir", Category.CORE.toString());
-    manager.registerGauge(this, registry, () -> isClosed() ? 0 : getIndexSize(), true, "sizeInBytes", Category.INDEX.toString());
-    manager.registerGauge(this, registry, () -> isClosed() ? "(closed)" : NumberUtils.readableSize(getIndexSize()), true, "size", Category.INDEX.toString());
+    manager.registerGauge(this, registry, () -> name == null ? "(null)" : name, getMetricTag(), true, "coreName", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> startTime, getMetricTag(), true, "startTime", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> getOpenCount(), getMetricTag(), true, "refCount", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> resourceLoader.getInstancePath().toString(), getMetricTag(), true, "instanceDir", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> isClosed() ? "(closed)" : getIndexDir(), getMetricTag(), true, "indexDir", Category.CORE.toString());
+    manager.registerGauge(this, registry, () -> isClosed() ? 0 : getIndexSize(), getMetricTag(), true, "sizeInBytes", Category.INDEX.toString());
+    manager.registerGauge(this, registry, () -> isClosed() ? "(closed)" : NumberUtils.readableSize(getIndexSize()), getMetricTag(), true, "size", Category.INDEX.toString());
     if (coreContainer != null) {
-      manager.registerGauge(this, registry, () -> coreContainer.getNamesForCore(this), true, "aliases", Category.CORE.toString());
+      manager.registerGauge(this, registry, () -> coreContainer.getNamesForCore(this), getMetricTag(), true, "aliases", Category.CORE.toString());
       final CloudDescriptor cd = getCoreDescriptor().getCloudDescriptor();
       if (cd != null) {
         manager.registerGauge(this, registry, () -> {
@@ -1166,7 +1167,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
           } else {
             return "_notset_";
           }
-        }, true, "collection", Category.CORE.toString());
+        }, getMetricTag(), true, "collection", Category.CORE.toString());
 
         manager.registerGauge(this, registry, () -> {
           if (cd.getShardId() != null) {
@@ -1174,15 +1175,15 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
           } else {
             return "_auto_";
           }
-        }, true, "shard", Category.CORE.toString());
+        }, getMetricTag(), true, "shard", Category.CORE.toString());
       }
     }
     // initialize disk total / free metrics
     Path dataDirPath = Paths.get(dataDir);
     File dataDirFile = dataDirPath.toFile();
-    manager.registerGauge(this, registry, () -> dataDirFile.getTotalSpace(), true, "totalSpace", Category.CORE.toString(), "fs");
-    manager.registerGauge(this, registry, () -> dataDirFile.getUsableSpace(), true, "usableSpace", Category.CORE.toString(), "fs");
-    manager.registerGauge(this, registry, () -> dataDirPath.toAbsolutePath().toString(), true, "path", Category.CORE.toString(), "fs");
+    manager.registerGauge(this, registry, () -> dataDirFile.getTotalSpace(), getMetricTag(), true, "totalSpace", Category.CORE.toString(), "fs");
+    manager.registerGauge(this, registry, () -> dataDirFile.getUsableSpace(), getMetricTag(), true, "usableSpace", Category.CORE.toString(), "fs");
+    manager.registerGauge(this, registry, () -> dataDirPath.toAbsolutePath().toString(), getMetricTag(), true, "path", Category.CORE.toString(), "fs");
     manager.registerGauge(this, registry, () -> {
       try {
         return org.apache.lucene.util.IOUtils.spins(dataDirPath.toAbsolutePath());
@@ -1190,7 +1191,11 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
         // default to spinning
         return true;
       }
-    }, true, "spins", Category.CORE.toString(), "fs");
+    }, getMetricTag(), true, "spins", Category.CORE.toString(), "fs");
+  }
+
+  public String getMetricTag() {
+    return metricTag;
   }
 
   private void checkVersionFieldExistsInSchema(IndexSchema schema, CoreDescriptor coreDescriptor) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/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
index edded0e..38ffc99 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrInfoBean.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrInfoBean.java
@@ -83,7 +83,7 @@ public interface SolrInfoBean {
   /** 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)}).
+   * from {@link org.apache.solr.metrics.SolrMetricProducer#initializeMetrics(SolrMetricManager, String, 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>
    */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
index 43ec573..1707c80 100644
--- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
@@ -837,21 +837,21 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
-    super.initializeMetrics(manager, registry, scope);
-
-    manager.registerGauge(this, registry, () -> core != null ? NumberUtils.readableSize(core.getIndexSize()) : "", true,
-        "indexSize", getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> (core != null && !core.isClosed() ? getIndexVersion().toString() : ""), true,
-        "indexVersion", getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> (core != null && !core.isClosed() ? getIndexVersion().generation : 0), true,
-        GENERATION, getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> core != null ? core.getIndexDir() : "", true,
-        "indexPath", getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> isMaster, true,
-        "isMaster", getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> isSlave, true,
-        "isSlave", getCategory().toString(), scope);
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    super.initializeMetrics(manager, registry, tag, scope);
+
+    manager.registerGauge(this, registry, () -> core != null ? NumberUtils.readableSize(core.getIndexSize()) : "",
+        tag, true, "indexSize", getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> (core != null && !core.isClosed() ? getIndexVersion().toString() : ""),
+        tag, true, "indexVersion", getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> (core != null && !core.isClosed() ? getIndexVersion().generation : 0),
+        tag, true, GENERATION, getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> core != null ? core.getIndexDir() : "",
+        tag, true, "indexPath", getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> isMaster,
+        tag, true, "isMaster", getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> isSlave,
+        tag, true, "isSlave", getCategory().toString(), scope);
     final MetricsMap fetcherMap = new MetricsMap((detailed, map) -> {
       IndexFetcher fetcher = currentIndexFetcher;
       if (fetcher != null) {
@@ -880,13 +880,13 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw
         addVal(map, IndexFetcher.CONF_FILES_REPLICATED, props, String.class);
       }
     });
-    manager.registerGauge(this, registry, fetcherMap, true, "fetcher", getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> isMaster && includeConfFiles != null ? includeConfFiles : "", true,
-        "confFilesToReplicate", getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> isMaster ? getReplicateAfterStrings() : Collections.<String>emptyList(), true,
-        REPLICATE_AFTER, getCategory().toString(), scope);
-    manager.registerGauge(this, registry, () -> isMaster && replicationEnabled.get(), true,
-        "replicationEnabled", getCategory().toString(), scope);
+    manager.registerGauge(this, registry, fetcherMap, tag, true, "fetcher", getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> isMaster && includeConfFiles != null ? includeConfFiles : "",
+        tag, true, "confFilesToReplicate", getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> isMaster ? getReplicateAfterStrings() : Collections.<String>emptyList(),
+        tag, true, REPLICATE_AFTER, getCategory().toString(), scope);
+    manager.registerGauge(this, registry, () -> isMaster && replicationEnabled.get(),
+        tag, true, "replicationEnabled", getCategory().toString(), scope);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
index 808e557..d4cfd99 100644
--- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
@@ -80,6 +80,8 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
 
   private Set<String> metricNames = ConcurrentHashMap.newKeySet();
   private MetricRegistry registry;
+  protected String registryName;
+  protected SolrMetricManager metricManager;
 
 
   @SuppressForbidden(reason = "Need currentTimeMillis, used only for stats output")
@@ -144,8 +146,10 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, final String scope) {
-    registry = manager.registry(registryName);
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, final String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
+    this.registry = manager.registry(registryName);
     numErrors = manager.meter(this, registryName, "errors", getCategory().toString(), scope);
     numServerErrors = manager.meter(this, registryName, "serverErrors", getCategory().toString(), scope);
     numClientErrors = manager.meter(this, registryName, "clientErrors", getCategory().toString(), scope);
@@ -153,10 +157,10 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
     requests = manager.counter(this, registryName, "requests", getCategory().toString(), scope);
     MetricsMap metricsMap = new MetricsMap((detail, map) ->
       shardPurposes.forEach((k, v) -> map.put(k, v.getCount())));
-    manager.register(this, registryName, metricsMap, true, "shardRequests", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, metricsMap, tag, true, "shardRequests", getCategory().toString(), scope);
     requestTimes = manager.timer(this, registryName, "requestTimes", getCategory().toString(), scope);
     totalTime = manager.counter(this, registryName, "totalTime", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> handlerStart, true, "handlerStart", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> handlerStart, tag, true, "handlerStart", getCategory().toString(), scope);
   }
 
   public static SolrParams getSolrParamsFromNamedList(NamedList args, String key) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
index 40099ea..8932c21 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
@@ -119,8 +119,8 @@ public class CoreAdminHandler extends RequestHandlerBase implements PermissionNa
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
-    super.initializeMetrics(manager, registryName, scope);
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    super.initializeMetrics(manager, registryName, tag, scope);
     parallelExecutor = MetricUtils.instrumentedExecutorService(parallelExecutor, this, manager.registry(registryName),
         SolrMetricManager.mkName("parallelCoreAdminExecutor", getCategory().name(),scope, "threadPool"));
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
index 6bfd36a..8cff025 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
@@ -105,6 +105,8 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.
 
   private HttpClientMetricNameStrategy metricNameStrategy;
 
+  private String metricTag;
+
   protected final Random r = new Random();
 
   private final ReplicaListTransformer shufflingReplicaListTransformer = new ShufflingReplicaListTransformer(r);
@@ -398,10 +400,11 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    this.metricTag = tag;
     String expandedScope = SolrMetricManager.mkName(scope, SolrInfoBean.Category.QUERY.name());
-    clientConnectionManager.initializeMetrics(manager, registry, expandedScope);
-    httpRequestExecutor.initializeMetrics(manager, registry, expandedScope);
+    clientConnectionManager.initializeMetrics(manager, registry, tag, expandedScope);
+    httpRequestExecutor.initializeMetrics(manager, registry, tag, expandedScope);
     commExecutor = MetricUtils.instrumentedExecutorService(commExecutor, null,
         manager.registry(registry),
         SolrMetricManager.mkName("httpShardExecutor", expandedScope, "threadPool"));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java b/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java
index 78a62fa..d923306 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java
@@ -99,7 +99,7 @@ public abstract class SearchComponent implements SolrInfoBean, NamedListInitiali
   {
     // By default do nothing
   }
-  
+
   //////////////////////// SolrInfoMBeans methods //////////////////////
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java b/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java
index 4ca6ce4..cba7e93 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java
@@ -87,6 +87,9 @@ public class SuggestComponent extends SearchComponent implements SolrCoreAware,
   
   @SuppressWarnings("unchecked")
   protected NamedList initParams;
+
+  protected SolrMetricManager metricManager;
+  protected String registryName;
   
   /**
    * Key is the dictionary name used in SolrConfig, value is the corresponding {@link SolrSuggester}
@@ -348,16 +351,18 @@ public class SuggestComponent extends SearchComponent implements SolrCoreAware,
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.registryName = registryName;
+    this.metricManager = manager;
     registry = manager.registry(registryName);
-    manager.registerGauge(this, registryName, () -> ramBytesUsed(), true, "totalSizeInBytes", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> ramBytesUsed(), tag, true, "totalSizeInBytes", getCategory().toString(), scope);
     MetricsMap suggestersMap = new MetricsMap((detailed, map) -> {
       for (Map.Entry<String, SolrSuggester> entry : suggesters.entrySet()) {
         SolrSuggester suggester = entry.getValue();
         map.put(entry.getKey(), suggester.toString());
       }
     });
-    manager.registerGauge(this, registryName, suggestersMap, true, "suggesters", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, suggestersMap, tag, true, "suggesters", getCategory().toString(), scope);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/highlight/HighlightingPluginBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/highlight/HighlightingPluginBase.java b/solr/core/src/java/org/apache/solr/highlight/HighlightingPluginBase.java
index 2620ec7e..bed4a1d 100644
--- a/solr/core/src/java/org/apache/solr/highlight/HighlightingPluginBase.java
+++ b/solr/core/src/java/org/apache/solr/highlight/HighlightingPluginBase.java
@@ -37,6 +37,8 @@ public abstract class HighlightingPluginBase implements SolrInfoBean, SolrMetric
   protected SolrParams defaults;
   protected Set<String> metricNames = ConcurrentHashMap.newKeySet(1);
   protected MetricRegistry registry;
+  protected SolrMetricManager metricManager;
+  protected String registryName;
 
   public void init(NamedList args) {
     if( args != null ) {
@@ -74,7 +76,9 @@ public abstract class HighlightingPluginBase implements SolrInfoBean, SolrMetric
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.registryName = registryName;
+    this.metricManager = manager;
     registry = manager.registry(registryName);
     numRequests = manager.counter(this, registryName, "requests", getCategory().toString(), scope);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
index 74c9596..c57a704 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrCoreMetricManager.java
@@ -56,7 +56,7 @@ public class SolrCoreMetricManager implements Closeable {
    */
   public SolrCoreMetricManager(SolrCore core) {
     this.core = core;
-    this.tag = String.valueOf(core.hashCode());
+    this.tag = core.getMetricTag();
     this.metricManager = core.getCoreContainer().getMetricManager();
     initCloudMode();
     registryName = createRegistryName(cloudMode, collectionName, shardName, replicaName, core.getName());
@@ -127,7 +127,7 @@ public class SolrCoreMetricManager implements Closeable {
       throw new IllegalArgumentException("registerMetricProducer() called with illegal arguments: " +
           "scope = " + scope + ", producer = " + producer);
     }
-    producer.initializeMetrics(metricManager, getRegistryName(), scope);
+    producer.initializeMetrics(metricManager, getRegistryName(), tag, scope);
   }
 
   /**
@@ -142,7 +142,7 @@ public class SolrCoreMetricManager implements Closeable {
   }
 
   /**
-   * Closes reporters specific to this core.
+   * Closes reporters specific to this core and unregisters gauges with this core's instance tag.
    */
   @Override
   public void close() throws IOException {
@@ -150,6 +150,7 @@ public class SolrCoreMetricManager implements Closeable {
     if (getLeaderRegistryName() != null) {
       metricManager.closeReporters(getLeaderRegistryName(), tag);
     }
+    metricManager.unregisterGauges(getRegistryName(), tag);
   }
 
   public SolrCore getCore() {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
index 4223675..d5b8864 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -31,6 +31,7 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.regex.Pattern;
@@ -645,7 +646,7 @@ public class SolrMetricManager {
    *                   using dotted notation
    * @param metricPath (optional) additional top-most metric name path elements
    */
-  public void register(SolrInfoBean info, String registry, Metric metric, boolean force, String metricName, String... metricPath) {
+  public void registerMetric(SolrInfoBean info, String registry, Metric metric, boolean force, String metricName, String... metricPath) {
     MetricRegistry metricRegistry = registry(registry);
     String fullName = mkName(metricName, metricPath);
     if (info != null) {
@@ -659,8 +660,56 @@ public class SolrMetricManager {
     }
   }
 
-  public void registerGauge(SolrInfoBean info, String registry, Gauge<?> gauge, boolean force, String metricName, String... metricPath) {
-    register(info, registry, gauge, force, metricName, metricPath);
+  /**
+   * This is a wrapper for {@link Gauge} metrics, which are usually implemented as
+   * lambdas that often keep a reference to their parent instance. In order to make sure that
+   * all such metrics are removed when their parent instance is removed / closed the
+   * metric is associated with an instance tag, which can be used then to remove
+   * wrappers with the matching tag using {@link #unregisterGauges(String, String)}.
+   */
+  public static class GaugeWrapper<T> implements Gauge<T> {
+    private final Gauge<T> gauge;
+    private final String tag;
+
+    public GaugeWrapper(Gauge<T> gauge, String tag) {
+      this.gauge = gauge;
+      this.tag = tag;
+    }
+
+    @Override
+    public T getValue() {
+      return gauge.getValue();
+    }
+
+    public String getTag() {
+      return tag;
+    }
+
+    public Gauge<T> getGauge() {
+      return gauge;
+    }
+  }
+
+  public void registerGauge(SolrInfoBean info, String registry, Gauge<?> gauge, String tag, boolean force, String metricName, String... metricPath) {
+    registerMetric(info, registry, new GaugeWrapper(gauge, tag), force, metricName, metricPath);
+  }
+
+  public int unregisterGauges(String registryName, String tag) {
+    if (tag == null) {
+      return 0;
+    }
+    MetricRegistry registry = registry(registryName);
+    AtomicInteger removed = new AtomicInteger();
+    registry.removeMatching((name, metric) -> {
+      if (metric instanceof GaugeWrapper &&
+          tag.equals(((GaugeWrapper)metric).getTag())) {
+        removed.incrementAndGet();
+        return true;
+      } else {
+        return false;
+      }
+    });
+    return removed.get();
   }
 
   /**
@@ -1110,8 +1159,7 @@ public class SolrMetricManager {
         attrs, initArgs);
     for (PluginInfo info : infos) {
       try {
-        loadReporter(registryName, core, info,
-            String.valueOf(core.hashCode()));
+        loadReporter(registryName, core, info, core.getMetricTag());
       } catch (Exception e) {
         log.warn("Could not load shard reporter, pluginInfo=" + info, e);
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
index 73abab1..ef78b3c 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
@@ -17,16 +17,39 @@
 package org.apache.solr.metrics;
 
 /**
- * Used by objects that expose metrics through {@link SolrCoreMetricManager}.
+ * Used by objects that expose metrics through {@link SolrMetricManager}.
  */
 public interface SolrMetricProducer {
 
   /**
-   * Initializes metrics specific to this producer
+   * Initializes metrics specific to this producer.
+   * <p>Note: for back-compatibility this method by default calls {@link #initializeMetrics(SolrMetricManager, String, String)}.</p>
    * @param manager an instance of {@link SolrMetricManager}
    * @param registry registry name where metrics are registered
+   * @param tag symbolic tag that represents a group of related instances that
+   * have the same life-cycle. Parent component can use the <code>tag</code> when
+   * calling {@link SolrMetricManager#unregisterGauges(String, String)}
+   * to unregister metrics created by this instance of the producer.
    * @param scope scope of the metrics (eg. handler name) to separate metrics of
    *              instances of the same component executing in different contexts
    */
-  void initializeMetrics(SolrMetricManager manager, String registry, String scope);
+  default void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    initializeMetrics(manager, registry, scope);
+  }
+
+  /**
+   * Initializes metrics specific to this producer.
+   * <p>Note: for back-compatibility this method has a default no-op implementation.</p>
+   * @param manager an instance of {@link SolrMetricManager}
+   * @param registry registry name where metrics are registered
+   * @param scope scope of the metrics (eg. handler name) to separate metrics of
+   *              instances of the same component executing in different contexts
+   * @deprecated this method doesn't provide enough context to properly manage
+   * life-cycle of some metrics (see SOLR-11882).
+   * Instead use {@link #initializeMetrics(SolrMetricManager, String, String, String)}.
+   */
+  @Deprecated
+  default void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/metrics/reporters/solr/SolrReporter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/reporters/solr/SolrReporter.java b/solr/core/src/java/org/apache/solr/metrics/reporters/solr/SolrReporter.java
index 8d36cef..7055f52 100644
--- a/solr/core/src/java/org/apache/solr/metrics/reporters/solr/SolrReporter.java
+++ b/solr/core/src/java/org/apache/solr/metrics/reporters/solr/SolrReporter.java
@@ -303,7 +303,7 @@ public class SolrReporter extends ScheduledReporter {
                       String reporterId, TimeUnit rateUnit, TimeUnit durationUnit,
                       SolrParams params, boolean skipHistograms, boolean skipAggregateValues,
                       boolean cloudClient, boolean compact) {
-    super(null, "solr-reporter", MetricFilter.ALL, rateUnit, durationUnit);
+    super(null, "solr-reporter", MetricFilter.ALL, rateUnit, durationUnit, null, true);
     this.metricManager = metricManager;
     this.urlProvider = urlProvider;
     this.reporterId = reporterId;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/FastLRUCache.java b/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
index a73a65a..75fef10 100644
--- a/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
@@ -62,6 +62,8 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>
   private MetricsMap cacheMap;
   private Set<String> metricNames = ConcurrentHashMap.newKeySet();
   private MetricRegistry registry;
+  private SolrMetricManager metricManager;
+  private String registryName;
 
   @Override
   public Object init(Map args, Object persistence, CacheRegenerator regenerator) {
@@ -226,7 +228,9 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
     registry = manager.registry(registryName);
     cacheMap = new MetricsMap((detailed, map) -> {
       if (cache != null) {
@@ -277,9 +281,10 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>
         }
       }
     });
-    manager.registerGauge(this, registryName, cacheMap, true, scope, getCategory().toString());
+    manager.registerGauge(this, registryName, cacheMap, tag, true, scope, getCategory().toString());
   }
 
+
   // for unit tests only
   MetricsMap getMetricsMap() {
     return cacheMap;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/search/LFUCache.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/LFUCache.java b/solr/core/src/java/org/apache/solr/search/LFUCache.java
index 7d41ae3..e593c1b 100644
--- a/solr/core/src/java/org/apache/solr/search/LFUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/LFUCache.java
@@ -67,6 +67,8 @@ public class LFUCache<K, V> implements SolrCache<K, V> {
   private MetricsMap cacheMap;
   private Set<String> metricNames = ConcurrentHashMap.newKeySet();
   private MetricRegistry registry;
+  private SolrMetricManager metricManager;
+  private String registryName;
 
   @Override
   public Object init(Map args, Object persistence, CacheRegenerator regenerator) {
@@ -234,7 +236,9 @@ public class LFUCache<K, V> implements SolrCache<K, V> {
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
     registry = manager.registry(registryName);
     cacheMap = new MetricsMap((detailed, map) -> {
       if (cache != null) {
@@ -288,7 +292,7 @@ public class LFUCache<K, V> implements SolrCache<K, V> {
 
       }
     });
-    manager.registerGauge(this, registryName, cacheMap, true, scope, getCategory().toString());
+    manager.registerGauge(this, registryName, cacheMap, tag, true, scope, getCategory().toString());
   }
 
   // for unit tests only

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/search/LRUCache.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/LRUCache.java b/solr/core/src/java/org/apache/solr/search/LRUCache.java
index af05dad..8f53b45 100644
--- a/solr/core/src/java/org/apache/solr/search/LRUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/LRUCache.java
@@ -89,6 +89,8 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
   private MetricsMap cacheMap;
   private Set<String> metricNames = ConcurrentHashMap.newKeySet();
   private MetricRegistry registry;
+  private SolrMetricManager metricManager;
+  private String registryName;
 
   private long maxRamBytes = Long.MAX_VALUE;
   // The synchronization used for the map will be used to update this,
@@ -306,9 +308,9 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
     warmupTime = TimeUnit.MILLISECONDS.convert(System.nanoTime() - warmingStartTime, TimeUnit.NANOSECONDS);
   }
 
-
   @Override
   public void close() {
+
   }
 
 
@@ -331,7 +333,9 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
     registry = manager.registry(registryName);
     cacheMap = new MetricsMap((detailed, res) -> {
       synchronized (map) {
@@ -360,7 +364,7 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
         res.put("cumulative_evictionsRamUsage", stats.evictionsRamUsage.longValue());
       }
     });
-    manager.registerGauge(this, registryName, cacheMap, true, scope, getCategory().toString());
+    manager.registerGauge(this, registryName, cacheMap, tag, true, scope, getCategory().toString());
   }
 
   // for unit tests only

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java
index 82787d1..b2647cd 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java
@@ -56,7 +56,7 @@ public class SolrFieldCacheBean implements SolrInfoBean, SolrMetricProducer {
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
     registry = manager.registry(registryName);
     MetricsMap metricsMap = new MetricsMap((detailed, map) -> {
       if (detailed && !disableEntryList && !disableJmxEntryList) {
@@ -72,6 +72,6 @@ public class SolrFieldCacheBean implements SolrInfoBean, SolrMetricProducer {
         map.put("entries_count", UninvertingReader.getUninvertedStatsSize());
       }
     });
-    manager.register(this, registryName, metricsMap, true, "fieldCache", Category.CACHE.toString(), scope);
+    manager.registerGauge(this, registryName, metricsMap, tag, true, "fieldCache", Category.CACHE.toString(), scope);
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
index e989732..14927ca 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
@@ -138,6 +138,8 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
   private boolean releaseDirectory;
 
   private Set<String> metricNames = ConcurrentHashMap.newKeySet();
+  private SolrMetricManager metricManager;
+  private String registryName;
 
   private static DirectoryReader getReader(SolrCore core, SolrIndexConfig config, DirectoryFactory directoryFactory,
                                            String path) throws IOException {
@@ -439,12 +441,12 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
       cache.setState(SolrCache.State.LIVE);
       infoRegistry.put(cache.name(), cache);
     }
-    SolrMetricManager manager = core.getCoreContainer().getMetricManager();
-    String registry = core.getCoreMetricManager().getRegistryName();
+    metricManager = core.getCoreContainer().getMetricManager();
+    registryName = core.getCoreMetricManager().getRegistryName();
     for (SolrCache cache : cacheList) {
-      cache.initializeMetrics(manager, registry, SolrMetricManager.mkName(cache.name(), STATISTICS_KEY));
+      cache.initializeMetrics(metricManager, registryName, core.getMetricTag(), SolrMetricManager.mkName(cache.name(), STATISTICS_KEY));
     }
-    initializeMetrics(manager, registry, STATISTICS_KEY);
+    initializeMetrics(metricManager, registryName, core.getMetricTag(), STATISTICS_KEY);
     registerTime = new Date();
   }
 
@@ -2249,20 +2251,21 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
-
-    manager.registerGauge(this, registry, () -> name, true, "searcherName", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> cachingEnabled, true, "caching", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> openTime, true, "openedAt", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> warmupTime, true, "warmupTime", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> registerTime, true, "registeredAt", Category.SEARCHER.toString(), scope);
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    this.registryName = registry;
+    this.metricManager = manager;
+    manager.registerGauge(this, registry, () -> name, tag, true, "searcherName", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> cachingEnabled, tag, true, "caching", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> openTime, tag, true, "openedAt", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> warmupTime, tag, true, "warmupTime", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> registerTime, tag, true, "registeredAt", Category.SEARCHER.toString(), scope);
     // reader stats
-    manager.registerGauge(this, registry, () -> reader.numDocs(), true, "numDocs", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> reader.maxDoc(), true, "maxDoc", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> reader.maxDoc() - reader.numDocs(), true, "deletedDocs", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> reader.toString(), true, "reader", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> reader.directory().toString(), true, "readerDir", Category.SEARCHER.toString(), scope);
-    manager.registerGauge(this, registry, () -> reader.getVersion(), true, "indexVersion", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> reader.numDocs(), tag, true, "numDocs", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> reader.maxDoc(), tag, true, "maxDoc", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> reader.maxDoc() - reader.numDocs(), tag, true, "deletedDocs", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> reader.toString(), tag, true, "reader", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> reader.directory().toString(), tag, true, "readerDir", Category.SEARCHER.toString(), scope);
+    manager.registerGauge(this, registry, () -> reader.getVersion(), tag, true, "indexVersion", Category.SEARCHER.toString(), scope);
 
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
index a70e2b8..fc0c28f 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
@@ -102,6 +102,10 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   private Boolean testMode = null;
   private boolean isV2Enabled = !"true".equals(System.getProperty("disable.v2.api", "false"));
 
+  private final String metricTag = Integer.toHexString(hashCode());
+  private SolrMetricManager metricManager;
+  private String registryName;
+
   /**
    * Enum to define action that needs to be processed.
    * PASSTHROUGH: Pass through to Restlet via webapp.
@@ -204,16 +208,16 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   }
 
   private void setupJvmMetrics(CoreContainer coresInit)  {
-    SolrMetricManager metricManager = coresInit.getMetricManager();
+    metricManager = coresInit.getMetricManager();
+    registryName = SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm);
     final Set<String> hiddenSysProps = coresInit.getConfig().getMetricsConfig().getHiddenSysProps();
     try {
-      String registry = SolrMetricManager.getRegistryName(SolrInfoBean.Group.jvm);
-      metricManager.registerAll(registry, new AltBufferPoolMetricSet(), true, "buffers");
-      metricManager.registerAll(registry, new ClassLoadingGaugeSet(), true, "classes");
-      metricManager.registerAll(registry, new OperatingSystemMetricSet(), true, "os");
-      metricManager.registerAll(registry, new GarbageCollectorMetricSet(), true, "gc");
-      metricManager.registerAll(registry, new MemoryUsageGaugeSet(), true, "memory");
-      metricManager.registerAll(registry, new ThreadStatesGaugeSet(), true, "threads"); // todo should we use CachedThreadStatesGaugeSet instead?
+      metricManager.registerAll(registryName, new AltBufferPoolMetricSet(), true, "buffers");
+      metricManager.registerAll(registryName, new ClassLoadingGaugeSet(), true, "classes");
+      metricManager.registerAll(registryName, new OperatingSystemMetricSet(), true, "os");
+      metricManager.registerAll(registryName, new GarbageCollectorMetricSet(), true, "gc");
+      metricManager.registerAll(registryName, new MemoryUsageGaugeSet(), true, "memory");
+      metricManager.registerAll(registryName, new ThreadStatesGaugeSet(), true, "threads"); // todo should we use CachedThreadStatesGaugeSet instead?
       MetricsMap sysprops = new MetricsMap((detailed, map) -> {
         System.getProperties().forEach((k, v) -> {
           if (!hiddenSysProps.contains(k)) {
@@ -221,7 +225,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
           }
         });
       });
-      metricManager.registerGauge(null, registry, sysprops, true, "properties", "system");
+      metricManager.registerGauge(null, registryName, sysprops, metricTag, true, "properties", "system");
     } catch (Exception e) {
       log.warn("Error registering JVM metrics", e);
     }
@@ -317,6 +321,10 @@ public class SolrDispatchFilter extends BaseSolrFilter {
       SolrRequestParsers.fileCleaningTracker = null;
     }
 
+    if (metricManager != null) {
+      metricManager.unregisterGauges(registryName, metricTag);
+    }
+
     if (cores != null) {
       try {
         cores.shutdown();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/store/blockcache/Metrics.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/store/blockcache/Metrics.java b/solr/core/src/java/org/apache/solr/store/blockcache/Metrics.java
index cc7ae4b..6d9e9ea 100644
--- a/solr/core/src/java/org/apache/solr/store/blockcache/Metrics.java
+++ b/solr/core/src/java/org/apache/solr/store/blockcache/Metrics.java
@@ -56,10 +56,14 @@ public class Metrics extends SolrCacheBase implements SolrInfoBean, SolrMetricPr
   private MetricsMap metricsMap;
   private MetricRegistry registry;
   private Set<String> metricNames = ConcurrentHashMap.newKeySet();
+  private SolrMetricManager metricManager;
+  private String registryName;
   private long previous = System.nanoTime();
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
     registry = manager.registry(registryName);
     metricsMap = new MetricsMap((detailed, map) -> {
       long now = System.nanoTime();
@@ -104,7 +108,7 @@ public class Metrics extends SolrCacheBase implements SolrInfoBean, SolrMetricPr
       previous = now;
 
     });
-    manager.registerGauge(this, registryName, metricsMap, true, getName(), getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, metricsMap, tag, true, getName(), getCategory().toString(), scope);
   }
 
   private float getPerSecond(long value, double seconds) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/store/hdfs/HdfsLocalityReporter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/store/hdfs/HdfsLocalityReporter.java b/solr/core/src/java/org/apache/solr/store/hdfs/HdfsLocalityReporter.java
index 3474d3c..d10216b 100644
--- a/solr/core/src/java/org/apache/solr/store/hdfs/HdfsLocalityReporter.java
+++ b/solr/core/src/java/org/apache/solr/store/hdfs/HdfsLocalityReporter.java
@@ -52,6 +52,8 @@ public class HdfsLocalityReporter implements SolrInfoBean, SolrMetricProducer {
 
   private final Set<String> metricNames = ConcurrentHashMap.newKeySet();
   private MetricRegistry registry;
+  private SolrMetricManager metricManager;
+  private String registryName;
 
   public HdfsLocalityReporter() {
     cache = new ConcurrentHashMap<>();
@@ -94,7 +96,9 @@ public class HdfsLocalityReporter implements SolrInfoBean, SolrMetricProducer {
    * Provide statistics on HDFS block locality, both in terms of bytes and block counts.
    */
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
     registry = manager.registry(registryName);
     MetricsMap metricsMap = new MetricsMap((detailed, map) -> {
       long totalBytes = 0;
@@ -145,7 +149,7 @@ public class HdfsLocalityReporter implements SolrInfoBean, SolrMetricProducer {
         map.put(LOCALITY_BLOCKS_RATIO, localCount / (double) totalCount);
       }
     });
-    manager.registerGauge(this, registryName, metricsMap, true, "hdfsLocality", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, metricsMap, tag, true, "hdfsLocality", getCategory().toString(), scope);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
index d51c970..75453e1 100644
--- a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
+++ b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
@@ -91,6 +91,8 @@ public class DirectUpdateHandler2 extends UpdateHandler implements SolrCoreState
   LongAdder numDocsPending = new LongAdder();
   LongAdder numErrors = new LongAdder();
   Meter numErrorsCumulative;
+  SolrMetricManager metricManager;
+  String registryName;
 
   // tracks when auto-commit should occur
   protected final CommitTracker commitTracker;
@@ -161,25 +163,27 @@ public class DirectUpdateHandler2 extends UpdateHandler implements SolrCoreState
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registryName;
     this.registry = manager.registry(registryName);
     commitCommands = manager.meter(this, registryName, "commits", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> commitTracker.getCommitCount(), true, "autoCommits", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> softCommitTracker.getCommitCount(), true, "softAutoCommits", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> commitTracker.getCommitCount(), tag, true, "autoCommits", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> softCommitTracker.getCommitCount(), tag, true, "softAutoCommits", getCategory().toString(), scope);
     if (commitTracker.getDocsUpperBound() > 0) {
-      manager.registerGauge(this, registryName, () -> commitTracker.getDocsUpperBound(), true, "autoCommitMaxDocs",
+      manager.registerGauge(this, registryName, () -> commitTracker.getDocsUpperBound(), tag, true, "autoCommitMaxDocs",
           getCategory().toString(), scope);
     }
     if (commitTracker.getTimeUpperBound() > 0) {
-      manager.registerGauge(this, registryName, () -> "" + commitTracker.getTimeUpperBound() + "ms", true, "autoCommitMaxTime",
+      manager.registerGauge(this, registryName, () -> "" + commitTracker.getTimeUpperBound() + "ms", tag, true, "autoCommitMaxTime",
           getCategory().toString(), scope);
     }
     if (softCommitTracker.getDocsUpperBound() > 0) {
-      manager.registerGauge(this, registryName, () -> softCommitTracker.getDocsUpperBound(), true, "softAutoCommitMaxDocs",
+      manager.registerGauge(this, registryName, () -> softCommitTracker.getDocsUpperBound(), tag, true, "softAutoCommitMaxDocs",
           getCategory().toString(), scope);
     }
     if (softCommitTracker.getTimeUpperBound() > 0) {
-      manager.registerGauge(this, registryName, () -> "" + softCommitTracker.getTimeUpperBound() + "ms", true, "softAutoCommitMaxTime",
+      manager.registerGauge(this, registryName, () -> "" + softCommitTracker.getTimeUpperBound() + "ms", tag, true, "softAutoCommitMaxTime",
           getCategory().toString(), scope);
     }
     optimizeCommands = manager.meter(this, registryName, "optimizes", getCategory().toString(), scope);
@@ -187,11 +191,11 @@ public class DirectUpdateHandler2 extends UpdateHandler implements SolrCoreState
     splitCommands = manager.meter(this, registryName, "splits", getCategory().toString(), scope);
     mergeIndexesCommands = manager.meter(this, registryName, "merges", getCategory().toString(), scope);
     expungeDeleteCommands = manager.meter(this, registryName, "expungeDeletes", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> numDocsPending.longValue(), true, "docsPending", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> addCommands.longValue(), true, "adds", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> deleteByIdCommands.longValue(), true, "deletesById", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> deleteByQueryCommands.longValue(), true, "deletesByQuery", getCategory().toString(), scope);
-    manager.registerGauge(this, registryName, () -> numErrors.longValue(), true, "errors", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> numDocsPending.longValue(), tag, true, "docsPending", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> addCommands.longValue(), tag, true, "adds", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> deleteByIdCommands.longValue(), tag, true, "deletesById", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> deleteByQueryCommands.longValue(), tag, true, "deletesByQuery", getCategory().toString(), scope);
+    manager.registerGauge(this, registryName, () -> numErrors.longValue(), tag, true, "errors", getCategory().toString(), scope);
 
     addCommandsCumulative = manager.meter(this, registryName, "cumulativeAdds", getCategory().toString(), scope);
     deleteByIdCommandsCumulative = manager.meter(this, registryName, "cumulativeDeletesById", getCategory().toString(), scope);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/update/PeerSync.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/PeerSync.java b/solr/core/src/java/org/apache/solr/update/PeerSync.java
index 426e0f7..10b3ea1 100644
--- a/solr/core/src/java/org/apache/solr/update/PeerSync.java
+++ b/solr/core/src/java/org/apache/solr/update/PeerSync.java
@@ -171,7 +171,7 @@ public class PeerSync implements SolrMetricProducer {
   public static final String METRIC_SCOPE = "peerSync";
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
     syncTime = manager.timer(null, registry, "time", scope, METRIC_SCOPE);
     syncErrors = manager.counter(null, registry, "errors", scope, METRIC_SCOPE);
     syncSkipped = manager.counter(null, registry, "skipped", scope, METRIC_SCOPE);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
index 049d228..fda5fa5 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java
@@ -86,6 +86,9 @@ public class SolrIndexWriter extends IndexWriter {
   private final AtomicLong runningMajorMergesDocs = new AtomicLong();
   private final AtomicLong runningMinorMergesDocs = new AtomicLong();
 
+  private final SolrMetricManager metricManager;
+  private final String registryName;
+
   public static SolrIndexWriter create(SolrCore core, String name, String path, DirectoryFactory directoryFactory, boolean create, IndexSchema schema, SolrIndexConfig config, IndexDeletionPolicy delPolicy, Codec codec) throws IOException {
 
     SolrIndexWriter w = null;
@@ -113,6 +116,8 @@ public class SolrIndexWriter extends IndexWriter {
     // no metrics
     mergeTotals = false;
     mergeDetails = false;
+    metricManager = null;
+    registryName = null;
   }
 
   private SolrIndexWriter(SolrCore core, String name, String path, Directory directory, boolean create, IndexSchema schema, SolrIndexConfig config, IndexDeletionPolicy delPolicy, Codec codec) throws IOException {
@@ -126,8 +131,8 @@ public class SolrIndexWriter extends IndexWriter {
     infoStream = getConfig().getInfoStream();
     this.directory = directory;
     numOpens.incrementAndGet();
-    SolrMetricManager metricManager = core.getCoreContainer().getMetricManager();
-    String registry = core.getCoreMetricManager().getRegistryName();
+    metricManager = core.getCoreContainer().getMetricManager();
+    registryName = core.getCoreMetricManager().getRegistryName();
     if (config.metricsInfo != null && config.metricsInfo.initArgs != null) {
       Object v = config.metricsInfo.initArgs.get("majorMergeDocs");
       if (v != null) {
@@ -151,20 +156,21 @@ public class SolrIndexWriter extends IndexWriter {
       }
       if (mergeDetails) {
         mergeTotals = true; // override
-        majorMergedDocs = metricManager.meter(null, registry, "docs", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
-        majorDeletedDocs = metricManager.meter(null, registry, "deletedDocs", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
+        majorMergedDocs = metricManager.meter(null, registryName, "docs", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
+        majorDeletedDocs = metricManager.meter(null, registryName, "deletedDocs", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
       }
       if (mergeTotals) {
-        minorMerge = metricManager.timer(null, registry, "minor", SolrInfoBean.Category.INDEX.toString(), "merge");
-        majorMerge = metricManager.timer(null, registry, "major", SolrInfoBean.Category.INDEX.toString(), "merge");
-        mergeErrors = metricManager.counter(null, registry, "errors", SolrInfoBean.Category.INDEX.toString(), "merge");
-        metricManager.registerGauge(null, registry, () -> runningMajorMerges.get(), true, "running", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
-        metricManager.registerGauge(null, registry, () -> runningMinorMerges.get(), true, "running", SolrInfoBean.Category.INDEX.toString(), "merge", "minor");
-        metricManager.registerGauge(null, registry, () -> runningMajorMergesDocs.get(), true, "running.docs", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
-        metricManager.registerGauge(null, registry, () -> runningMinorMergesDocs.get(), true, "running.docs", SolrInfoBean.Category.INDEX.toString(), "merge", "minor");
-        metricManager.registerGauge(null, registry, () -> runningMajorMergesSegments.get(), true, "running.segments", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
-        metricManager.registerGauge(null, registry, () -> runningMinorMergesSegments.get(), true, "running.segments", SolrInfoBean.Category.INDEX.toString(), "merge", "minor");
-        flushMeter = metricManager.meter(null, registry, "flush", SolrInfoBean.Category.INDEX.toString());
+        minorMerge = metricManager.timer(null, registryName, "minor", SolrInfoBean.Category.INDEX.toString(), "merge");
+        majorMerge = metricManager.timer(null, registryName, "major", SolrInfoBean.Category.INDEX.toString(), "merge");
+        mergeErrors = metricManager.counter(null, registryName, "errors", SolrInfoBean.Category.INDEX.toString(), "merge");
+        String tag = core.getMetricTag();
+        metricManager.registerGauge(null, registryName, () -> runningMajorMerges.get(), tag, true, "running", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
+        metricManager.registerGauge(null, registryName, () -> runningMinorMerges.get(), tag, true, "running", SolrInfoBean.Category.INDEX.toString(), "merge", "minor");
+        metricManager.registerGauge(null, registryName, () -> runningMajorMergesDocs.get(), tag, true, "running.docs", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
+        metricManager.registerGauge(null, registryName, () -> runningMinorMergesDocs.get(), tag, true, "running.docs", SolrInfoBean.Category.INDEX.toString(), "merge", "minor");
+        metricManager.registerGauge(null, registryName, () -> runningMajorMergesSegments.get(), tag, true, "running.segments", SolrInfoBean.Category.INDEX.toString(), "merge", "major");
+        metricManager.registerGauge(null, registryName, () -> runningMinorMergesSegments.get(), tag, true, "running.segments", SolrInfoBean.Category.INDEX.toString(), "merge", "minor");
+        flushMeter = metricManager.meter(null, registryName, "flush", SolrInfoBean.Category.INDEX.toString());
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/update/UpdateLog.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateLog.java b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
index 2d6fd98..4ca4bf2 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
@@ -245,6 +245,8 @@ public class UpdateLog implements PluginInfoInitialized, SolrMetricProducer {
   protected Meter applyingBufferedOpsMeter;
   protected Meter replayOpsMeter;
   protected Meter copyOverOldUpdatesMeter;
+  protected SolrMetricManager metricManager;
+  protected String registryName;
 
   public static class LogPtr {
     final long pointer;
@@ -416,7 +418,9 @@ public class UpdateLog implements PluginInfoInitialized, SolrMetricProducer {
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registry;
     bufferedOpsGauge = () -> {
       if (tlog == null) {
         return 0;
@@ -431,13 +435,13 @@ public class UpdateLog implements PluginInfoInitialized, SolrMetricProducer {
       }
     };
 
-    manager.registerGauge(null, registry, bufferedOpsGauge, true, "ops", scope, "buffered");
-    manager.registerGauge(null, registry, () -> logs.size(), true, "logs", scope, "replay", "remaining");
-    manager.registerGauge(null, registry, () -> getTotalLogsSize(), true, "bytes", scope, "replay", "remaining");
+    manager.registerGauge(null, registry, bufferedOpsGauge, tag, true, "ops", scope, "buffered");
+    manager.registerGauge(null, registry, () -> logs.size(), tag, true, "logs", scope, "replay", "remaining");
+    manager.registerGauge(null, registry, () -> getTotalLogsSize(), tag, true, "bytes", scope, "replay", "remaining");
     applyingBufferedOpsMeter = manager.meter(null, registry, "ops", scope, "applyingBuffered");
     replayOpsMeter = manager.meter(null, registry, "ops", scope, "replay");
     copyOverOldUpdatesMeter = manager.meter(null, registry, "ops", scope, "copyOverOldUpdates");
-    manager.registerGauge(null, registry, () -> state.getValue(), true, "state", scope);
+    manager.registerGauge(null, registry, () -> state.getValue(), tag, true, "state", scope);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
index 4ad5106..fa752a0 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
@@ -117,11 +117,11 @@ public class UpdateShardHandler implements SolrMetricProducer, SolrInfoBean {
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
     registry = manager.registry(registryName);
     String expandedScope = SolrMetricManager.mkName(scope, getCategory().name());
-    clientConnectionManager.initializeMetrics(manager, registryName, expandedScope);
-    httpRequestExecutor.initializeMetrics(manager, registryName, expandedScope);
+    clientConnectionManager.initializeMetrics(manager, registryName, tag, expandedScope);
+    httpRequestExecutor.initializeMetrics(manager, registryName, tag, expandedScope);
     updateExecutor = MetricUtils.instrumentedExecutorService(updateExecutor, this, registry,
         SolrMetricManager.mkName("updateExecutor", expandedScope, "threadPool"));
     recoveryExecutor = MetricUtils.instrumentedExecutorService(recoveryExecutor, this, registry,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/483914b6/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
index bd8d368..246777c 100644
--- a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
@@ -92,6 +92,8 @@ public class InstrumentedHttpRequestExecutor extends HttpRequestExecutor impleme
   }
 
   protected MetricRegistry metricsRegistry;
+  protected SolrMetricManager metricManager;
+  protected String registryName;
   protected String scope;
   protected HttpClientMetricNameStrategy nameStrategy;
 
@@ -128,9 +130,10 @@ public class InstrumentedHttpRequestExecutor extends HttpRequestExecutor impleme
   }
 
   @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+  public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+    this.metricManager = manager;
+    this.registryName = registry;
     this.metricsRegistry = manager.registry(registry);
     this.scope = scope;
   }
-
 }