You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2017/01/16 00:10:58 UTC

[40/50] [abbrv] lucene-solr:jira/solr-5944: SOLR-9960 MetricsHandler should support multiple prefixes.

SOLR-9960 MetricsHandler should support multiple prefixes.


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

Branch: refs/heads/jira/solr-5944
Commit: 53d5af17dac5e2c27f1304b029cbd09461ea197b
Parents: 64b8633
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Fri Jan 13 19:24:40 2017 +0100
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Sat Jan 14 09:52:15 2017 +0100

----------------------------------------------------------------------
 solr/CHANGES.txt                                | 14 +--
 .../solr/handler/admin/MetricsHandler.java      | 92 +++++++++++++-------
 .../apache/solr/metrics/SolrMetricManager.java  | 30 ++++---
 .../solr/handler/admin/MetricsHandlerTest.java  | 26 +++++-
 4 files changed, 109 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/53d5af17/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index b6055fe..ccc5d7c 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -196,14 +196,16 @@ New Features
 
 * SOLR-9805: Use metrics-jvm library to instrument jvm internals such as GC, memory usage and others. (shalin)
 
-* SOLR-9812: SOLR-9911: Added a new /admin/metrics API to return all metrics collected by Solr via API.
-  API supports three optional parameters:
+* SOLR-9812: SOLR-9911, SOLR-9960: Added a new /admin/metrics API to return all metrics collected by Solr via API.
+  API supports four optional multi-valued parameters:
   * 'group' (all,jvm,jetty,node,core),
-  * 'type' (all,counter,timer,gauge,histogram) both of which are multi-valued
-  * 'prefix' that filters the returned metrics
+  * 'type' (all,counter,timer,gauge,histogram),
+  * 'prefix' that filters the returned metrics,
+  * 'registry' that selects one or more registries by prefix (eg. solr.jvm,solr.core.collection1)
   Example: http://localhost:8983/solr/admin/metrics?group=jvm,jetty&type=counter
-  Example: http://localhost:8983/solr/admin/metrics?group=jvm&prefix=buffers
-  (shalin)
+  Example: http://localhost:8983/solr/admin/metrics?group=jvm&prefix=buffers,os
+  Example: http://localhost:8983/solr/admin/metrics?registry=solr.node,solr.core&prefix=ADMIN
+  (shalin, ab)
 
 * SOLR-9884: Add version to segments handler output (Steven Bower via Erick Erickson)
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/53d5af17/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java
index 0c87875..385317b 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java
@@ -18,9 +18,10 @@
 package org.apache.solr.handler.admin;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import com.codahale.metrics.Counter;
@@ -34,7 +35,6 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.RequestHandlerBase;
 import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.request.SolrQueryRequest;
@@ -74,59 +74,85 @@ public class MetricsHandler extends RequestHandlerBase implements PermissionName
     MetricFilter mustMatchFilter = parseMustMatchFilter(req);
     List<MetricType> metricTypes = parseMetricTypes(req);
     List<MetricFilter> metricFilters = metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList());
-    List<Group> requestedGroups = parseGroups(req);
+    Set<String> requestedRegistries = parseRegistries(req);
 
     NamedList response = new NamedList();
