You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2017/05/26 22:25:12 UTC

lucene-solr:branch_6_6: SOLR-10000: Expose cache statistics using metrics API (partial port from master).

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_6_6 e17fee908 -> 692e09835


SOLR-10000: Expose cache statistics using metrics API (partial port from master).

 Conflicts:
	solr/CHANGES.txt


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

Branch: refs/heads/branch_6_6
Commit: 692e09835526170ef4701bcac984b3cbe05fa7c8
Parents: e17fee9
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Wed May 10 21:21:10 2017 +0200
Committer: Steve Rowe <sa...@gmail.com>
Committed: Fri May 26 18:24:35 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   2 +
 .../org/apache/solr/core/CoreContainer.java     |   3 +
 .../apache/solr/core/HdfsDirectoryFactory.java  |  10 +-
 .../src/java/org/apache/solr/core/SolrCore.java |  36 +++-
 .../org/apache/solr/metrics/MetricsMap.java     | 184 +++++++++++++++++++
 .../org/apache/solr/search/FastLRUCache.java    |  13 ++
 .../java/org/apache/solr/search/LFUCache.java   |  12 ++
 .../java/org/apache/solr/search/LRUCache.java   |  12 ++
 .../java/org/apache/solr/search/SolrCache.java  |   3 +-
 .../apache/solr/search/SolrFieldCacheMBean.java |  23 ++-
 .../apache/solr/search/SolrIndexSearcher.java   |  19 +-
 .../apache/solr/store/blockcache/Metrics.java   |  14 +-
 .../solr/store/hdfs/HdfsLocalityReporter.java   |  14 +-
 13 files changed, 337 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index cce7973..c45bb9a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -321,6 +321,8 @@ Other Changes
 
 * SOLR-10644: solr.in.sh installed by install script should be writable by solr user (janhoy)
 
+* SOLR-10000: Expose cache statistics using metrics API. (ab)
+
 * SOLR-10729: Deprecated LatLonType, GeoHashField, SpatialPointVectorFieldType, and SpatialTermQueryPrefixTreeFieldType.
   Instead, switch to LatLonPointSpatialField or SpatialRecursivePrefixTreeFieldType or RptWithGeometrySpatialField.
   (David Smiley)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 d845023..11621f9 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -75,6 +75,7 @@ import org.apache.solr.metrics.SolrCoreMetricManager;
 import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.metrics.SolrMetricProducer;
 import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.search.SolrFieldCacheMBean;
 import org.apache.solr.security.AuthenticationPlugin;
 import org.apache.solr.security.AuthorizationPlugin;
 import org.apache.solr.security.HttpClientInterceptorPlugin;
