You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2017/01/14 09:41:25 UTC
lucene-solr:branch_6x: SOLR-9960 MetricsHandler should support
multiple prefixes.
Repository: lucene-solr
Updated Branches:
refs/heads/branch_6x 21b8dbf6b -> e37b777e1
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/e37b777e
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/e37b777e
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/e37b777e
Branch: refs/heads/branch_6x
Commit: e37b777e1abf3b4b7eae3b38b16e0b767517945d
Parents: 21b8dbf
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 10:40:27 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/e37b777e/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index e2c6ad6..b95b3a3 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -135,14 +135,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-9880: Add Ganglia, Graphite and SLF4J metrics reporters. (ab)
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e37b777e/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/e37b777e/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/e37b777e/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);