ok2c closed pull request #89: add dropwizard metrics to httpclient
URL: https://github.com/apache/httpcomponents-client/pull/89
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/httpclient/pom.xml b/httpclient/pom.xml
index 320ce5ea7..84739f523 100644
--- a/httpclient/pom.xml
+++ b/httpclient/pom.xml
@@ -54,6 +54,11 @@
<artifactId>commons-codec</artifactId>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>io.dropwizard.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
diff --git
a/httpclient/src/main/java/org/apache/http/client/MetricConstants.java
b/httpclient/src/main/java/org/apache/http/client/MetricConstants.java
new file mode 100644
index 000000000..f9b5f558f
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/client/MetricConstants.java
@@ -0,0 +1,46 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.client;
+
+/**
+ * constants for {@link com.codahale.metrics.MetricRegistry}
+ *
+ * @since 4.5.5
+ */
+public class MetricConstants {
+ public static final String REQUESTS_PER_SECOND = "requests-per-second";
+
+ public static final String SUCCEEDED_REQUESTS_PER_SECOND =
"succeeded-requests-per-second";
+
+ public static final String FAILED_REQUESTS_PER_SECOND =
"failed-requests-per-second";
+
+ // in milliseconds
+ public static final String RESPONSE_TIME = "response-time";
+
+ public static final String SLOW_REQUESTS_PER_SECOND =
"slow-requests-per-second";
+}
diff --git
a/httpclient/src/main/java/org/apache/http/client/utils/MetricUtils.java
b/httpclient/src/main/java/org/apache/http/client/utils/MetricUtils.java
new file mode 100644
index 000000000..9f571e28d
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/client/utils/MetricUtils.java
@@ -0,0 +1,101 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.client.utils;
+
+import com.codahale.metrics.MetricRegistry;
+
+/**
+ * utilities for {@link com.codahale.metrics.MetricRegistry}
+ *
+ * @since 4.5.5
+ */
+public class MetricUtils {
+ /**
+ * increase counter
+ * @param metricRegistry
+ * @param itemName
+ * @param value
+ */
+ public static void inc(final MetricRegistry metricRegistry, final String
itemName, final long value) {
+ if (metricRegistry != null) {
+ try {
+ metricRegistry.counter(itemName).inc(value);
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }
+
+ /**
+ * decrease counter
+ * @param metricRegistry
+ * @param itemName
+ * @param value
+ */
+ public static void dec(final MetricRegistry metricRegistry, final String
itemName, final long value) {
+ if (metricRegistry != null) {
+ try {
+ metricRegistry.counter(itemName).dec(value);
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }
+
+ /**
+ * mark meter
+ * @param metricRegistry
+ * @param itemName
+ * @param value
+ */
+ public static void mark(final MetricRegistry metricRegistry, final String
itemName, final long value) {
+ if (metricRegistry != null) {
+ try {
+ metricRegistry.meter(itemName).mark(value);
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }
+
+ /**
+ * update histogram
+ * @param metricRegistry
+ * @param itemName
+ * @param value
+ */
+ public static void update(final MetricRegistry metricRegistry, final
String itemName, final long value) {
+ if (metricRegistry != null) {
+ try {
+ metricRegistry.histogram(itemName).update(value);
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }
+}
diff --git
a/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java
b/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java
index 866d6c12a..acf5db1c5 100644
---
a/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java
+++
b/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java
@@ -31,6 +31,7 @@
import java.io.IOException;
import java.net.URI;
+import com.codahale.metrics.MetricRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
@@ -40,9 +41,11 @@
import org.apache.http.annotation.ThreadingBehavior;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
+import org.apache.http.client.MetricConstants;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.MetricUtils;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
@@ -58,6 +61,8 @@
private final Log log = LogFactory.getLog(getClass());
+ private MetricRegistry metricRegistry;
+
protected abstract CloseableHttpResponse doExecute(HttpHost target,
HttpRequest request,
HttpContext context) throws IOException, ClientProtocolException;
@@ -69,7 +74,26 @@ public CloseableHttpResponse execute(
final HttpHost target,
final HttpRequest request,
final HttpContext context) throws IOException,
ClientProtocolException {
- return doExecute(target, request, context);
+ final long prologue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.REQUESTS_PER_SECOND, 1);
+
+ try {
+ final CloseableHttpResponse closeableHttpResponse =
doExecute(target, request, context);
+
+ final long epilogue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.SUCCEEDED_REQUESTS_PER_SECOND, 1);
+ MetricUtils.update(this.metricRegistry,
MetricConstants.RESPONSE_TIME, epilogue - prologue);
+
+ return closeableHttpResponse;
+ } catch (ClientProtocolException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
+ } catch (IOException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
+ }
}
/**
@@ -79,8 +103,27 @@ public CloseableHttpResponse execute(
public CloseableHttpResponse execute(
final HttpUriRequest request,
final HttpContext context) throws IOException,
ClientProtocolException {
- Args.notNull(request, "HTTP request");
- return doExecute(determineTarget(request), request, context);
+ final long prologue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.REQUESTS_PER_SECOND, 1);
+
+ try {
+ Args.notNull(request, "HTTP request");
+ final CloseableHttpResponse closeableHttpResponse =
doExecute(determineTarget(request), request, context);
+
+ final long epilogue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.SUCCEEDED_REQUESTS_PER_SECOND, 1);
+ MetricUtils.update(this.metricRegistry,
MetricConstants.RESPONSE_TIME, epilogue - prologue);
+
+ return closeableHttpResponse;
+ } catch (ClientProtocolException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
+ } catch (IOException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
+ }
}
private static HttpHost determineTarget(final HttpUriRequest request)
throws ClientProtocolException {
@@ -115,7 +158,26 @@ public CloseableHttpResponse execute(
public CloseableHttpResponse execute(
final HttpHost target,
final HttpRequest request) throws IOException,
ClientProtocolException {
- return doExecute(target, request, null);
+ final long prologue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.REQUESTS_PER_SECOND, 1);
+
+ try {
+ final CloseableHttpResponse closeableHttpResponse =
doExecute(target, request, null);
+
+ final long epilogue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.SUCCEEDED_REQUESTS_PER_SECOND, 1);
+ MetricUtils.update(this.metricRegistry,
MetricConstants.RESPONSE_TIME, epilogue - prologue);
+
+ return closeableHttpResponse;
+ } catch (ClientProtocolException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
+ } catch (IOException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
+ }
}
/**
@@ -216,28 +278,54 @@ public CloseableHttpResponse execute(
public <T> T execute(final HttpHost target, final HttpRequest request,
final ResponseHandler<? extends T> responseHandler, final
HttpContext context)
throws IOException, ClientProtocolException {
- Args.notNull(responseHandler, "Response handler");
+ final long prologue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.REQUESTS_PER_SECOND, 1);
- final CloseableHttpResponse response = execute(target, request,
context);
try {
- final T result = responseHandler.handleResponse(response);
- final HttpEntity entity = response.getEntity();
- EntityUtils.consume(entity);
- return result;
- } catch (final ClientProtocolException t) {
- // Try to salvage the underlying connection in case of a protocol
exception
- final HttpEntity entity = response.getEntity();
+ Args.notNull(responseHandler, "Response handler");
+
+ final CloseableHttpResponse response = execute(target, request,
context);
try {
+ final T result = responseHandler.handleResponse(response);
+ final HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
- } catch (final Exception t2) {
- // Log this exception. The original exception is more
- // important and will be thrown to the caller.
- this.log.warn("Error consuming content after an exception.",
t2);
+
+ final long epilogue = System.currentTimeMillis();
+
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.SUCCEEDED_REQUESTS_PER_SECOND, 1);
+ MetricUtils.update(this.metricRegistry,
MetricConstants.RESPONSE_TIME, epilogue - prologue);
+
+ return result;
+ } catch (final ClientProtocolException t) {
+ // Try to salvage the underlying connection in case of a
protocol exception
+ final HttpEntity entity = response.getEntity();
+ try {
+ EntityUtils.consume(entity);
+ } catch (final Exception t2) {
+ // Log this exception. The original exception is more
+ // important and will be thrown to the caller.
+ this.log.warn("Error consuming content after an
exception.", t2);
+ }
+ throw t;
+ } finally {
+ response.close();
}
- throw t;
- } finally {
- response.close();
+ } catch (ClientProtocolException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
+ } catch (IOException e) {
+ MetricUtils.mark(this.metricRegistry,
MetricConstants.FAILED_REQUESTS_PER_SECOND, 1);
+ throw e;
}
}
+ public MetricRegistry getMetricRegistry() {
+ return this.metricRegistry;
+ }
+
+ public void setMetricRegistry(final MetricRegistry metricRegistry) {
+ this.metricRegistry = metricRegistry;
+ }
+
}
diff --git
a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java
b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java
index 3a7c5613b..8a902d133 100644
---
a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java
+++
b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java
@@ -42,6 +42,7 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
+import com.codahale.metrics.MetricRegistry;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.Header;
import org.apache.http.HttpHost;
@@ -216,6 +217,8 @@
private PublicSuffixMatcher publicSuffixMatcher;
+ private MetricRegistry metricRegistry;
+
public static HttpClientBuilder create() {
return new HttpClientBuilder();
}
@@ -864,6 +867,11 @@ public final HttpClientBuilder evictIdleConnections(final
long maxIdleTime, fina
return this;
}
+ public final HttpClientBuilder setMetricRegistry(final MetricRegistry
metricRegistry) {
+ this.metricRegistry = metricRegistry;
+ return this;
+ }
+
/**
* Produces an instance of {@link ClientExecChain} to be used as a main
exec.
* <p>
@@ -1236,7 +1244,7 @@ public void close() throws IOException {
});
}
- return new InternalHttpClient(
+ final InternalHttpClient internalHttpClient = new InternalHttpClient(
execChain,
connManagerCopy,
routePlannerCopy,
@@ -1246,6 +1254,9 @@ public void close() throws IOException {
defaultCredentialsProvider,
defaultRequestConfig != null ? defaultRequestConfig :
RequestConfig.DEFAULT,
closeablesCopy);
+ internalHttpClient.setMetricRegistry(metricRegistry);
+
+ return internalHttpClient;
}
}
diff --git
a/httpclient/src/test/java/org/apache/http/impl/client/TestCloseableHttpClient.java
b/httpclient/src/test/java/org/apache/http/impl/client/TestCloseableHttpClient.java
index 766f2338d..f03d636ec 100644
---
a/httpclient/src/test/java/org/apache/http/impl/client/TestCloseableHttpClient.java
+++
b/httpclient/src/test/java/org/apache/http/impl/client/TestCloseableHttpClient.java
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.io.InputStream;
+import com.codahale.metrics.MetricRegistry;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
@@ -75,6 +76,7 @@ public void setup() throws Exception {
Mockito.when(entity.isStreaming()).thenReturn(Boolean.TRUE);
Mockito.when(response.getEntity()).thenReturn(entity);
client = Mockito.mock(NoopCloseableHttpClient.class,
Mockito.CALLS_REAL_METHODS);
+ client.setMetricRegistry(new MetricRegistry());
}
@Test
diff --git
a/httpclient/src/test/java/org/apache/http/impl/client/TestInternalHttpClient.java
b/httpclient/src/test/java/org/apache/http/impl/client/TestInternalHttpClient.java
index 9567073c5..a318d6d1a 100644
---
a/httpclient/src/test/java/org/apache/http/impl/client/TestInternalHttpClient.java
+++
b/httpclient/src/test/java/org/apache/http/impl/client/TestInternalHttpClient.java
@@ -30,6 +30,7 @@
import java.io.IOException;
import java.util.Arrays;
+import com.codahale.metrics.MetricRegistry;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthSchemeProvider;
@@ -88,7 +89,7 @@ public void setup() throws Exception {
client = new InternalHttpClient(execChain, connManager, routePlanner,
cookieSpecRegistry, authSchemeRegistry, cookieStore,
credentialsProvider,
defaultConfig, Arrays.asList(closeable1, closeable2));
-
+ client.setMetricRegistry(new MetricRegistry());
}
@Test
diff --git a/pom.xml b/pom.xml
index 6776d50d8..f11f59b34 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,7 @@
<httpcore.version>4.4.8</httpcore.version>
<commons-logging.version>1.2</commons-logging.version>
<commons-codec.version>1.10</commons-codec.version>
+ <metrics.version>3.2.5</metrics.version>
<ehcache.version>2.6.11</ehcache.version>
<memcached.version>2.12.3</memcached.version>
<slf4j.version>1.7.25</slf4j.version>
@@ -123,6 +124,11 @@
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
+ <dependency>
+ <groupId>io.dropwizard.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]