-    for (Group group : requestedGroups) {
-      String registryName = SolrMetricManager.getRegistryName(group);
-      if (group == Group.core) {
-        // this requires special handling because of the way we create registry name for a core (deeply nested)
-        container.getAllCoreNames().forEach(s -> {
-          String coreRegistryName;
-          try (SolrCore core = container.getCore(s)) {
-            coreRegistryName = core.getCoreMetricManager().getRegistryName();
-          }
-          MetricRegistry registry = metricManager.registry(coreRegistryName);
-          response.add(coreRegistryName, MetricUtils.toNamedList(registry, metricFilters, mustMatchFilter));
-        });
-      } else {
-        MetricRegistry registry = metricManager.registry(registryName);
-        response.add(registryName, MetricUtils.toNamedList(registry, metricFilters, mustMatchFilter));
-      }
+    for (String registryName : requestedRegistries) {
+      MetricRegistry registry = metricManager.registry(registryName);
+      response.add(registryName, MetricUtils.toNamedList(registry, metricFilters, mustMatchFilter));
     }
     rsp.getValues().add("metrics", response);
   }
 
   private MetricFilter parseMustMatchFilter(SolrQueryRequest req) {
-    String prefix = req.getParams().get("prefix");
+    String[] prefixes = req.getParams().getParams("prefix");
     MetricFilter mustMatchFilter;
-    if (prefix != null) {
-      mustMatchFilter = new SolrMetricManager.PrefixFilter(prefix.trim());
+    if (prefixes != null && prefixes.length > 0) {
+      Set<String> prefixSet = new HashSet<>();
+      for (String prefix : prefixes) {
+        prefixSet.addAll(StrUtils.splitSmart(prefix, ','));
+      }
+      mustMatchFilter = new SolrMetricManager.PrefixFilter((String[])prefixSet.toArray(new String[prefixSet.size()]));
     } else  {
       mustMatchFilter = MetricFilter.ALL;
     }
     return mustMatchFilter;
   }
 
-  private List<Group> parseGroups(SolrQueryRequest req) {
+  private Set<String> parseRegistries(SolrQueryRequest req) {
     String[] groupStr = req.getParams().getParams("group");
-    List<String> groups = Collections.emptyList();
+    String[] registryStr = req.getParams().getParams("registry");
+    if ((groupStr == null || groupStr.length == 0) && (registryStr == null || registryStr.length == 0)) {
+      // return all registries
+      return container.getMetricManager().registryNames();
+    }
+    boolean allRegistries = false;
+    Set<String> initialPrefixes = Collections.emptySet();
     if (groupStr != null && groupStr.length > 0) {
-      groups = new ArrayList<>();
+      initialPrefixes = new HashSet<>();
       for (String g : groupStr) {
-        groups.addAll(StrUtils.splitSmart(g, ','));
+        List<String> split = StrUtils.splitSmart(g, ',');
+        for (String s : split) {
+          if (s.trim().equals("all")) {
+            allRegistries = true;
+            break;
+          }
+          initialPrefixes.add(SolrMetricManager.overridableRegistryName(s.trim()));
+        }
+        if (allRegistries) {
+          return container.getMetricManager().registryNames();
+        }
       }
     }
 
-    List<Group> requestedGroups = Arrays.asList(Group.values()); // by default we return all groups
-    try {
-      if (groups.size() > 0 && !groups.contains("all")) {
-        requestedGroups = groups.stream().map(String::trim).map(Group::valueOf).collect(Collectors.toList());
+    if (registryStr != null && registryStr.length > 0) {
+      if (initialPrefixes.isEmpty()) {
+        initialPrefixes = new HashSet<>();
+      }
+      for (String r : registryStr) {
+        List<String> split = StrUtils.splitSmart(r, ',');
+        for (String s : split) {
+          if (s.trim().equals("all")) {
+            allRegistries = true;
+            break;
+          }
+          initialPrefixes.add(SolrMetricManager.overridableRegistryName(s.trim()));
+        }
+        if (allRegistries) {
+          return container.getMetricManager().registryNames();
+        }
+      }
+    }
+    Set<String> validRegistries = new HashSet<>();
+    for (String r : container.getMetricManager().registryNames()) {
+      for (String prefix : initialPrefixes) {
+        if (r.startsWith(prefix)) {
+          validRegistries.add(r);
+          break;
+        }
       }
-    } catch (IllegalArgumentException e) {
-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Invalid group in: " + groups + " specified. Must be one of (all, jvm, jetty, http, node, core)", e);
     }
-    return requestedGroups;
+    return validRegistries;
   }
 
   private List<MetricType> parseMetricTypes(SolrQueryRequest req) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/53d5af17/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 9f126ed..caa8906 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -93,31 +93,37 @@ public class SolrMetricManager {
    * with names that start with a prefix.
    */
   public static class PrefixFilter implements MetricFilter {
-    private final String prefix;
+    private final String[] prefixes;
     private final Set<String> matched = new HashSet<>();
+    private boolean allMatch = false;
 
     /**
      * Create a filter that uses the provided prefix.
-     * @param prefix prefix to use, must not be null. If empty then any
-     *               name will match.
+     * @param prefixes prefixes to use, must not be null. If empty then any
+     *               name will match, if not empty then match on any prefix will
+     *                 succeed (logical OR).
      */
-    public PrefixFilter(String prefix) {
-      Objects.requireNonNull(prefix);
-      this.prefix = prefix;
+    public PrefixFilter(String... prefixes) {
+      Objects.requireNonNull(prefixes);
+      this.prefixes = prefixes;
+      if (prefixes.length == 0) {
+        allMatch = true;
+      }
     }
 
     @Override
     public boolean matches(String name, Metric metric) {
-      if (prefix.isEmpty()) {
+      if (allMatch) {
         matched.add(name);
         return true;
       }
-      if (name.startsWith(prefix)) {
-        matched.add(name);
-        return true;
-      } else {
-        return false;
+      for (String prefix : prefixes) {
+        if (name.startsWith(prefix)) {
+          matched.add(name);
+          return true;
+        }
       }
+      return false;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/53d5af17/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java
index edab3ce..a1b29db 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java
@@ -66,6 +66,26 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
     assertNotNull(values.get("solr.jvm"));
 
     resp = new SolrQueryResponse();
+    // "collection" works too, because it's a prefix for "collection1"
+    handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", "registry", "solr.core.collection,solr.jvm"), resp);
+    values = resp.getValues();
+    assertNotNull(values.get("metrics"));
+    values = (NamedList) values.get("metrics");
+    assertEquals(2, values.size());
+    assertNotNull(values.get("solr.core.collection1"));
+    assertNotNull(values.get("solr.jvm"));
+
+    resp = new SolrQueryResponse();
+    // "collection" works too, because it's a prefix for "collection1"
+    handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", "registry", "solr.core.collection", "registry", "solr.jvm"), resp);
+    values = resp.getValues();
+    assertNotNull(values.get("metrics"));
+    values = (NamedList) values.get("metrics");
+    assertEquals(2, values.size());
+    assertNotNull(values.get("solr.core.collection1"));
+    assertNotNull(values.get("solr.jvm"));
+
+    resp = new SolrQueryResponse();
     handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", "group", "jvm,jetty"), resp);
     values = resp.getValues();
     assertNotNull(values.get("metrics"));
@@ -94,7 +114,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
     assertNull(values.get("ADMIN./admin/authorization.errors")); // this is a timer node
 
     resp = new SolrQueryResponse();
-    handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", "prefix", "CONTAINER.cores"), resp);
+    handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", "prefix", "CONTAINER.cores,CONTAINER.threadPool"), resp);
     values = resp.getValues();
     assertNotNull(values.get("metrics"));
     values = (NamedList) values.get("metrics");
@@ -102,10 +122,12 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
     assertEquals(0, ((NamedList)values.get("solr.jvm")).size());
     assertEquals(0, ((NamedList)values.get("solr.jetty")).size());
     assertEquals(0, ((NamedList)values.get("solr.core.collection1")).size());
-    assertEquals(3, ((NamedList)values.get("solr.node")).size());
+    assertEquals(11, ((NamedList)values.get("solr.node")).size());
     assertNotNull(values.get("solr.node"));
     values = (NamedList) values.get("solr.node");
     assertNotNull(values.get("CONTAINER.cores.lazy")); // this is a gauge node
+    assertNotNull(values.get("CONTAINER.threadPool.coreContainerWorkExecutor.completed"));
+    assertNotNull(values.get("CONTAINER.threadPool.coreLoadExecutor.completed"));
 
     resp = new SolrQueryResponse();
     handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", "group", "jvm", "prefix", "CONTAINER.cores"), resp);