mirror of https://github.com/apache/lucene.git
SOLR-9960 MetricsHandler should support multiple prefixes.
This commit is contained in:
parent
64b86331c2
commit
53d5af17da
|
@ -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)
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
Set<String> validRegistries = new HashSet<>();
|
||||
for (String r : container.getMetricManager().registryNames()) {
|
||||
for (String prefix : initialPrefixes) {
|
||||
if (r.startsWith(prefix)) {
|
||||
validRegistries.add(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return validRegistries;
|
||||
}
|
||||
|
||||
private List<MetricType> parseMetricTypes(SolrQueryRequest req) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -65,6 +65,26 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
|
|||
assertNotNull(values.get("solr.jetty"));
|
||||
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();
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue