You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2017/01/04 05:48:42 UTC
[1/2] lucene-solr:branch_6x: SOLR-9877: Use instrumented http client
and connection pool
Repository: lucene-solr
Updated Branches:
refs/heads/branch_6x 93d1bba8f -> f65dc0618
SOLR-9877: Use instrumented http client and connection pool
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/a50ebcb4
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/a50ebcb4
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/a50ebcb4
Branch: refs/heads/branch_6x
Commit: a50ebcb412b1a884b826b62418e9f5d8b3c1f40c
Parents: 93d1bba
Author: Shalin Shekhar Mangar <sh...@apache.org>
Authored: Wed Jan 4 11:05:40 2017 +0530
Committer: Shalin Shekhar Mangar <sh...@apache.org>
Committed: Wed Jan 4 11:05:40 2017 +0530
----------------------------------------------------------------------
solr/CHANGES.txt | 4 +-
.../org/apache/solr/core/CoreContainer.java | 8 +-
.../component/HttpShardHandlerFactory.java | 68 ++++++++--
.../apache/solr/update/UpdateShardHandler.java | 70 +++++++++--
.../solr/util/stats/InstrumentedHttpClient.java | 83 +++++++++++++
.../stats/InstrumentedHttpRequestExecutor.java | 124 +++++++++++++++++++
...trumentedPoolingClientConnectionManager.java | 111 +++++++++++++++++
7 files changed, 450 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a50ebcb4/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 283e47b..df4b911 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -152,6 +152,8 @@ New Features
* SOLR-8530: Add HavingStream to Streaming API and StreamingExpressions (Joel Bernstein)
+* SOLR-9877: Use instrumented http client and connection pool. (shalin)
+
Optimizations
----------------------
* SOLR-9704: Facet Module / JSON Facet API: Optimize blockChildren facets that have
@@ -249,7 +251,7 @@ Bug Fixes
* SOLR-9154: Fix DirectSolrSpellChecker to work when added through the Config API. (Anshum Gupta)
-* SOLR-9859: replication.properties cannot be updated after being written and neither replication.properties or
+* SOLR-9859: replication.properties cannot be updated after being written and neither replication.properties or
index.properties are durable in the face of a crash. (Pushkar Raste, Chris de Kok, Cao Manh Dat, Mark Miller)
* SOLR-9901: Implement move in HdfsDirectoryFactory. (Mark Miller)
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a50ebcb4/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 2727a5a..7294679 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -438,10 +438,16 @@ public class CoreContainer {
}
}
+ metricManager = new SolrMetricManager();
shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
+ if (shardHandlerFactory instanceof SolrMetricProducer) {
+ SolrMetricProducer metricProducer = (SolrMetricProducer) shardHandlerFactory;
+ metricProducer.initializeMetrics(metricManager, SolrInfoMBean.Group.http.toString(), "httpShardHandler");
+ }
updateShardHandler = new UpdateShardHandler(cfg.getUpdateShardHandlerConfig());
+ updateShardHandler.initializeMetrics(metricManager, SolrInfoMBean.Group.http.toString(), "updateShardHandler");
solrCores.allocateLazyCores(cfg.getTransientCacheSize(), loader);
@@ -454,8 +460,6 @@ public class CoreContainer {
MDCLoggingContext.setNode(this);
- metricManager = new SolrMetricManager();
-
ZkStateReader.ConfigData securityConfig = isZooKeeperAware() ? getZkController().getZkStateReader().getSecurityProps(false) : new ZkStateReader.ConfigData(EMPTY_MAP, -1);
initializeAuthorizationPlugin((Map<String, Object>) securityConfig.data.get("authorization"));
initializeAuthenticationPlugin((Map<String, Object>) securityConfig.data.get("authentication"));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a50ebcb4/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
index 71e9fe3..ff50cbc 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
@@ -20,7 +20,6 @@ import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
-import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.impl.conn.SchemeRegistryFactory;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
@@ -40,15 +39,22 @@ import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.URLUtil;
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.core.PluginInfo;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.update.UpdateShardHandler;
import org.apache.solr.update.UpdateShardHandlerConfig;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.util.DefaultSolrThreadFactory;
+import org.apache.solr.util.stats.InstrumentedHttpClient;
+import org.apache.solr.util.stats.InstrumentedPoolingClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@@ -62,7 +68,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.apache.solr.util.plugin.PluginInfoInitialized {
+public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.apache.solr.util.plugin.PluginInfoInitialized, SolrMetricProducer {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String DEFAULT_SCHEME = "http";
@@ -80,7 +86,7 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.
new DefaultSolrThreadFactory("httpShardExecutor")
);
- protected PoolingClientConnectionManager clientConnectionManager;
+ protected InstrumentedPoolingClientConnectionManager clientConnectionManager;
protected CloseableHttpClient defaultClient;
private LBHttpSolrClient loadbalancer;
//default values:
@@ -189,11 +195,12 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.
);
ModifiableSolrParams clientParams = getClientParams();
-
- this.clientConnectionManager = new PoolingClientConnectionManager(SchemeRegistryFactory.createSystemDefault());
+ clientConnectionManager = new InstrumentedPoolingClientConnectionManager(SchemeRegistryFactory.createSystemDefault());
clientConnectionManager.setDefaultMaxPerRoute(maxConnectionsPerHost);
clientConnectionManager.setMaxTotal(maxConnections);
- this.defaultClient = HttpClientUtil.createClient(clientParams, clientConnectionManager);
+ InstrumentedHttpClient httpClient = new InstrumentedHttpClient(clientConnectionManager);
+ HttpClientUtil.configureClient(httpClient, clientParams);
+ this.defaultClient = httpClient;
this.idleConnectionsEvictor = new UpdateShardHandler.IdleConnectionsEvictor(clientConnectionManager,
connectionsEvictorSleepDelay, TimeUnit.MILLISECONDS, maxConnectionIdleTime, TimeUnit.MILLISECONDS);
idleConnectionsEvictor.start();
@@ -204,10 +211,9 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.
// but for these read only requests we can use the standard DefaultHttpRequestRetryHandler rules
((DefaultHttpClient) this.defaultClient).setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler());
}
-
this.loadbalancer = createLoadbalancer(defaultClient);
}
-
+
protected ModifiableSolrParams getClientParams() {
ModifiableSolrParams clientParams = new ModifiableSolrParams();
clientParams.set(HttpClientUtil.PROP_SO_TIMEOUT, soTimeout);
@@ -399,4 +405,50 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.
return url;
}
+
+ @Override
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ @Override
+ public String getVersion() {
+ return getClass().getPackage().getSpecificationVersion();
+ }
+
+ @Override
+ public Collection<String> initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+ List<String> metricNames = new ArrayList<>(4);
+ metricNames.addAll(clientConnectionManager.initializeMetrics(manager, registry, scope));
+ if (defaultClient instanceof SolrMetricProducer) {
+ SolrMetricProducer solrMetricProducer = (SolrMetricProducer) defaultClient;
+ metricNames.addAll(solrMetricProducer.initializeMetrics(manager, registry, scope));
+ }
+ return metricNames;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Metrics tracked by HttpShardHandlerFactory for distributed query requests";
+ }
+
+ @Override
+ public Category getCategory() {
+ return Category.OTHER;
+ }
+
+ @Override
+ public String getSource() {
+ return null;
+ }
+
+ @Override
+ public URL[] getDocs() {
+ return new URL[0];
+ }
+
+ @Override
+ public NamedList getStatistics() {
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a50ebcb4/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
index 3ed31dc..a1725b3 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java
@@ -17,6 +17,10 @@
package org.apache.solr.update;
import java.lang.invoke.MethodHandles;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@@ -25,7 +29,6 @@ import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.impl.conn.SchemeRegistryFactory;
import org.apache.http.util.Args;
import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
@@ -35,11 +38,16 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.IOUtils;
+import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SolrjNamedThreadFactory;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
+import org.apache.solr.util.stats.InstrumentedHttpClient;
+import org.apache.solr.util.stats.InstrumentedPoolingClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class UpdateShardHandler {
+public class UpdateShardHandler implements SolrMetricProducer {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -56,17 +64,17 @@ public class UpdateShardHandler {
private ExecutorService recoveryExecutor = ExecutorUtil.newMDCAwareCachedThreadPool(
new SolrjNamedThreadFactory("recoveryExecutor"));
- private PoolingClientConnectionManager clientConnectionManager;
-
private final CloseableHttpClient client;
+ private final InstrumentedPoolingClientConnectionManager clientConnectionManager;
+
private final UpdateShardHandlerConfig cfg;
private IdleConnectionsEvictor idleConnectionsEvictor;
public UpdateShardHandler(UpdateShardHandlerConfig cfg) {
this.cfg = cfg;
- clientConnectionManager = new PoolingClientConnectionManager(SchemeRegistryFactory.createSystemDefault());
+ clientConnectionManager = new InstrumentedPoolingClientConnectionManager(SchemeRegistryFactory.createSystemDefault());
if (cfg != null ) {
clientConnectionManager.setMaxTotal(cfg.getMaxUpdateConnections());
clientConnectionManager.setDefaultMaxPerRoute(cfg.getMaxUpdateConnectionsPerHost());
@@ -74,8 +82,9 @@ public class UpdateShardHandler {
ModifiableSolrParams clientParams = getClientParams();
log.info("Creating UpdateShardHandler HTTP client with params: {}", clientParams);
- client = HttpClientUtil.createClient(clientParams, clientConnectionManager);
-
+ InstrumentedHttpClient httpClient = new InstrumentedHttpClient(clientConnectionManager);
+ HttpClientUtil.configureClient(httpClient, clientParams);
+ client = httpClient;
if (cfg != null) {
idleConnectionsEvictor = new IdleConnectionsEvictor(clientConnectionManager,
cfg.getUpdateConnectionsEvictorSleepDelay(), TimeUnit.MILLISECONDS,
@@ -101,6 +110,53 @@ public class UpdateShardHandler {
}
+
+ @Override
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ @Override
+ public String getVersion() {
+ return getClass().getPackage().getSpecificationVersion();
+ }
+
+ @Override
+ public Collection<String> initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+ List<String> metricNames = new ArrayList<>(4);
+ metricNames.addAll(clientConnectionManager.initializeMetrics(manager, registry, scope));
+ if (client instanceof SolrMetricProducer) {
+ SolrMetricProducer solrMetricProducer = (SolrMetricProducer) client;
+ metricNames.addAll(solrMetricProducer.initializeMetrics(manager, registry, scope));
+ }
+ return metricNames;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Metrics tracked by UpdateShardHandler for distributed updates and recovery";
+ }
+
+ @Override
+ public Category getCategory() {
+ return null;
+ }
+
+ @Override
+ public String getSource() {
+ return null;
+ }
+
+ @Override
+ public URL[] getDocs() {
+ return new URL[0];
+ }
+
+ @Override
+ public NamedList getStatistics() {
+ return null;
+ }
+
public HttpClient getHttpClient() {
return client;
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a50ebcb4/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpClient.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpClient.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpClient.java
new file mode 100644
index 0000000..35c58aa
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpClient.java
@@ -0,0 +1,83 @@
+/*
+ * 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.util.stats;
+
+import java.net.URL;
+import java.util.Collection;
+
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.protocol.HttpRequestExecutor;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
+
+public class InstrumentedHttpClient extends DefaultHttpClient implements SolrMetricProducer {
+
+ protected final InstrumentedHttpRequestExecutor requestExecutor;
+
+ public InstrumentedHttpClient(ClientConnectionManager conman) {
+ super(conman);
+ this.requestExecutor = new InstrumentedHttpRequestExecutor();
+ }
+
+ @Override
+ protected HttpRequestExecutor createRequestExecutor() {
+ return requestExecutor;
+ }
+
+ @Override
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ @Override
+ public String getVersion() {
+ return getClass().getPackage().getSpecificationVersion();
+ }
+
+ @Override
+ public Collection<String> initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+ return requestExecutor.initializeMetrics(manager, registry, scope);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Metrics tracked by http client";
+ }
+
+ @Override
+ public Category getCategory() {
+ return Category.OTHER;
+ }
+
+ @Override
+ public String getSource() {
+ return null;
+ }
+
+ @Override
+ public URL[] getDocs() {
+ return new URL[0];
+ }
+
+ @Override
+ public NamedList getStatistics() {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a50ebcb4/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
new file mode 100644
index 0000000..ad76d73
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
@@ -0,0 +1,124 @@
+/*
+ * 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.util.stats;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Locale;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Timer;
+import org.apache.http.HttpClientConnection;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.RequestLine;
+import org.apache.http.client.methods.HttpRequestWrapper;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestExecutor;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
+
+/**
+ * Sub-class of HttpRequestExecutor which tracks metrics interesting to solr
+ * Inspired and partially copied from dropwizard httpclient library
+ */
+public class InstrumentedHttpRequestExecutor extends HttpRequestExecutor implements SolrMetricProducer {
+ protected MetricRegistry metricsRegistry;
+ protected String scope;
+
+ private static String methodNameString(HttpRequest request) {
+ return request.getRequestLine().getMethod().toLowerCase(Locale.ROOT) + "-requests";
+ }
+
+ @Override
+ public HttpResponse execute(HttpRequest request, HttpClientConnection conn, HttpContext context) throws IOException, HttpException {
+ final Timer.Context timerContext = timer(request).time();
+ try {
+ return super.execute(request, conn, context);
+ } finally {
+ timerContext.stop();
+ }
+ }
+
+ private Timer timer(HttpRequest request) {
+ return metricsRegistry.timer(getNameFor(request));
+ }
+
+ @Override
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ @Override
+ public String getVersion() {
+ return getClass().getPackage().getSpecificationVersion();
+ }
+
+ @Override
+ public Collection<String> initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+ this.metricsRegistry = manager.registry(registry);
+ this.scope = scope;
+ return Collections.emptyList(); // we do not know the names of the metrics yet
+ }
+
+ @Override
+ public String getDescription() {
+ return null;
+ }
+
+ @Override
+ public Category getCategory() {
+ return Category.OTHER;
+ }
+
+ @Override
+ public String getSource() {
+ return null;
+ }
+
+ @Override
+ public URL[] getDocs() {
+ return null;
+ }
+
+ @Override
+ public NamedList getStatistics() {
+ return null;
+ }
+
+ private String getNameFor(HttpRequest request) {
+ try {
+ final RequestLine requestLine = request.getRequestLine();
+ String schemeHostPort = null;
+ if (request instanceof HttpRequestWrapper) {
+ HttpRequestWrapper wrapper = (HttpRequestWrapper) request;
+ schemeHostPort = wrapper.getTarget().getSchemeName() + "://" + wrapper.getTarget().getHostName() + ":" + wrapper.getTarget().getPort();
+ }
+ final URIBuilder url = new URIBuilder(requestLine.getUri());
+ return SolrMetricManager.mkName((schemeHostPort != null ? schemeHostPort : "") + url.removeQuery().build().toString() + "." + methodNameString(request), scope);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a50ebcb4/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingClientConnectionManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingClientConnectionManager.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingClientConnectionManager.java
new file mode 100644
index 0000000..2f51c46
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedPoolingClientConnectionManager.java
@@ -0,0 +1,111 @@
+/*
+ * 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.util.stats;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.impl.conn.PoolingClientConnectionManager;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.metrics.SolrMetricManager;
+import org.apache.solr.metrics.SolrMetricProducer;
+
+/**
+ * Sub-class of PoolingHttpClientConnectionManager which tracks metrics interesting to Solr.
+ * Inspired by dropwizard metrics-httpclient library implementation.
+ */
+public class InstrumentedPoolingClientConnectionManager extends PoolingClientConnectionManager implements SolrMetricProducer {
+ protected MetricRegistry metricsRegistry;
+
+ public InstrumentedPoolingClientConnectionManager(SchemeRegistry schreg) {
+ super(schreg);
+ }
+
+ public MetricRegistry getMetricsRegistry() {
+ return metricsRegistry;
+ }
+
+ public void setMetricsRegistry(MetricRegistry metricRegistry) {
+ this.metricsRegistry = metricRegistry;
+ }
+
+ @Override
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ @Override
+ public String getVersion() {
+ return getClass().getPackage().getSpecificationVersion();
+ }
+
+ @Override
+ public Collection<String> initializeMetrics(SolrMetricManager manager, String registry, String scope) {
+ this.metricsRegistry = manager.registry(registry);
+ metricsRegistry.register(SolrMetricManager.mkName("availableConnections", scope),
+ (Gauge<Integer>) () -> {
+ // this acquires a lock on the connection pool; remove if contention sucks
+ return getTotalStats().getAvailable();
+ });
+ metricsRegistry.register(SolrMetricManager.mkName("leasedConnections", scope),
+ (Gauge<Integer>) () -> {
+ // this acquires a lock on the connection pool; remove if contention sucks
+ return getTotalStats().getLeased();
+ });
+ metricsRegistry.register(SolrMetricManager.mkName("maxConnections", scope),
+ (Gauge<Integer>) () -> {
+ // this acquires a lock on the connection pool; remove if contention sucks
+ return getTotalStats().getMax();
+ });
+ metricsRegistry.register(SolrMetricManager.mkName("pendingConnections", scope),
+ (Gauge<Integer>) () -> {
+ // this acquires a lock on the connection pool; remove if contention sucks
+ return getTotalStats().getPending();
+ });
+ return Arrays.asList("availableConnections", "leasedConnections", "maxConnections", "pendingConnections");
+ }
+
+ @Override
+ public String getDescription() {
+ return "";
+ }
+
+ @Override
+ public Category getCategory() {
+ return Category.OTHER;
+ }
+
+ @Override
+ public String getSource() {
+ return null;
+ }
+
+ @Override
+ public URL[] getDocs() {
+ return null;
+ }
+
+ @Override
+ public NamedList getStatistics() {
+ return null;
+ }
+}
[2/2] lucene-solr:branch_6x: SOLR-9877: Null check for metric
registry before attempting to use it
Posted by sh...@apache.org.
SOLR-9877: Null check for metric registry before attempting to use it
(cherry picked from commit 662be93)
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f65dc061
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f65dc061
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f65dc061
Branch: refs/heads/branch_6x
Commit: f65dc06180bdb02cfbfa048e2f08d1183c250d5d
Parents: a50ebcb
Author: Shalin Shekhar Mangar <sh...@apache.org>
Authored: Thu Dec 29 09:57:03 2016 +0530
Committer: Shalin Shekhar Mangar <sh...@apache.org>
Committed: Wed Jan 4 11:06:06 2017 +0530
----------------------------------------------------------------------
.../solr/util/stats/InstrumentedHttpRequestExecutor.java | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f65dc061/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
index ad76d73..0426780 100644
--- a/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
+++ b/solr/core/src/java/org/apache/solr/util/stats/InstrumentedHttpRequestExecutor.java
@@ -53,11 +53,16 @@ public class InstrumentedHttpRequestExecutor extends HttpRequestExecutor impleme
@Override
public HttpResponse execute(HttpRequest request, HttpClientConnection conn, HttpContext context) throws IOException, HttpException {
- final Timer.Context timerContext = timer(request).time();
+ Timer.Context timerContext = null;
+ if (metricsRegistry != null) {
+ timerContext = timer(request).time();
+ }
try {
return super.execute(request, conn, context);
} finally {
- timerContext.stop();
+ if (timerContext != null) {
+ timerContext.stop();
+ }
}
}