@@ -520,6 +521,8 @@ public class CoreContainer {
     metricManager.registerGauge(registryName, () -> cfg.getCoreRootDirectory().toFile().getUsableSpace(),
         true, "usableSpace", SolrInfoMBean.Category.CONTAINER.toString(), "fs");
 
+    SolrFieldCacheMBean fieldCacheBean = new SolrFieldCacheMBean();
+    fieldCacheBean.initializeMetrics(metricManager, registryName, null);
     // setup executor to load cores in parallel
     ExecutorService coreLoadExecutor = MetricUtils.instrumentedExecutorService(
         ExecutorUtil.newMDCAwareFixedThreadPool(

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 15f398a..2a437f7 100644
--- a/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
+++ b/solr/core/src/java/org/apache/solr/core/HdfsDirectoryFactory.java
@@ -51,6 +51,8 @@ import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.common.util.NamedList;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
 import org.apache.solr.store.blockcache.BlockCache;
 import org.apache.solr.store.blockcache.BlockDirectory;
 import org.apache.solr.store.blockcache.BlockDirectoryCache;
@@ -70,7 +72,7 @@ import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.RemovalListener;
 import com.google.common.cache.RemovalNotification;
 
-public class HdfsDirectoryFactory extends CachingDirectoryFactory implements SolrCoreAware {
+public class HdfsDirectoryFactory extends CachingDirectoryFactory implements SolrCoreAware, SolrMetricProducer {
   private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   
   public static final String BLOCKCACHE_SLAB_COUNT = "solr.hdfs.blockcache.slab.count";
@@ -493,6 +495,12 @@ 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);
+  }
+
+  @Override
   public Collection<SolrInfoMBean> offerMBeans() {
     return Arrays.<SolrInfoMBean>asList(MetricsHolder.metrics, LocalityHolder.reporter);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 e17266d..4c58d55 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -895,7 +895,11 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
 
     // Initialize JMX
     this.infoRegistry = initInfoRegistry(name, config);
-    infoRegistry.put("fieldCache", new SolrFieldCacheMBean());
+    SolrFieldCacheMBean solrFieldCacheMBean = new SolrFieldCacheMBean();
+    // this is registered at the CONTAINER level because it's not core-specific - for now we
+    // also register it here for back-compat
+    solrFieldCacheMBean.initializeMetrics(metricManager, coreMetricManager.getRegistryName(), "core");
+    infoRegistry.put("fieldCache", solrFieldCacheMBean);
 
     initSchema(config, schema);
 
@@ -997,6 +1001,11 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
       }
     }
 
+    // Allow the directory factory to report metrics
+    if (directoryFactory instanceof SolrMetricProducer) {
+      ((SolrMetricProducer)directoryFactory).initializeMetrics(metricManager, coreMetricManager.getRegistryName(), "directoryFactory");
+    }
+
     // seed version buckets with max from index during core initialization ... requires a searcher!
     seedVersionBuckets();
 
@@ -1128,7 +1137,27 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
     manager.registerGauge(registry, () -> getIndexDir(), true, "indexDir", Category.CORE.toString());
     manager.registerGauge(registry, () -> getIndexSize(), true, "sizeInBytes", Category.INDEX.toString());
     manager.registerGauge(registry, () -> NumberUtils.readableSize(getIndexSize()), true, "size", Category.INDEX.toString());
-    manager.registerGauge(registry, () -> coreContainer.getCoreNames(this), true, "aliases", Category.CORE.toString());
+    if (coreContainer != null) {
+      manager.registerGauge(registry, () -> coreContainer.getCoreNames(this), true, "aliases", Category.CORE.toString());
+      final CloudDescriptor cd = getCoreDescriptor().getCloudDescriptor();
+      if (cd != null) {
+        manager.registerGauge(registry, () -> {
+          if (cd.getCollectionName() != null) {
+            return cd.getCollectionName();
+          } else {
+            return "_notset_";
+          }
+        }, true, "collection", Category.CORE.toString());
+
+        manager.registerGauge(registry, () -> {
+          if (cd.getShardId() != null) {
+            return cd.getShardId();
+          } else {
+            return "_auto_";
+          }
+        }, true, "shard", Category.CORE.toString());
+      }
+    }
     // initialize disk total / free metrics
     Path dataDirPath = Paths.get(dataDir);
     File dataDirFile = dataDirPath.toFile();
@@ -2668,6 +2697,9 @@ public final class SolrCore implements SolrInfoMBean, SolrMetricProducer, Closea
     for (PluginInfo info : pluginInfos) {
       T o = createInitInstance(info,type, type.getSimpleName(), defClassName);
       registry.put(info.name, o);
+      if (o instanceof SolrMetricProducer) {
+        coreMetricManager.registerMetricProducer(type.getSimpleName() + "." + info.name, (SolrMetricProducer)o);
+      }
       if(info.isDefault()){
         def = o;
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/solr/core/src/java/org/apache/solr/metrics/MetricsMap.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/metrics/MetricsMap.java b/solr/core/src/java/org/apache/solr/metrics/MetricsMap.java
new file mode 100644
index 0000000..f43c60b
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/MetricsMap.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.metrics;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.ReflectionException;
+import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiConsumer;
+
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Metric;
+import org.apache.lucene.store.AlreadyClosedException;
+import org.apache.solr.common.SolrException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Dynamically constructed map of metrics, intentionally different from {@link com.codahale.metrics.MetricSet}
+ * where each metric had to be known in advance and registered separately in {@link com.codahale.metrics.MetricRegistry}.
+ * <p>Note: this awkwardly extends {@link Gauge} and not {@link Metric} because awkwardly {@link Metric} instances
+ * are not supported by {@link com.codahale.metrics.MetricRegistryListener} :(</p>
+ * <p>Note 2: values added to this metric map should belong to the list of types supported by JMX:
+ * {@link javax.management.openmbean.OpenType#ALLOWED_CLASSNAMES_LIST}, otherwise only their toString()
+ * representation will be shown in JConsole.</p>
+ */
+public class MetricsMap implements Gauge<Map<String,Object>>, DynamicMBean {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  // set to true to use cached statistics between getMBeanInfo calls to work
+  // around over calling getStatistics on MBeanInfos when iterating over all attributes (SOLR-6586)
+  private final boolean useCachedStatsBetweenGetMBeanInfoCalls = Boolean.getBoolean("useCachedStatsBetweenGetMBeanInfoCalls");
+
+  private BiConsumer<Boolean, Map<String, Object>> initializer;
+  private volatile Map<String,Object> cachedValue;
+
+  public MetricsMap(BiConsumer<Boolean, Map<String,Object>> initializer) {
+    this.initializer = initializer;
+  }
+
+  @Override
+  public Map<String,Object> getValue() {
+    return getValue(true);
+  }
+
+  public Map<String,Object> getValue(boolean detailed) {
+    Map<String,Object> map = new HashMap<>();
+    initializer.accept(detailed, map);
+    return map;
+  }
+
+  public String toString() {
+    return getValue().toString();
+  }
+
+  @Override
+  public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
+    Object val;
+    Map<String,Object> stats = null;
+    if (useCachedStatsBetweenGetMBeanInfoCalls) {
+      Map<String,Object> cachedStats = this.cachedValue;
+      if (cachedStats != null) {
+        stats = cachedStats;
+      }
+    }
+    if (stats == null) {
+      stats = getValue(true);
+    }
+    val = stats.get(attribute);
+
+    if (val != null) {
+      // It's String or one of the simple types, just return it as JMX suggests direct support for such types
+      for (String simpleTypeName : SimpleType.ALLOWED_CLASSNAMES_LIST) {
+        if (val.getClass().getName().equals(simpleTypeName)) {
+          return val;
+        }
+      }
+      // It's an arbitrary object which could be something complex and odd, return its toString, assuming that is
+      // a workable representation of the object
+      return val.toString();
+    }
+    return null;
+  }
+
+  @Override
+  public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+    throw new UnsupportedOperationException("Operation not Supported");
+  }
+
+  @Override
+  public AttributeList getAttributes(String[] attributes) {
+    AttributeList list = new AttributeList();
+    for (String attribute : attributes) {
+      try {
+        list.add(new Attribute(attribute, getAttribute(attribute)));
+      } catch (Exception e) {
+        log.warn("Could not get attribute " + attribute);
+      }
+    }
+    return list;
+  }
+
+  @Override
+  public AttributeList setAttributes(AttributeList attributes) {
+    throw new UnsupportedOperationException("Operation not Supported");
+  }
+
+  @Override
+  public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+    throw new UnsupportedOperationException("Operation not Supported");
+  }
+
+  @Override
+  public MBeanInfo getMBeanInfo() {
+    ArrayList<MBeanAttributeInfo> attrInfoList = new ArrayList<>();
+    Map<String,Object> stats = getValue(true);
+    if (useCachedStatsBetweenGetMBeanInfoCalls) {
+      cachedValue = stats;
+    }
+    try {
+      stats.forEach((k, v) -> {
+        Class type = v.getClass();
+        OpenType typeBox = determineType(type);
+        if (type.equals(String.class) || typeBox == null) {
+          attrInfoList.add(new MBeanAttributeInfo(k, String.class.getName(),
+              null, true, false, false));
+        } else {
+          attrInfoList.add(new OpenMBeanAttributeInfoSupport(
+              k, k, typeBox, true, false, false));
+        }
+      });
+    } catch (Exception e) {
+      // don't log issue if the core is closing
+      if (!(SolrException.getRootCause(e) instanceof AlreadyClosedException))
+        log.warn("Could not get attributes of MetricsMap: {}", this, e);
+    }
+    MBeanAttributeInfo[] attrInfoArr = attrInfoList
+        .toArray(new MBeanAttributeInfo[attrInfoList.size()]);
+    return new MBeanInfo(getClass().getName(), "MetricsMap", attrInfoArr, null, null, null);
+  }
+
+  private OpenType determineType(Class type) {
+    try {
+      for (Field field : SimpleType.class.getFields()) {
+        if (field.getType().equals(SimpleType.class)) {
+          SimpleType candidate = (SimpleType) field.get(SimpleType.class);
+          if (candidate.getTypeName().equals(type.getName())) {
+            return candidate;
+          }
+        }
+      }
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+    return null;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 9c4b892..3ebff0a 100644
--- a/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
@@ -15,7 +15,10 @@
  * limitations under the License.
  */
 package org.apache.solr.search;
+
 import org.apache.solr.common.SolrException;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.util.ConcurrentLRUCache;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -274,9 +277,19 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>
   }
 
   @Override
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsMap metrics = new MetricsMap((detailed, map) -> {
+      NamedList nl = getStatistics();
+      map.putAll(nl.asMap(5));
+    });
+    manager.registerGauge(registry, metrics, true, scope, getCategory().toString());
+  }
+
+  @Override
   public String toString() {
     return name() + getStatistics().toString();
   }
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 2b593c6..71c29fa 100644
--- a/solr/core/src/java/org/apache/solr/search/LFUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/LFUCache.java
@@ -28,6 +28,8 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.SolrCore;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.util.ConcurrentLFUCache;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -301,7 +303,17 @@ public class LFUCache<K, V> implements SolrCache<K, V> {
   }
 
   @Override
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsMap metrics = new MetricsMap((detailed, map) -> {
+      NamedList nl = getStatistics();
+      map.putAll(nl.asMap(5));
+    });
+    manager.registerGauge(registry, metrics, true, scope, getCategory().toString());
+  }
+
+  @Override
   public String toString() {
     return name + getStatistics().toString();
   }
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 b178fb2..1983820 100644
--- a/solr/core/src/java/org/apache/solr/search/LRUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/LRUCache.java
@@ -31,6 +31,8 @@ import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -55,6 +57,7 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
   static final long LINKED_HASHTABLE_RAM_BYTES_PER_ENTRY =
       HASHTABLE_RAM_BYTES_PER_ENTRY
           + 2 * RamUsageEstimator.NUM_BYTES_OBJECT_REF; // previous & next references
+
   /// End copied code
 
   /* An instance of this class will be shared across multiple instances
@@ -356,6 +359,15 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
   }
 
   @Override
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsMap metrics = new MetricsMap((detailed, map) -> {
+      NamedList nl = getStatistics();
+      map.putAll(nl.asMap(5));
+    });
+    manager.registerGauge(registry, metrics, true, scope, getCategory().toString());
+  }
+
+  @Override
   public String toString() {
     return name() + getStatistics().toString();
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/solr/core/src/java/org/apache/solr/search/SolrCache.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/SolrCache.java b/solr/core/src/java/org/apache/solr/search/SolrCache.java
index 9a2d0fc..cc57e12 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrCache.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrCache.java
@@ -17,6 +17,7 @@
 package org.apache.solr.search;
 
 import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.metrics.SolrMetricProducer;
 
 import java.util.Map;
 
@@ -24,7 +25,7 @@ import java.util.Map;
 /**
  * Primary API for dealing with Solr's internal caches.
  */
-public interface SolrCache<K,V> extends SolrInfoMBean {
+public interface SolrCache<K,V> extends SolrInfoMBean, SolrMetricProducer {
 
   /**
    * The initialization routine. Instance specific arguments are passed in

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java
index 642b708..9ac4e8a 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java
@@ -22,13 +22,16 @@ import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.JmxMonitoredMap.JmxAugmentedSolrInfoMBean;
 import org.apache.solr.core.SolrCore;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
 import org.apache.solr.uninverting.UninvertingReader;
 
 /**
  * A SolrInfoMBean that provides introspection of the Solr FieldCache
  *
  */
-public class SolrFieldCacheMBean implements JmxAugmentedSolrInfoMBean {
+public class SolrFieldCacheMBean implements JmxAugmentedSolrInfoMBean, SolrMetricProducer {
 
   private boolean disableEntryList = Boolean.getBoolean("disableSolrFieldCacheMBeanEntryList");
   private boolean disableJmxEntryList = Boolean.getBoolean("disableSolrFieldCacheMBeanEntryListJmx");
@@ -75,4 +78,22 @@ public class SolrFieldCacheMBean implements JmxAugmentedSolrInfoMBean {
     return stats;
   }
 
+  @Override
+  public void initializeMetrics(SolrMetricManager manager, String registryName, String scope) {
+    MetricsMap metricsMap = new MetricsMap((detailed, map) -> {
+      if (detailed && !disableEntryList && !disableJmxEntryList) {
+        UninvertingReader.FieldCacheStats fieldCacheStats = UninvertingReader.getUninvertedStats();
+        String[] entries = fieldCacheStats.info;
+        map.put("entries_count", entries.length);
+        map.put("total_size", fieldCacheStats.totalSize);
+        for (int i = 0; i < entries.length; i++) {
+          final String entry = entries[i];
+          map.put("entry#" + i, entry);
+        }
+      } else {
+        map.put("entries_count", UninvertingReader.getUninvertedStatsSize());
+      }
+    });
+    manager.register(registryName, metricsMap, true, "fieldCache", Category.CACHE.toString(), scope);
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 0e5276a..997ecb9 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
@@ -67,6 +67,9 @@ import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrInfoMBean;
 import org.apache.solr.index.SlowCompositeReaderWrapper;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestInfo;
@@ -86,7 +89,7 @@ import org.slf4j.LoggerFactory;
  *
  * @since solr 0.9
  */
-public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrInfoMBean {
+public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrInfoMBean, SolrMetricProducer {
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
@@ -430,6 +433,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();
+    for (SolrCache cache : cacheList) {
+      cache.initializeMetrics(manager, registry, SolrMetricManager.mkName(cache.name(), STATISTICS_KEY));
+    }
+    initializeMetrics(manager, registry, STATISTICS_KEY);
     registerTime = new Date();
   }
 
@@ -2251,6 +2260,14 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
     return lst;
   }
 
+  @Override
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsMap metrics = new MetricsMap((detailed, map) -> {
+      map.putAll(getStatistics().asMap(5));
+    });
+    manager.registerGauge(registry, metrics, true, scope, Category.SEARCHER.toString());
+  }
+
   private static class FilterImpl extends Filter {
     private final Filter topFilter;
     private final List<Weight> weights;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 d3e3497..cb423ed 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
@@ -22,6 +22,9 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
 import org.apache.solr.search.SolrCacheBase;
 
 /**
@@ -29,7 +32,7 @@ import org.apache.solr.search.SolrCacheBase;
  *
  * @lucene.experimental
  */
-public class Metrics extends SolrCacheBase implements SolrInfoMBean {
+public class Metrics extends SolrCacheBase implements SolrInfoMBean, SolrMetricProducer {
 
 
   public AtomicLong blockCacheSize = new AtomicLong(0);
@@ -101,6 +104,15 @@ public class Metrics extends SolrCacheBase implements SolrInfoMBean {
     return stats;
   }
 
+  @Override
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsMap metrics = new MetricsMap((detailed, map) -> {
+      NamedList nl = getStatistics();
+      map.putAll(nl.asMap(5));
+    });
+    manager.registerGauge(registry, metrics, true, getName(), getCategory().toString(), scope);
+  }
+
   private float getPerSecond(long value, double seconds) {
     return (float) (value / seconds);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/692e0983/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 ba7c7fd..c905877 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
@@ -33,10 +33,13 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class HdfsLocalityReporter implements SolrInfoMBean {
+public class HdfsLocalityReporter implements SolrInfoMBean, SolrMetricProducer {
   public static final String LOCALITY_BYTES_TOTAL = "locality.bytes.total";
   public static final String LOCALITY_BYTES_LOCAL = "locality.bytes.local";
   public static final String LOCALITY_BYTES_RATIO = "locality.bytes.ratio";
@@ -133,6 +136,15 @@ public class HdfsLocalityReporter implements SolrInfoMBean {
     return createStatistics(totalBytes, localBytes, totalCount, localCount);
   }
 
+  @Override
+  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+    MetricsMap metrics = new MetricsMap((detailed, map) -> {
+      NamedList nl = getStatistics();
+      map.putAll(nl.asMap(5));
+    });
+    manager.registerGauge(registry, metrics, true, "hdfsLocality", getCategory().toString(), scope);
+  }
+
   /**
    * Generate a statistics object based on the given measurements for all files monitored by this reporter.
    *