Skip to content

Commit 775d36d

Browse files
committed
Merge branch 'main' into v2_support_dynamic_and_json
2 parents eb68c76 + 7b7749f commit 775d36d

File tree

4 files changed

+98
-4
lines changed

4 files changed

+98
-4
lines changed

client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,39 @@
1313
import com.clickhouse.client.api.data_formats.internal.SerializerUtils;
1414
import com.clickhouse.client.api.enums.ProxyType;
1515
import com.clickhouse.client.api.http.ClickHouseHttpProto;
16+
import io.micrometer.core.annotation.Timed;
17+
import org.apache.hc.client5.http.AuthenticationStrategy;
1618
import org.apache.hc.client5.http.ConnectTimeoutException;
19+
import org.apache.hc.client5.http.classic.ExecChain;
20+
import org.apache.hc.client5.http.classic.ExecChainHandler;
1721
import org.apache.hc.client5.http.classic.methods.HttpPost;
1822
import org.apache.hc.client5.http.config.ConnectionConfig;
1923
import org.apache.hc.client5.http.config.RequestConfig;
24+
import org.apache.hc.client5.http.impl.ChainElement;
25+
import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
26+
import org.apache.hc.client5.http.impl.DefaultClientConnectionReuseStrategy;
27+
import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
2028
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
29+
import org.apache.hc.client5.http.impl.classic.ConnectExec;
2130
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
2231
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
2332
import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;
2433
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
2534
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
2635
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
36+
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
2737
import org.apache.hc.client5.http.protocol.HttpClientContext;
2838
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
2939
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
3040
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
3141
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
42+
import org.apache.hc.core5.http.ClassicHttpRequest;
3243
import org.apache.hc.core5.http.ClassicHttpResponse;
3344
import org.apache.hc.core5.http.ConnectionRequestTimeoutException;
3445
import org.apache.hc.core5.http.ContentType;
3546
import org.apache.hc.core5.http.Header;
3647
import org.apache.hc.core5.http.HttpEntity;
48+
import org.apache.hc.core5.http.HttpException;
3749
import org.apache.hc.core5.http.HttpHeaders;
3850
import org.apache.hc.core5.http.HttpHost;
3951
import org.apache.hc.core5.http.HttpRequest;
@@ -45,7 +57,10 @@
4557
import org.apache.hc.core5.http.impl.io.DefaultHttpResponseParserFactory;
4658
import org.apache.hc.core5.http.io.SocketConfig;
4759
import org.apache.hc.core5.http.io.entity.EntityTemplate;
60+
import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
4861
import org.apache.hc.core5.http.protocol.HttpContext;
62+
import org.apache.hc.core5.http.protocol.RequestTargetHost;
63+
import org.apache.hc.core5.http.protocol.RequestUserAgent;
4964
import org.apache.hc.core5.io.CloseMode;
5065
import org.apache.hc.core5.io.IOCallback;
5166
import org.apache.hc.core5.net.URIBuilder;
@@ -81,7 +96,9 @@
8196
import java.util.Objects;
8297
import java.util.Properties;
8398
import java.util.Set;
99+
import java.util.concurrent.ConcurrentLinkedQueue;
84100
import java.util.concurrent.TimeUnit;
101+
import java.util.concurrent.atomic.AtomicLong;
85102
import java.util.function.Function;
86103

