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 2019/10/15 10:52:04 UTC
[lucene-solr] 01/03: SOLR-13677: All Metrics Gauges should be
unregistered by the objects that registered them (#836)
This is an automated email from the ASF dual-hosted git repository.
ab pushed a commit to branch jira/solr-13677-final
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
commit 36475541930efdc392fe5f64f1b4bf8439f8a3bd
Author: Noble Paul <no...@users.noreply.github.com>
AuthorDate: Mon Aug 19 19:48:06 2019 +1000
SOLR-13677: All Metrics Gauges should be unregistered by the objects that registered them (#836)
* SOLR-13677: All Metrics Gauges should be unregistered by the objects that registered them
---
.../solr/handler/dataimport/DataImportHandler.java | 8 +-
.../org/apache/solr/cloud/ReplicateFromLeader.java | 2 +-
.../src/java/org/apache/solr/core/PluginBag.java | 3 +-
.../src/java/org/apache/solr/core/SolrCore.java | 2 +-
.../apache/solr/handler/ReplicationHandler.java | 47 ++++---
.../apache/solr/handler/RequestHandlerBase.java | 48 +++----
.../solr/handler/admin/CoreAdminHandler.java | 9 +-
.../solr/handler/component/SuggestComponent.java | 23 ++--
.../org/apache/solr/metrics/SolrMetricManager.java | 78 ++++++++---
.../apache/solr/metrics/SolrMetricProducer.java | 52 ++++++--
.../java/org/apache/solr/metrics/SolrMetrics.java | 94 +++++++++++++
.../java/org/apache/solr/search/FastLRUCache.java | 50 +++----
.../src/java/org/apache/solr/search/LFUCache.java | 23 +++-
.../src/java/org/apache/solr/search/LRUCache.java | 31 +++--
.../org/apache/solr/search/SolrCacheHolder.java | 8 +-
.../apache/solr/security/AuthenticationPlugin.java | 55 ++++----
.../solr/handler/admin/MetricsHandlerTest.java | 146 +++++++++++++++++++--
.../org/apache/solr/common/util/ExecutorUtil.java | 1 +
18 files changed, 499 insertions(+), 181 deletions(-)
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 50938e4..80d374e 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
@@ -36,7 +36,7 @@ import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetrics;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.RawResponseWriter;
import org.apache.solr.response.SolrQueryResponse;
@@ -275,8 +275,8 @@ public class DataImportHandler extends RequestHandlerBase implements
}
@Override
- public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
- super.initializeMetrics(manager, registryName, tag, scope);
+ public void initializeMetrics(SolrMetrics m) {
+ super.initializeMetrics(m);
metrics = new MetricsMap((detailed, map) -> {
if (importer != null) {
DocBuilder.Statistics cumulative = importer.cumulativeStatistics;
@@ -299,7 +299,7 @@ public class DataImportHandler extends RequestHandlerBase implements
map.put(DataImporter.MSG.TOTAL_DOCS_SKIPPED, cumulative.skipDocCount);
}
});
- manager.registerGauge(this, registryName, metrics, tag, true, "importer", getCategory().toString(), scope);
+ solrMetrics.gauge(this, metrics, true, "importer", getCategory().toString());
}
// //////////////////////SolrInfoMBeans methods //////////////////////
diff --git a/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java b/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java
index 957b321..17a6ec3 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ReplicateFromLeader.java
@@ -133,7 +133,7 @@ public class ReplicateFromLeader {
public void stopReplication() {
if (replicationProcess != null) {
- replicationProcess.close();
+ replicationProcess.shutdown();
}
}
}
diff --git a/solr/core/src/java/org/apache/solr/core/PluginBag.java b/solr/core/src/java/org/apache/solr/core/PluginBag.java
index 6088f52..a05f18e 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginBag.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginBag.java
@@ -192,10 +192,11 @@ public class PluginBag<T> implements AutoCloseable {
PluginHolder<T> pluginHolder = new PluginHolder<>(null, plugin);
pluginHolder.registerAPI = false;
PluginHolder<T> old = put(name, pluginHolder);
+ if(old != null) closeQuietly(old);
return old == null ? null : old.get();
}
- PluginHolder<T> put(String name, PluginHolder<T> plugin) {
+ public PluginHolder<T> put(String name, PluginHolder<T> plugin) {
Boolean registerApi = null;
Boolean disableHandler = null;
if (plugin.pluginInfo != null) {
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 3e2fb1e..9bfade2 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -231,7 +231,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());
+ private final String metricTag = getUniqueMetricTag(null);
public volatile boolean searchEnabled = true;
public volatile boolean indexEnabled = true;
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 dc1d1b1..76ecbec 100644
--- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
@@ -92,7 +92,7 @@ import org.apache.solr.core.backup.repository.BackupRepository;
import org.apache.solr.core.backup.repository.LocalFileSystemRepository;
import org.apache.solr.handler.IndexFetcher.IndexFetchResult;
import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetrics;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.SolrIndexSearcher;
@@ -863,21 +863,20 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw
}
@Override
- public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
- super.initializeMetrics(manager, registry, tag, scope);
-
- manager.registerGauge(this, registry, () -> (core != null && !core.isClosed() ? 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.isClosed() ? 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);
+ public void initializeMetrics(SolrMetrics m) {
+ super.initializeMetrics(m);
+ solrMetrics.gauge(this, () -> (core != null && !core.isClosed() ? NumberUtils.readableSize(core.getIndexSize()) : ""),
+ true, "indexSize", getCategory().toString());
+ solrMetrics.gauge(this, () -> (core != null && !core.isClosed() ? getIndexVersion().toString() : ""),
+ true, "indexVersion", getCategory().toString());
+ solrMetrics.gauge(this, () -> (core != null && !core.isClosed() ? getIndexVersion().generation : 0),
+ true, GENERATION, getCategory().toString());
+ solrMetrics.gauge(this, () -> (core != null && !core.isClosed() ? core.getIndexDir() : ""),
+ true, "indexPath", getCategory().toString());
+ solrMetrics.gauge(this, () -> isMaster,
+ true, "isMaster", getCategory().toString());
+ solrMetrics.gauge(this, () -> isSlave,
+ true, "isSlave", getCategory().toString());
final MetricsMap fetcherMap = new MetricsMap((detailed, map) -> {
IndexFetcher fetcher = currentIndexFetcher;
if (fetcher != null) {
@@ -906,13 +905,13 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw
addVal(map, IndexFetcher.CONF_FILES_REPLICATED, props, String.class);
}
});
- 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);
+ solrMetrics.gauge(this , fetcherMap, true, "fetcher", getCategory().toString());
+ solrMetrics.gauge(this, () -> isMaster && includeConfFiles != null ? includeConfFiles : "",
+ true, "confFilesToReplicate", getCategory().toString());
+ solrMetrics.gauge(this, () -> isMaster ? getReplicateAfterStrings() : Collections.<String>emptyList(),
+ true, REPLICATE_AFTER, getCategory().toString());
+ solrMetrics.gauge(this, () -> isMaster && replicationEnabled.get(),
+ true, "replicationEnabled", getCategory().toString());
}
//TODO Should a failure retrieving any piece of info mark the overall request as a failure? Is there a core set of values that are required to make a response here useful?
@@ -1387,7 +1386,7 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw
});
}
- public void close() {
+ public void shutdown() {
if (executorService != null) executorService.shutdown();
if (pollingIndexFetcher != null) {
pollingIndexFetcher.destroy();
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 eca391b..499db95 100644
--- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
@@ -22,11 +22,14 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import com.codahale.metrics.MetricRegistry;
-import com.google.common.collect.ImmutableList;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
+import com.google.common.collect.ImmutableList;
+import org.apache.solr.api.Api;
+import org.apache.solr.api.ApiBag;
+import org.apache.solr.api.ApiSupport;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
@@ -36,16 +39,13 @@ import org.apache.solr.core.PluginBag;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrInfoBean;
import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
import org.apache.solr.metrics.SolrMetricProducer;
+import org.apache.solr.metrics.SolrMetrics;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.util.SolrPluginUtils;
-import org.apache.solr.api.Api;
-import org.apache.solr.api.ApiBag;
-import org.apache.solr.api.ApiSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -79,9 +79,6 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
private PluginInfo pluginInfo;
private Set<String> metricNames = ConcurrentHashMap.newKeySet();
- private MetricRegistry registry;
- protected String registryName;
- protected SolrMetricManager metricManager;
@SuppressForbidden(reason = "Need currentTimeMillis, used only for stats output")
@@ -143,22 +140,27 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
}
+ protected SolrMetrics solrMetrics;
+
+ @Override
+ public SolrMetrics getMetrics() {
+ return solrMetrics;
+ }
+
@Override
- 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);
- numTimeouts = manager.meter(this, registryName, "timeouts", getCategory().toString(), scope);
- requests = manager.counter(this, registryName, "requests", getCategory().toString(), scope);
+ public void initializeMetrics(SolrMetrics m) {
+ this.solrMetrics = m.getChildInfo(this);
+ numErrors = solrMetrics.meter(this, "errors", getCategory().toString());
+ numServerErrors = solrMetrics.meter(this, "serverErrors", getCategory().toString());
+ numClientErrors = solrMetrics.meter(this, "clientErrors", getCategory().toString());
+ numTimeouts = solrMetrics.meter(this, "timeouts", getCategory().toString());
+ requests = solrMetrics.counter(this, "requests", getCategory().toString());
MetricsMap metricsMap = new MetricsMap((detail, map) ->
shardPurposes.forEach((k, v) -> map.put(k, v.getCount())));
- 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, tag, true, "handlerStart", getCategory().toString(), scope);
+ solrMetrics.gauge(this, metricsMap, true, "shardRequests", getCategory().toString());
+ requestTimes = solrMetrics.timer(this,"requestTimes", getCategory().toString());
+ totalTime = solrMetrics.counter(this, "totalTime", getCategory().toString());
+ solrMetrics.gauge(this, () -> handlerStart, true, "handlerStart", getCategory().toString());
}
public static SolrParams getSolrParamsFromNamedList(NamedList args, String key) {
@@ -274,7 +276,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
@Override
public MetricRegistry getMetricRegistry() {
- return registry;
+ return solrMetrics.getRegistry();
}
@Override
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 45cb063..ae22555 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
@@ -46,6 +46,7 @@ import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.logging.MDCLoggingContext;
import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetrics;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.security.AuthorizationContext;
@@ -120,10 +121,10 @@ public class CoreAdminHandler extends RequestHandlerBase implements PermissionNa
}
@Override
- 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"));
+ public void initializeMetrics(SolrMetrics m) {
+ super.initializeMetrics(m);
+ parallelExecutor = MetricUtils.instrumentedExecutorService(parallelExecutor, this, solrMetrics.getRegistry(),
+ SolrMetricManager.mkName("parallelCoreAdminExecutor", getCategory().name(), solrMetrics.scope, "threadPool"));
}
@Override
public Boolean registerV2() {
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 2d6fdb1..00d8697 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
@@ -48,8 +48,8 @@ import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrEventListener;
import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
import org.apache.solr.metrics.SolrMetricProducer;
+import org.apache.solr.metrics.SolrMetrics;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.spelling.suggest.SolrSuggester;
import org.apache.solr.spelling.suggest.SuggesterOptions;
@@ -88,9 +88,6 @@ 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}
*/
@@ -350,19 +347,25 @@ public class SuggestComponent extends SearchComponent implements SolrCoreAware,
return "Suggester component";
}
+ protected SolrMetrics metricsInfo;
+
+ @Override
+ public SolrMetrics getMetrics() {
+ return metricsInfo;
+ }
+
@Override
- 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(), tag, true, "totalSizeInBytes", getCategory().toString(), scope);
+ public void initializeMetrics(SolrMetrics info) {
+ this.metricsInfo = info.getChildInfo(this);
+
+ metricsInfo.metricManager.registerGauge(this, info.registry, () -> ramBytesUsed(), metricsInfo.tag, true, "totalSizeInBytes", getCategory().toString(), metricsInfo.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, tag, true, "suggesters", getCategory().toString(), scope);
+ metricsInfo.metricManager.registerGauge(this, metricsInfo.registry, suggestersMap, metricsInfo.tag, true, "suggesters", getCategory().toString(), metricsInfo.scope);
}
@Override
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 7d2877d..187598d 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java
@@ -607,10 +607,14 @@ public class SolrMetricManager {
*/
public Meter meter(SolrInfoBean info, String registry, String metricName, String... metricPath) {
final String name = mkName(metricName, metricPath);
+ return meter(info, registry(registry), name);
+ }
+
+ public Meter meter(SolrInfoBean info, MetricRegistry registry, String metricsPath) {
if (info != null) {
- info.registerMetricName(name);
+ info.registerMetricName(metricsPath);
}
- return registry(registry).meter(name, meterSupplier);
+ return registry.meter(metricsPath, meterSupplier);
}
/**
@@ -630,6 +634,14 @@ public class SolrMetricManager {
return registry(registry).timer(name, timerSupplier);
}
+ public Timer timer(SolrInfoBean info, MetricRegistry registry, String name) {
+ if (info != null) {
+ info.registerMetricName(name);
+ }
+ return registry.timer(name, timerSupplier);
+
+ }
+
/**
* Create or get an existing named {@link Counter}
*
@@ -641,10 +653,15 @@ public class SolrMetricManager {
*/
public Counter counter(SolrInfoBean info, String registry, String metricName, String... metricPath) {
final String name = mkName(metricName, metricPath);
+ return counter(info, registry(registry), name);
+ }
+
+ public Counter counter(SolrInfoBean info, MetricRegistry registry, String name) {
if (info != null) {
info.registerMetricName(name);
}
- return registry(registry).counter(name, counterSupplier);
+ return registry.counter(name, counterSupplier);
+
}
/**
@@ -690,13 +707,27 @@ public class SolrMetricManager {
}
}
- /**
- * 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 void registerGauge(SolrInfoBean info, MetricRegistry registry, Gauge<?> g, boolean force, String name) {
+ if (info != null) {
+ info.registerMetricName(name);
+ }
+ synchronized (registry) {
+ if (force && registry.getMetrics().containsKey(name)) {
+ registry.remove(name);
+ }
+ registry.register(name, g);
+ }
+
+ }
+
+
+ /**
+ * 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;
@@ -724,20 +755,22 @@ public class SolrMetricManager {
registerMetric(info, registry, new GaugeWrapper(gauge, tag), force, metricName, metricPath);
}
- public int unregisterGauges(String registryName, String tag) {
- if (tag == null) {
+ public int unregisterGauges(String registryName, String tagSegment) {
+ if (tagSegment == null) {
return 0;
}
MetricRegistry registry = registry(registryName);
+ if (registry == null) return 0;
AtomicInteger removed = new AtomicInteger();
registry.removeMatching((name, metric) -> {
- if (metric instanceof GaugeWrapper &&
- tag.equals(((GaugeWrapper) metric).getTag())) {
- removed.incrementAndGet();
- return true;
- } else {
- return false;
+ if (metric instanceof GaugeWrapper) {
+ GaugeWrapper wrapper = (GaugeWrapper) metric;
+ boolean toRemove = tagSegment.equals(wrapper.getTag()) || wrapper.getTag().contains(tagSegment);
+ if (toRemove) removed.incrementAndGet();
+ return toRemove;
}
+ return false;
+
});
return removed.get();
}
@@ -752,10 +785,16 @@ public class SolrMetricManager {
* segments prepended to the name.
*/
public static String mkName(String name, String... path) {
+ return makeName(path == null || path.length == 0 ? Collections.emptyList() : Arrays.asList(path),
+ name);
+
+ }
+
+ public static String makeName(List<String> path, String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("name must not be empty");
}
- if (path == null || path.length == 0) {
+ if (path == null || path.size() == 0) {
return name;
} else {
StringBuilder sb = new StringBuilder();
@@ -774,6 +813,7 @@ public class SolrMetricManager {
sb.append(name);
return sb.toString();
}
+
}
/**
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 265d7e4..0069734 100644
--- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricProducer.java
@@ -19,17 +19,53 @@ package org.apache.solr.metrics;
/**
* Used by objects that expose metrics through {@link SolrMetricManager}.
*/
-public interface SolrMetricProducer {
+public interface SolrMetricProducer extends AutoCloseable {
+
+ /**
+ * Unique metric name is in the format of A.B.C
+ * A is the parent of B is the parent of C and so on.
+ * If object "B" is unregistered , C also must get unregistered.
+ * If object "A" is unregistered , B , C also must get unregistered.
+ */
+ default String getUniqueMetricTag(String parentName) {
+ String name = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
+ if (parentName != null && parentName.contains(name)) return parentName;
+ return parentName == null ?
+ name :
+ parentName + ":" + name;
+ }
+
/**
* Initializes metrics specific to this producer
- * @param manager an instance of {@link SolrMetricManager}
+ *
+ * @param manager an instance of {@link SolrMetricManager}
* @param registry registry name where metrics are registered
- * @param tag a symbolic tag that represents this instance of the producer,
- * or a group of related instances that have the same life-cycle. This tag is
- * used when managing life-cycle of some metrics and is set when
- * {@link #initializeMetrics(SolrMetricManager, String, String, String)} is called.
- * @param scope scope of the metrics (eg. handler name) to separate metrics of
+ * @param tag a symbolic tag that represents this instance of the producer,
+ * or a group of related instances that have the same life-cycle. This tag is
+ * used when managing life-cycle of some metrics and is set when
+ * {@link #initializeMetrics(SolrMetricManager, String, String, String)} is called.
+ * @param scope scope of the metrics (eg. handler name) to separate metrics of
*/
- void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope);
+ default void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
+ initializeMetrics(new SolrMetrics(manager, registry, tag, scope));
+
+ }
+
+ default void initializeMetrics(SolrMetrics info) {
+ throw new RuntimeException("This means , the class has not implemented both of these methods");
+
+ }
+
+ default SolrMetrics getMetrics() {
+ return null;
+ }
+
+ @Override
+ default void close() throws Exception {
+ SolrMetrics info = getMetrics();
+ if (info == null || info.tag.indexOf(':') == -1) return;//this will end up unregistering the root itself
+ info.unregister();
+ }
+
}
diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetrics.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetrics.java
new file mode 100644
index 0000000..28aea4e
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetrics.java
@@ -0,0 +1,94 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collections;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Timer;
+import org.apache.solr.core.SolrInfoBean;
+
+import static org.apache.solr.metrics.SolrMetricManager.makeName;
+
+public class SolrMetrics {
+ public final String registry;
+ public final SolrMetricManager metricManager;
+ public final String tag;
+ public final String scope;
+ private SolrMetrics parent;
+
+ public SolrMetrics(SolrMetricManager metricManager, String registry, String tag, String scope) {
+ this.registry = registry;
+ this.metricManager = metricManager;
+ this.tag = tag;
+ this.scope = scope;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public void unregister() {
+ metricManager.unregisterGauges(registry, tag);
+ }
+
+ public SolrMetrics getChildInfo(SolrMetricProducer producer) {
+ SolrMetrics metricsInfo = new SolrMetrics(metricManager, registry, producer.getUniqueMetricTag(tag), scope);
+ metricsInfo.parent = this;
+ return metricsInfo;
+ }
+
+ public Meter meter(SolrInfoBean info, String metricName, String... metricpath) {
+ return metricManager.meter(info, getRegistry(), createName(metricName, metricpath));
+ }
+
+ private String createName(String metricName, String... metricpath) {
+ ArrayList<String> l = new ArrayList<>();
+ if(metricpath != null ) {
+ Collections.addAll(l, metricpath);
+ }
+ l.add(scope);
+ return makeName(l, metricName);
+ }
+
+ public Counter counter(SolrInfoBean info, String metricName, String... metricpath) {
+ return metricManager.counter(info, getRegistry(), createName(metricName, metricpath));
+
+ }
+
+ public void gauge(SolrInfoBean info, Gauge<?> gauge, boolean force, String metricName, String... metricpath) {
+ metricManager.registerGauge(info, getRegistry(), new SolrMetricManager.GaugeWrapper<>(gauge, tag), force, createName(metricName, metricpath));
+ }
+
+ public Timer timer(SolrInfoBean info, String metricName, String... metricpath) {
+ return metricManager.timer(info, getRegistry(), createName(metricName, metricpath));
+
+ }
+
+ public SolrMetrics getParent() {
+ return parent;
+ }
+
+ public MetricRegistry getRegistry() {
+ return metricManager.registry(registry);
+ }
+}
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 2dc1c1e..af802e2 100644
--- a/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
@@ -16,24 +16,24 @@
*/
package org.apache.solr.search;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+
import com.codahale.metrics.MetricRegistry;
import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.RamUsageEstimator;
import org.apache.solr.common.SolrException;
import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetrics;
import org.apache.solr.util.ConcurrentLRUCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.invoke.MethodHandles;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.TimeUnit;
-
/**
* SolrCache based on ConcurrentLRUCache implementation.
* <p>
@@ -42,12 +42,11 @@ import java.util.concurrent.TimeUnit;
* <p>
* Also see <a href="http://wiki.apache.org/solr/SolrCaching">SolrCaching</a>
*
- *
* @see org.apache.solr.util.ConcurrentLRUCache
* @see org.apache.solr.search.SolrCache
* @since solr 1.4
*/
-public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>, Accountable {
+public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K, V>, Accountable {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(FastLRUCache.class);
@@ -61,7 +60,7 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
private long warmupTime = 0;
private String description = "Concurrent LRU Cache";
- private ConcurrentLRUCache<K,V> cache;
+ private ConcurrentLRUCache<K, V> cache;
private int showItems = 0;
private long maxRamBytes;
@@ -75,7 +74,6 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
private MetricsMap cacheMap;
private Set<String> metricNames = ConcurrentHashMap.newKeySet();
- private MetricRegistry registry;
@Override
public Object init(Map args, Object persistence, CacheRegenerator regenerator) {
@@ -117,7 +115,7 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
str = (String) args.get(MAX_RAM_MB_PARAM);
long maxRamMB = str == null ? -1 : (long) Double.parseDouble(str);
this.maxRamBytes = maxRamMB < 0 ? Long.MAX_VALUE : maxRamMB * 1024L * 1024L;
- if (maxRamBytes != Long.MAX_VALUE) {
+ if (maxRamBytes != Long.MAX_VALUE) {
ramLowerWatermark = Math.round(maxRamBytes * 0.8);
description = generateDescription(maxRamBytes, ramLowerWatermark, cleanupThread);
cache = new ConcurrentLRUCache<>(ramLowerWatermark, maxRamBytes, cleanupThread, null, maxIdleTimeSec);
@@ -213,7 +211,7 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
*/
protected String generateDescription(int limit, int initialSize, int minLimit, int acceptableLimit, boolean newThread) {
String description = "Concurrent LRU Cache(maxSize=" + limit + ", initialSize=" + initialSize +
- ", minSize="+minLimit + ", acceptableSize="+acceptableLimit+", cleanupThread="+newThread;
+ ", minSize=" + minLimit + ", acceptableSize=" + acceptableLimit + ", cleanupThread=" + newThread;
if (isAutowarmingOn()) {
description += ", " + getAutowarmDescription();
}
@@ -274,10 +272,9 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
for (int i = itemsArr.length - 1; i >= 0; i--) {
try {
boolean continueRegen = regenerator.regenerateItem(searcher,
- this, old, itemsArr[i].getKey(), itemsArr[i].getValue());
+ this, old, itemsArr[i].getKey(), itemsArr[i].getValue());
if (!continueRegen) break;
- }
- catch (Exception e) {
+ } catch (Exception e) {
SolrException.log(log, "Error during auto-warming of key:" + itemsArr[i].getKey(), e);
}
}
@@ -288,6 +285,7 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
@Override
public void close() {
+ if (metricsInfo != null) metricsInfo.unregister();
// add the stats to the cumulative stats object (the first in the statsList)
statsList.get(0).add(cache.getStats());
statsList.remove(cache.getStats());
@@ -310,10 +308,18 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
return metricNames;
}
+
+ SolrMetrics metricsInfo;
+
+ @Override
+ public SolrMetrics getMetrics() {
+ return metricsInfo;
+ }
+
@Override
- public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
- registry = manager.registry(registryName);
- manager.registerGauge(this, registryName, cacheMap, tag, true, scope, getCategory().toString());
+ public void initializeMetrics(SolrMetrics metricsInfo) {
+ this.metricsInfo = metricsInfo;
+ metricsInfo.metricManager.registerGauge(this, metricsInfo.registry, cacheMap, metricsInfo.tag, true, metricsInfo.scope, getCategory().toString());
}
// for unit tests only
@@ -323,7 +329,7 @@ public class FastLRUCache<K, V> extends SolrCacheBase implements SolrCache<K,V>,
@Override
public MetricRegistry getMetricRegistry() {
- return registry;
+ return metricsInfo == null ? null : metricsInfo.getRegistry();
}
@Override
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 20cf664..a309d73 100644
--- a/solr/core/src/java/org/apache/solr/search/LFUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/LFUCache.java
@@ -17,10 +17,10 @@
package org.apache.solr.search;
import java.lang.invoke.MethodHandles;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
@@ -29,7 +29,7 @@ import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.RamUsageEstimator;
import org.apache.solr.common.SolrException;
import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetrics;
import org.apache.solr.util.ConcurrentLFUCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -79,7 +79,6 @@ public class LFUCache<K, V> implements SolrCache<K, V>, Accountable {
private int maxIdleTimeSec;
private MetricsMap cacheMap;
private Set<String> metricNames = ConcurrentHashMap.newKeySet();
- private MetricRegistry registry;
private int maxSize;
private int minSizeLimit;
@@ -235,6 +234,7 @@ public class LFUCache<K, V> implements SolrCache<K, V>, Accountable {
statsList.get(0).add(cache.getStats());
statsList.remove(cache.getStats());
cache.destroy();
+ if (solrMetrics != null) solrMetrics.unregister();
}
//////////////////////// SolrInfoMBeans methods //////////////////////
@@ -262,9 +262,17 @@ public class LFUCache<K, V> implements SolrCache<K, V>, Accountable {
return "0." + hundredths;
}
+
+ private SolrMetrics solrMetrics;
+
+ @Override
+ public SolrMetrics getMetrics() {
+ return solrMetrics;
+ }
+
@Override
- public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
- registry = manager.registry(registryName);
+ public void initializeMetrics(SolrMetrics info) {
+ solrMetrics = info.getChildInfo(this);
cacheMap = new MetricsMap((detailed, map) -> {
if (cache != null) {
ConcurrentLFUCache.Stats stats = cache.getStats();
@@ -330,7 +338,7 @@ public class LFUCache<K, V> implements SolrCache<K, V>, Accountable {
}
});
- manager.registerGauge(this, registryName, cacheMap, tag, true, scope, getCategory().toString());
+ solrMetrics.metricManager.registerGauge(this, solrMetrics.registry, cacheMap, solrMetrics.getTag(), true, solrMetrics.scope, getCategory().toString());
}
// for unit tests only
@@ -345,7 +353,8 @@ public class LFUCache<K, V> implements SolrCache<K, V>, Accountable {
@Override
public MetricRegistry getMetricRegistry() {
- return registry;
+ return solrMetrics == null ? null : solrMetrics.getRegistry();
+
}
@Override
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 c733c07..ae3e81c 100644
--- a/solr/core/src/java/org/apache/solr/search/LRUCache.java
+++ b/solr/core/src/java/org/apache/solr/search/LRUCache.java
@@ -18,11 +18,11 @@ package org.apache.solr.search;
import java.lang.invoke.MethodHandles;
import java.util.Collection;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
@@ -33,7 +33,7 @@ import org.apache.lucene.util.RamUsageEstimator;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.TimeSource;
import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -77,7 +77,6 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
private String description="LRU Cache";
private MetricsMap cacheMap;
private Set<String> metricNames = ConcurrentHashMap.newKeySet();
- private MetricRegistry registry;
private int maxSize;
private int initialSize;
@@ -234,8 +233,8 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
}
/**
- *
- * @return Returns the description of this cache.
+ *
+ * @return Returns the description of this cache.
*/
private String generateDescription() {
String description = "LRU Cache(maxSize=" + getMaxSize() + ", initialSize=" + initialSize;
@@ -341,9 +340,9 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
// Don't do the autowarming in the synchronized block, just pull out the keys and values.
synchronized (other.map) {
-
+
int sz = autowarm.getWarmCount(other.map.size());
-
+
keys = new Object[sz];
vals = new Object[sz];
@@ -380,10 +379,9 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
@Override
public void close() {
-
+ if(solrMetrics != null) solrMetrics.unregister();
}
-
//////////////////////// SolrInfoMBeans methods //////////////////////
@@ -402,9 +400,16 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
return metricNames;
}
+ SolrMetrics solrMetrics;
+
+ @Override
+ public SolrMetrics getMetrics() {
+ return solrMetrics;
+ }
+
@Override
- public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, String scope) {
- registry = manager.registry(registryName);
+ public void initializeMetrics(SolrMetrics m) {
+ solrMetrics = m.getChildInfo(this);
cacheMap = new MetricsMap((detailed, res) -> {
synchronized (map) {
res.put(LOOKUPS_PARAM, lookups);
@@ -433,7 +438,7 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
res.put("cumulative_evictionsRamUsage", stats.evictionsRamUsage.longValue());
res.put("cumulative_evictionsIdleTime", stats.evictionsIdleTime.longValue());
});
- manager.registerGauge(this, registryName, cacheMap, tag, true, scope, getCategory().toString());
+ solrMetrics.metricManager.registerGauge(this, solrMetrics.registry, cacheMap, solrMetrics.tag, true, solrMetrics.scope, getCategory().toString());
}
// for unit tests only
@@ -443,7 +448,7 @@ public class LRUCache<K,V> extends SolrCacheBase implements SolrCache<K,V>, Acco
@Override
public MetricRegistry getMetricRegistry() {
- return registry;
+ return solrMetrics ==null ?null: solrMetrics.getRegistry();
}
@Override
diff --git a/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java b/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java
index 66b8ab1..58a43eb 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java
@@ -24,6 +24,7 @@ import java.util.Set;
import com.codahale.metrics.MetricRegistry;
import org.apache.solr.common.util.Utils;
import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -142,11 +143,8 @@ public class SolrCacheHolder<K, V> implements SolrCache<K,V> {
}
@Override
- public void initializeMetrics(SolrMetricManager manager, String registry, String tag, String scope) {
- log.debug("Going to register cachemetrics " + Utils.toJSONString(factory));
-
- delegate.initializeMetrics(manager, registry, tag,scope);
-
+ public void initializeMetrics(SolrMetrics info) {
+ delegate.initializeMetrics(info);
}
}
diff --git a/solr/core/src/java/org/apache/solr/security/AuthenticationPlugin.java b/solr/core/src/java/org/apache/solr/security/AuthenticationPlugin.java
index 5fd18a1..8044af9 100644
--- a/solr/core/src/java/org/apache/solr/security/AuthenticationPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/AuthenticationPlugin.java
@@ -19,7 +19,6 @@ package org.apache.solr.security;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
-import java.io.Closeable;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
@@ -29,29 +28,25 @@ import com.codahale.metrics.Counter;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
-import org.apache.solr.core.SolrInfoBean;
-import org.apache.solr.metrics.SolrMetricManager;
-import org.apache.solr.metrics.SolrMetricProducer;
-
import org.apache.http.HttpRequest;
import org.apache.http.protocol.HttpContext;
+import org.apache.solr.core.SolrInfoBean;
+import org.apache.solr.metrics.SolrMetricProducer;
+import org.apache.solr.metrics.SolrMetrics;
import org.eclipse.jetty.client.api.Request;
/**
*
* @lucene.experimental
*/
-public abstract class AuthenticationPlugin implements Closeable, SolrInfoBean, SolrMetricProducer {
+public abstract class AuthenticationPlugin implements SolrInfoBean, SolrMetricProducer {
final public static String AUTHENTICATION_PLUGIN_PROP = "authenticationPlugin";
final public static String HTTP_HEADER_X_SOLR_AUTHDATA = "X-Solr-AuthData";
// Metrics
private Set<String> metricNames = ConcurrentHashMap.newKeySet();
- private MetricRegistry registry;
- protected String registryName;
- protected SolrMetricManager metricManager;
protected Meter numErrors = new Meter();
protected Counter requests = new Counter();
protected Timer requestTimes = new Timer();
@@ -66,7 +61,7 @@ public abstract class AuthenticationPlugin implements Closeable, SolrInfoBean, S
* @param pluginConfig Config parameters, possibly from a ZK source
*/
public abstract void init(Map<String, Object> pluginConfig);
-
+
/**
* This method attempts to authenticate the request. Upon a successful authentication, this
* must call the next filter in the filter chain and set the user principal of the request,
@@ -107,10 +102,10 @@ public abstract class AuthenticationPlugin implements Closeable, SolrInfoBean, S
* delegate to {@link PKIAuthenticationPlugin}. Return true to indicate that your plugin
* did handle the request, or false to signal that PKI plugin should handle it. This method
* will be called by {@link PKIAuthenticationPlugin}'s interceptor.
- *
+ *
* <p>
* If not overridden, this method will return true for plugins implementing {@link HttpClientBuilderPlugin}.
- * This method can be overridden by subclasses e.g. to set HTTP headers, even if you don't use a clientBuilder.
+ * This method can be overridden by subclasses e.g. to set HTTP headers, even if you don't use a clientBuilder.
* </p>
* @param httpRequest the httpRequest that is about to be sent to another internal Solr node
* @param httpContext the context of that request.
@@ -137,31 +132,35 @@ public abstract class AuthenticationPlugin implements Closeable, SolrInfoBean, S
protected boolean interceptInternodeRequest(Request request) {
return this instanceof HttpClientBuilderPlugin;
}
-
+
/**
* Cleanup any per request data
*/
public void closeRequest() {
}
+ protected SolrMetrics metrics;
+
+ @Override
+ public SolrMetrics getMetrics() {
+ return metrics;
+ }
@Override
- public void initializeMetrics(SolrMetricManager manager, String registryName, String tag, final String scope) {
- this.metricManager = manager;
- this.registryName = registryName;
+ public void initializeMetrics(SolrMetrics metrics) {
+ this.metrics = metrics.getChildInfo(this);
// Metrics
- registry = manager.registry(registryName);
- numErrors = manager.meter(this, registryName, "errors", getCategory().toString(), scope);
- requests = manager.counter(this, registryName, "requests", getCategory().toString(), scope);
- numAuthenticated = manager.counter(this, registryName, "authenticated", getCategory().toString(), scope);
- numPassThrough = manager.counter(this, registryName, "passThrough", getCategory().toString(), scope);
- numWrongCredentials = manager.counter(this, registryName, "failWrongCredentials", getCategory().toString(), scope);
- numMissingCredentials = manager.counter(this, registryName, "failMissingCredentials", getCategory().toString(), scope);
- requestTimes = manager.timer(this, registryName, "requestTimes", getCategory().toString(), scope);
- totalTime = manager.counter(this, registryName, "totalTime", getCategory().toString(), scope);
+ numErrors = this.metrics.meter(this, "errors", getCategory().toString());
+ requests = this.metrics.counter(this, "requests", getCategory().toString());
+ numAuthenticated = this.metrics.counter(this, "authenticated",getCategory().toString());
+ numPassThrough = this.metrics.counter(this, "passThrough", getCategory().toString());
+ numWrongCredentials = this.metrics.counter(this, "failWrongCredentials",getCategory().toString());
+ numMissingCredentials = this.metrics.counter(this, "failMissingCredentials",getCategory().toString());
+ requestTimes = this.metrics.timer(this,"requestTimes", getCategory().toString());
+ totalTime = this.metrics.counter(this,"totalTime", getCategory().toString());
metricNames.addAll(Arrays.asList("errors", "requests", "authenticated", "passThrough",
"failWrongCredentials", "failMissingCredentials", "requestTimes", "totalTime"));
}
-
+
@Override
public String getName() {
return this.getClass().getName();
@@ -184,7 +183,7 @@ public abstract class AuthenticationPlugin implements Closeable, SolrInfoBean, S
@Override
public MetricRegistry getMetricRegistry() {
- return registry;
+ return metrics == null ? null : metrics.getRegistry();
}
-
+
}
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 a6dbd9e..3c16ce6 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
@@ -17,6 +17,7 @@
package org.apache.solr.handler.admin;
+import java.util.Arrays;
import java.util.Map;
import com.codahale.metrics.Counter;
@@ -24,6 +25,15 @@ import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.common.util.Utils;
+import org.apache.solr.core.PluginBag;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.metrics.MetricsMap;
+import org.apache.solr.metrics.SolrMetrics;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -53,12 +63,12 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
@AfterClass
public static void cleanupMetrics() throws Exception {
if (null != h) {
- h.getCoreContainer().getMetricManager().registry("solr.jvm" ).remove("solrtest_foo");
+ h.getCoreContainer().getMetricManager().registry("solr.jvm").remove("solrtest_foo");
h.getCoreContainer().getMetricManager().registry("solr.jetty").remove("solrtest_foo");
h.getCoreContainer().getMetricManager().registry("solr.jetty").remove("solrtest_foo:bar");
}
}
-
+
@Test
public void test() throws Exception {
MetricsHandler handler = new MetricsHandler(h.getCoreContainer());
@@ -145,7 +155,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
assertNotNull(values.get("metrics"));
values = (NamedList) values.get("metrics");
assertEquals(1, values.size());
- assertEquals(13, ((NamedList)values.get("solr.node")).size());
+ assertEquals(13, ((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
@@ -171,7 +181,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
assertNotNull(values.get("solr.core.collection1"));
values = (NamedList) values.get("solr.core.collection1");
assertEquals(1, values.size());
- Map m = (Map)values.get("CACHE.core.fieldCache");
+ Map m = (Map) values.get("CACHE.core.fieldCache");
assertNotNull(m);
assertNotNull(m.get("entries_count"));
@@ -223,7 +233,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
assertTrue(nl.size() > 0);
nl.forEach((k, v) -> {
assertTrue(v instanceof Map);
- Map map = (Map)v;
+ Map map = (Map) v;
assertTrue(map.size() > 2);
});
@@ -238,7 +248,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
assertTrue(nl.size() > 0);
nl.forEach((k, v) -> {
assertTrue(v instanceof Map);
- Map map = (Map)v;
+ Map map = (Map) v;
assertEquals(2, map.size());
assertNotNull(map.get("inserts"));
assertNotNull(map.get("size"));
@@ -257,7 +267,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
Object val = values.findRecursive("metrics", key1);
assertNotNull(val);
assertTrue(val instanceof Map);
- assertTrue(((Map)val).size() >= 2);
+ assertTrue(((Map) val).size() >= 2);
String key2 = "solr.core.collection1:CACHE.core.fieldCache:entries_count";
resp = new SolrQueryResponse();
@@ -276,7 +286,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
val = values.findRecursive("metrics", key3);
assertNotNull(val);
assertTrue(val instanceof Number);
- assertEquals(3, ((Number)val).intValue());
+ assertEquals(3, ((Number) val).intValue());
// test multiple keys
resp = new SolrQueryResponse();
@@ -306,7 +316,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json",
MetricsHandler.KEY_PARAM, "foo", MetricsHandler.KEY_PARAM, "foo:bar:baz:xyz"), resp);
values = resp.getValues();
- NamedList metrics = (NamedList)values.get("metrics");
+ NamedList metrics = (NamedList) values.get("metrics");
assertEquals(0, metrics.size());
assertNotNull(values.findRecursive("errors", "foo"));
assertNotNull(values.findRecursive("errors", "foo:bar:baz:xyz"));
@@ -316,7 +326,7 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json",
MetricsHandler.KEY_PARAM, "foo:bar:baz"), resp);
values = resp.getValues();
- metrics = (NamedList)values.get("metrics");
+ metrics = (NamedList) values.get("metrics");
assertEquals(0, metrics.size());
assertNotNull(values.findRecursive("errors", "foo:bar:baz"));
@@ -325,8 +335,122 @@ public class MetricsHandlerTest extends SolrTestCaseJ4 {
handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json",
MetricsHandler.KEY_PARAM, "solr.jetty:unknown:baz"), resp);
values = resp.getValues();
- metrics = (NamedList)values.get("metrics");
+ metrics = (NamedList) values.get("metrics");
assertEquals(0, metrics.size());
assertNotNull(values.findRecursive("errors", "solr.jetty:unknown:baz"));
}
+
+ @Test
+ public void testMetricsUnload() throws Exception {
+
+ SolrCore core = h.getCoreContainer().getCore("collection1");//;.getRequestHandlers().put("/dumphandler", new DumpRequestHandler());
+ RefreshablePluginHolder pluginHolder =null;
+ try {
+ PluginInfo info = new PluginInfo(SolrRequestHandler.TYPE, Utils.makeMap("name", "/dumphandler", "class", DumpRequestHandler.class.getName()));
+ DumpRequestHandler requestHandler = new DumpRequestHandler();
+ requestHandler.gaugevals = Utils.makeMap("d_k1","v1", "d_k2","v2");
+ pluginHolder = new RefreshablePluginHolder(info, requestHandler);
+ core.getRequestHandlers().put("/dumphandler",
+
+ pluginHolder);
+ } finally {
+ core.close();
+ }
+
+
+
+ MetricsHandler handler = new MetricsHandler(h.getCoreContainer());
+
+ SolrQueryResponse resp = new SolrQueryResponse();
+ handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", MetricsHandler.COMPACT_PARAM, "true", "key", "solr.core.collection1:QUERY./dumphandler.dumphandlergauge"),
+ resp);
+
+ assertEquals("v1", resp.getValues()._getStr(Arrays.asList("metrics", "solr.core.collection1:QUERY./dumphandler.dumphandlergauge","d_k1"), null));
+ assertEquals("v2", resp.getValues()._getStr(Arrays.asList("metrics","solr.core.collection1:QUERY./dumphandler.dumphandlergauge","d_k2"), null));
+ pluginHolder.closeHandler();
+ resp = new SolrQueryResponse();
+ handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", MetricsHandler.COMPACT_PARAM, "true", "key", "solr.core.collection1:QUERY./dumphandler.dumphandlergauge"),
+ resp);
+
+ assertEquals(null, resp.getValues()._getStr(Arrays.asList("metrics", "solr.core.collection1:QUERY./dumphandler.dumphandlergauge","d_k1"), null));
+ assertEquals(null, resp.getValues()._getStr(Arrays.asList("metrics","solr.core.collection1:QUERY./dumphandler.dumphandlergauge","d_k2"), null));
+
+ DumpRequestHandler requestHandler = new DumpRequestHandler();
+ requestHandler.gaugevals = Utils.makeMap("d_k1","v1.1", "d_k2","v2.1");
+ pluginHolder.reset(requestHandler);
+ resp = new SolrQueryResponse();
+ handler.handleRequestBody(req(CommonParams.QT, "/admin/metrics", CommonParams.WT, "json", MetricsHandler.COMPACT_PARAM, "true", "key", "solr.core.collection1:QUERY./dumphandler.dumphandlergauge"),
+ resp);
+
+ assertEquals("v1.1", resp.getValues()._getStr(Arrays.asList("metrics", "solr.core.collection1:QUERY./dumphandler.dumphandlergauge","d_k1"), null));
+ assertEquals("v2.1", resp.getValues()._getStr(Arrays.asList("metrics","solr.core.collection1:QUERY./dumphandler.dumphandlergauge","d_k2"), null));
+
+
+ }
+
+ static class RefreshablePluginHolder extends PluginBag.PluginHolder<SolrRequestHandler> {
+
+ private DumpRequestHandler rh;
+ private SolrMetrics metricsInfo;
+
+ public RefreshablePluginHolder(PluginInfo info, DumpRequestHandler rh) {
+ super(info);
+ this.rh = rh;
+ }
+
+ @Override
+ public boolean isLoaded() {
+ return true;
+ }
+
+ void closeHandler() throws Exception {
+ this.metricsInfo = rh.getMetrics();
+ if(metricsInfo.tag.contains(String.valueOf(rh.hashCode()))){
+ //this created a new child metrics
+ metricsInfo = metricsInfo.getParent();
+ }
+ this.rh.close();
+ }
+
+ void reset(DumpRequestHandler rh) throws Exception {
+ this.rh = rh;
+ if(metricsInfo != null)
+ this.rh.initializeMetrics(metricsInfo);
+ }
+
+
+ @Override
+ public SolrRequestHandler get() {
+ return rh;
+ }
+ }
+
+ public static class DumpRequestHandler extends RequestHandlerBase {
+
+ static String key = DumpRequestHandler.class.getName();
+ Map<String, Object> gaugevals ;
+ @Override
+ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
+ rsp.add("key", key);
+ }
+
+ @Override
+ public String getDescription() {
+ return "DO nothing";
+ }
+
+ @Override
+ public void initializeMetrics(SolrMetrics m) {
+ super.initializeMetrics(m);
+ MetricsMap metrics = new MetricsMap((detailed, map) -> map.putAll(gaugevals));
+ solrMetrics.gauge(this,
+ metrics, true, "dumphandlergauge", getCategory().toString());
+
+ }
+
+ @Override
+ public Boolean registerV2() {
+ return Boolean.FALSE;
+ }
+ }
}
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java b/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java
index a053a18..e5bad27 100644
--- a/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java
+++ b/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java
@@ -72,6 +72,7 @@ public class ExecutorUtil {
}
public static void shutdownAndAwaitTermination(ExecutorService pool) {
+ if(pool == null) return;
pool.shutdown(); // Disable new tasks from being submitted
awaitTermination(pool);
}