87104
public class HttpAPIClientHelper {
@@ -219,7 +236,7 @@ private HttpClientConnectionManager poolConnectionManager(LayeredConnectionSocke
219236

220237

221238
int networkBufferSize = MapUtils.getInt(chConfiguration, "client_network_buffer_size");
222-
ManagedHttpClientConnectionFactory connectionFactory = new ManagedHttpClientConnectionFactory(
239+
MeteredManagedHttpClientConnectionFactory connectionFactory = new MeteredManagedHttpClientConnectionFactory(
223240
Http1Config.custom()
224241
.setBufferSize(networkBufferSize)
225242
.build(),
@@ -238,6 +255,9 @@ private HttpClientConnectionManager poolConnectionManager(LayeredConnectionSocke
238255
Class<?> micrometerLoader = getClass().getClassLoader().loadClass("com.clickhouse.client.api.metrics.MicrometerLoader");
239256
Method applyMethod = micrometerLoader.getDeclaredMethod("applyPoolingMetricsBinder", Object.class, String.class, PoolingHttpClientConnectionManager.class);
240257
applyMethod.invoke(micrometerLoader, metricsRegistry, mGroupName, phccm);
258+
259+
applyMethod = micrometerLoader.getDeclaredMethod("applyConnectionMetricsBinder", Object.class, String.class, MeteredManagedHttpClientConnectionFactory.class);
260+
applyMethod.invoke(micrometerLoader, metricsRegistry, mGroupName, connectionFactory);
241261
} catch (Exception e) {
242262
LOG.error("Failed to register metrics", e);
243263
}
@@ -758,7 +778,6 @@ public void close() {
758778
httpClient.close(CloseMode.IMMEDIATE);
759779
}
760780

761-
762781
/**
763782
* This factory is used only when no ssl connections are required (no https endpoints).
764783
* Internally http client would create factory and spend time if no supplied.
@@ -779,4 +798,34 @@ public Socket connectSocket(TimeValue connectTimeout, Socket socket, HttpHost ho
779798
return null;
780799
}
781800
}
801+
802+
public class MeteredManagedHttpClientConnectionFactory extends ManagedHttpClientConnectionFactory {
803+
public MeteredManagedHttpClientConnectionFactory(Http1Config http1Config, CharCodingConfig charCodingConfig, DefaultHttpResponseParserFactory defaultHttpResponseParserFactory) {
804+
super(http1Config, charCodingConfig, defaultHttpResponseParserFactory);
805+
}
806+
807+
ConcurrentLinkedQueue<Long> times = new ConcurrentLinkedQueue<>();
808+
809+
810+
@Override
811+
public ManagedHttpClientConnection createConnection(Socket socket) throws IOException {
812+
long startT = System.currentTimeMillis();
813+
try {
814+
return super.createConnection(socket);
815+
} finally {
816+
long endT = System.currentTimeMillis();
817+
times.add(endT - startT);
818+
}
819+
}
820+
821+
public long getTime() {
822+
int count = times.size();
823+
long runningAverage = 0;
824+
for (int i = 0; i < count; i++) {
825+
runningAverage += times.poll();
826+
}
827+
828+
return count > 0 ? runningAverage / count : 0;
829+
}
830+
}
782831
}

client-v2/src/main/java/com/clickhouse/client/api/metrics/MicrometerLoader.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.clickhouse.client.api.metrics;
22

33
import com.clickhouse.client.api.ClientMisconfigurationException;
4+
import com.clickhouse.client.api.internal.HttpAPIClientHelper;
5+
import io.micrometer.core.instrument.Counter;
6+
import io.micrometer.core.instrument.Gauge;
47
import io.micrometer.core.instrument.MeterRegistry;
58
import io.micrometer.core.instrument.binder.httpcomponents.hc5.PoolingHttpClientConnectionManagerMetricsBinder;
69
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
@@ -14,4 +17,15 @@ public static void applyPoolingMetricsBinder(Object registry, String metricsGrou
1417
throw new ClientMisconfigurationException("Unsupported registry type." + registry.getClass());
1518
}
1619
}
20+
21+
public static void applyConnectionMetricsBinder(Object registry, String metricsGroupName, HttpAPIClientHelper.MeteredManagedHttpClientConnectionFactory factory) {
22+
if (registry instanceof MeterRegistry) {
23+
Gauge.builder("httpcomponents.httpclient.connect.time", factory, HttpAPIClientHelper.MeteredManagedHttpClientConnectionFactory::getTime)
24+
.description("The running average connection creation time.")
25+
.tag("httpclient", metricsGroupName)
26+
.register((MeterRegistry) registry);
27+
} else {
28+
throw new ClientMisconfigurationException("Unsupported registry type." + registry.getClass());
29+
}
30+
}
1731
}

client-v2/src/test/java/com/clickhouse/client/metrics/MetricsTest.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public void testRegisterMetrics() throws Exception {
6060
Gauge totalMax = meterRegistry.get("httpcomponents.httpclient.pool.total.max").gauge();
6161
Gauge available = meterRegistry.get("httpcomponents.httpclient.pool.total.connections").tags("state", "available").gauge();
6262
Gauge leased = meterRegistry.get("httpcomponents.httpclient.pool.total.connections").tags("state", "leased").gauge();
63+
Gauge times = meterRegistry.get("httpcomponents.httpclient.connect.time").gauge();
6364

6465
Assert.assertEquals((int) totalMax.value(), Integer.parseInt(ClientConfigProperties.HTTP_MAX_OPEN_CONNECTIONS.getDefaultValue()));
6566
Assert.assertEquals((int) available.value(), 1);
@@ -95,7 +96,30 @@ public void testRegisterMetrics() throws Exception {
9596
Assert.assertEquals((int) leased.value(), 0);
9697

9798
}
98-
// currently there are only 5 metrics that are monitored by micrometer (out of the box)
99-
assertEquals(meterRegistry.getMeters().size(), 5);
99+
// currently there are only 7 metrics that are monitored by micrometer (out of the box)
100+
assertEquals(meterRegistry.getMeters().size(), 6);
101+
}
102+
103+
//Disabled because we can't assume the time is greater than 0
104+
@Test(groups = { "integration" }, enabled = false)
105+
public void testConnectionTime() throws Exception {
106+
ClickHouseNode node = getServer(ClickHouseProtocol.HTTP);
107+
boolean isSecure = isCloud();
108+
109+
try (Client client = new Client.Builder()
110+
.addEndpoint(Protocol.HTTP, "192.168.1.1", node.getPort(), isSecure)
111+
.setUsername("default")
112+
.setPassword(ClickHouseServerForTest.getPassword())
113+
.setDefaultDatabase(ClickHouseServerForTest.getDatabase())
114+
.setConnectTimeout(5, ChronoUnit.SECONDS)
115+
.registerClientMetrics(meterRegistry, "pool-test")
116+
.build()) {
117+
118+
client.ping();
119+
Gauge times = meterRegistry.get("httpcomponents.httpclient.connect.time").gauge();
120+
121+
Assert.assertTrue(times.value() > 0);
122+
assertEquals(times.value(), 0);//Second time should be 0
123+
}
100124
}
101125
}

client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,4 +2127,11 @@ public boolean isVersionMatch(String versionExpression) {
21272127
List<GenericRecord> serverVersion = client.queryAll("SELECT version()");
21282128
return ClickHouseVersion.of(serverVersion.get(0).getString(1)).check(versionExpression);
21292129
}
2130+
2131+
@Test(groups = {"integration"})
2132+
public void testEmptyResponse() throws Exception {
2133+
try (QueryResponse response = client.query("SELECT number FROM system.numbers LIMIT 0", new QuerySettings().setFormat(ClickHouseFormat.RowBinary)).get()) {
2134+
System.out.println(response.getResultRows());
2135+
}
2136+
}
21302137
}

0 commit comments

Comments
 (0)