Skip to content

Commit 38eebc5

Browse files
kanagat kananinja nugusbayevfelixbarny
authored andcommitted
Change APM Server check from OkHttp to URLConnection (#284)
closes #272
1 parent dcae0ff commit 38eebc5

File tree

8 files changed

+138
-77
lines changed

8 files changed

+138
-77
lines changed

apm-agent-core/pom.xml

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,6 @@
5454
</build>
5555

5656
<dependencies>
57-
<dependency>
58-
<groupId>com.squareup.okhttp3</groupId>
59-
<artifactId>okhttp</artifactId>
60-
<version>${version.okhttp}</version>
61-
</dependency>
62-
<dependency>
63-
<groupId>com.squareup.okhttp3</groupId>
64-
<artifactId>logging-interceptor</artifactId>
65-
<version>${version.okhttp}</version>
66-
</dependency>
6757
<dependency>
6858
<groupId>com.lmax</groupId>
6959
<artifactId>disruptor</artifactId>
@@ -102,6 +92,18 @@
10292
<version>${version.byte-buddy}</version>
10393
</dependency>
10494

95+
<dependency>
96+
<groupId>com.squareup.okhttp3</groupId>
97+
<artifactId>okhttp</artifactId>
98+
<version>${version.okhttp}</version>
99+
<scope>test</scope>
100+
</dependency>
101+
<dependency>
102+
<groupId>com.squareup.okhttp3</groupId>
103+
<artifactId>logging-interceptor</artifactId>
104+
<version>${version.okhttp}</version>
105+
<scope>test</scope>
106+
</dependency>
105107
<dependency>
106108
<groupId>io.undertow</groupId>
107109
<artifactId>undertow-core</artifactId>

apm-agent-core/src/main/java/co/elastic/apm/report/ApmServerHealthChecker.java

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,50 +19,70 @@
1919
*/
2020
package co.elastic.apm.report;
2121

22-
import okhttp3.OkHttpClient;
23-
import okhttp3.Request;
24-
import okhttp3.Response;
2522
import org.slf4j.Logger;
2623
import org.slf4j.LoggerFactory;
2724

25+
import javax.net.ssl.HttpsURLConnection;
26+
import javax.net.ssl.SSLSocketFactory;
2827
import java.io.IOException;
28+
import java.net.HttpURLConnection;
29+
import java.net.URL;
2930

30-
// TODO use UrlConnection and remove OkHttp dependency
3131
class ApmServerHealthChecker implements Runnable {
3232
private static final Logger logger = LoggerFactory.getLogger(ApmServerHealthChecker.class);
33-
private final OkHttpClient httpClient;
33+
3434
private final ReporterConfiguration reporterConfiguration;
3535

36-
ApmServerHealthChecker(OkHttpClient httpClient, ReporterConfiguration reporterConfiguration) {
37-
this.httpClient = httpClient;
36+
ApmServerHealthChecker(ReporterConfiguration reporterConfiguration) {
3837
this.reporterConfiguration = reporterConfiguration;
3938
}
4039

4140
@Override
4241
public void run() {
4342
boolean success;
4443
String message = null;
44+
HttpURLConnection connection = null;
4545
try {
46-
final Response response = httpClient.newCall(new Request.Builder()
47-
.url(reporterConfiguration.getServerUrls().get(0).toString())
48-
.build())
49-
.execute();
50-
final int status = response.code();
46+
URL url = new URL(reporterConfiguration.getServerUrls().get(0).toString() + "/healthcheck");
47+
if (logger.isDebugEnabled()) {
48+
logger.debug("Starting healthcheck to {}", url);
49+
}
50+
connection = (HttpURLConnection) url.openConnection();
51+
if (!reporterConfiguration.isVerifyServerCert()) {
52+
if (connection instanceof HttpsURLConnection) {
53+
trustAll((HttpsURLConnection) connection);
54+
}
55+
}
56+
if (reporterConfiguration.getSecretToken() != null) {
57+
connection.setRequestProperty("Authorization", "Bearer " + reporterConfiguration.getSecretToken());
58+
}
59+
connection.setConnectTimeout((int) reporterConfiguration.getServerTimeout().getMillis());
60+
connection.setReadTimeout((int) reporterConfiguration.getServerTimeout().getMillis());
61+
connection.connect();
62+
63+
final int status = connection.getResponseCode();
64+
5165
success = status < 300;
66+
5267
if (!success) {
5368
if (status == 404) {
5469
message = "It seems like you are using a version of the APM Server which is not compatible with this agent. " +
5570
"Please use APM Server 6.5.0 or newer.";
5671
} else {
5772
message = Integer.toString(status);
5873
}
59-
} else if (response.body() != null) {
74+
} else {
6075
// prints out the version info of the APM Server
61-
message = response.body().string();
76+
message = HttpUtils.getBody(connection);
6277
}
6378
} catch (IOException e) {
6479
message = e.getMessage();
6580
success = false;
81+
} finally {
82+
if (connection != null) {
83+
connection.disconnect();
84+
connection = null;
85+
}
6686
}
6787

6888
if (success) {
@@ -71,4 +91,13 @@ public void run() {
7191
logger.warn("Elastic APM server is not available ({})", message);
7292
}
7393
}
94+
95+
private void trustAll(HttpsURLConnection connection) {
96+
final SSLSocketFactory sf = SslUtils.getTrustAllSocketFactory();
97+
if (sf != null) {
98+
// using the same instances is important for TCP connection reuse
99+
connection.setHostnameVerifier(SslUtils.getTrustAllHostnameVerifyer());
100+
connection.setSSLSocketFactory(sf);
101+
}
102+
}
74103
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*-
2+
* #%L
3+
* Elastic APM Java agent
4+
* %%
5+
* Copyright (C) 2018 Elastic and contributors
6+
* %%
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* #L%
19+
*/
20+
package co.elastic.apm.report;
21+
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
25+
import java.io.BufferedReader;
26+
import java.io.IOException;
27+
import java.io.InputStream;
28+
import java.io.InputStreamReader;
29+
import java.net.HttpURLConnection;
30+
31+
public class HttpUtils {
32+
33+
private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
34+
35+
private HttpUtils() {
36+
37+
}
38+
39+
public static String getBody(HttpURLConnection connection) {
40+
String body;
41+
try {
42+
if (connection == null || connection.getInputStream() == null)
43+
return null;
44+
body = readInputStream(connection.getInputStream());
45+
return body;
46+
} catch (final IOException e) {
47+
logger.error("Reading inputStream: {}", e.getMessage());
48+
try {
49+
body = readInputStream(connection.getErrorStream());
50+
return body;
51+
} catch (IOException e1) {
52+
logger.error("Reading errorStream: {}", e1.getMessage());
53+
}
54+
}
55+
return null;
56+
}
57+
58+
private static String readInputStream(final InputStream inputStream) throws IOException {
59+
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
60+
final StringBuilder bodyString = new StringBuilder();
61+
String line;
62+
while ((line = bufferedReader.readLine()) != null) {
63+
bodyString.append(line);
64+
}
65+
bufferedReader.close();
66+
return bodyString.toString();
67+
}
68+
69+
}

apm-agent-core/src/main/java/co/elastic/apm/report/ReporterFactory.java

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,15 @@
2828
import co.elastic.apm.report.processor.ProcessorEventHandler;
2929
import co.elastic.apm.report.serialize.DslJsonSerializer;
3030
import co.elastic.apm.util.VersionUtils;
31-
import okhttp3.Interceptor;
32-
import okhttp3.OkHttpClient;
33-
import okhttp3.Request;
34-
import okhttp3.Response;
35-
import okhttp3.logging.HttpLoggingInterceptor;
3631
import org.slf4j.Logger;
3732
import org.slf4j.LoggerFactory;
3833
import org.stagemonitor.configuration.ConfigurationRegistry;
3934

4035
import javax.annotation.Nonnull;
4136
import javax.annotation.Nullable;
42-
import javax.net.ssl.SSLSocketFactory;
43-
import java.io.IOException;
4437
import java.util.concurrent.ExecutorService;
4538
import java.util.concurrent.Executors;
4639
import java.util.concurrent.ThreadFactory;
47-
import java.util.concurrent.TimeUnit;
4840

4941
public class ReporterFactory {
5042

@@ -54,7 +46,6 @@ public class ReporterFactory {
5446
public Reporter createReporter(ConfigurationRegistry configurationRegistry, @Nullable String frameworkName,
5547
@Nullable String frameworkVersion) {
5648
final ReporterConfiguration reporterConfiguration = configurationRegistry.getConfig(ReporterConfiguration.class);
57-
final OkHttpClient httpClient = getOkHttpClient(reporterConfiguration);
5849
ExecutorService healthCheckExecutorService = Executors.newFixedThreadPool(1, new ThreadFactory() {
5950
@Override
6051
public Thread newThread(Runnable r) {
@@ -64,7 +55,7 @@ public Thread newThread(Runnable r) {
6455
return thread;
6556
}
6657
});
67-
healthCheckExecutorService.submit(new ApmServerHealthChecker(httpClient, reporterConfiguration));
58+
healthCheckExecutorService.submit(new ApmServerHealthChecker(reporterConfiguration));
6859
healthCheckExecutorService.shutdown();
6960
final ReportingEventHandler reportingEventHandler = getReportingEventHandler(configurationRegistry, frameworkName,
7061
frameworkVersion, reporterConfiguration);
@@ -87,45 +78,11 @@ private ReportingEventHandler getReportingEventHandler(ConfigurationRegistry con
8778
processorEventHandler, payloadSerializer);
8879
}
8980

90-
@Nonnull
91-
OkHttpClient getOkHttpClient(ReporterConfiguration reporterConfiguration) {
92-
final OkHttpClient.Builder builder = new OkHttpClient.Builder()
93-
.connectTimeout(reporterConfiguration.getServerTimeout().getMillis(), TimeUnit.MILLISECONDS);
94-
if (!reporterConfiguration.isVerifyServerCert()) {
95-
disableCertificateValidation(builder);
96-
}
97-
if (logger.isTraceEnabled()) {
98-
final HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
99-
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
100-
builder.addInterceptor(loggingInterceptor);
101-
}
102-
builder.addInterceptor(new Interceptor() {
103-
@Override
104-
public Response intercept(Chain chain) throws IOException {
105-
Request originalRequest = chain.request();
106-
Request requestWithUserAgent = originalRequest.newBuilder()
107-
.header("User-Agent", userAgent)
108-
.build();
109-
return chain.proceed(chain.request());
110-
}
111-
});
112-
return builder.build();
113-
}
114-
11581
private String getUserAgent() {
11682
String agentVersion = VersionUtils.getAgentVersion();
11783
if (agentVersion != null) {
11884
return "apm-agent-java " + agentVersion;
11985
}
12086
return "apm-agent-java";
12187
}
122-
123-
private void disableCertificateValidation(OkHttpClient.Builder builder) {
124-
final SSLSocketFactory sf = SslUtils.getTrustAllSocketFactory();
125-
if (sf != null) {
126-
builder
127-
.sslSocketFactory(sf, SslUtils.getTrustAllTrustManager())
128-
.hostnameVerifier(SslUtils.getTrustAllHostnameVerifyer());
129-
}
130-
}
13188
}

apm-agent-core/src/test/java/co/elastic/apm/AbstractServletTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ final void initServer() throws Exception {
6767
.build();
6868
}
6969

70-
7170
protected Response get(String path) throws IOException {
7271
return httpClient.newCall(new okhttp3.Request.Builder().url("http://localhost:" + getPort() + path).build()).execute();
7372
}

apm-agent-plugins/apm-servlet-plugin/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@
3434
<version>${version.spring}</version>
3535
<scope>test</scope>
3636
</dependency>
37+
<dependency>
38+
<groupId>com.squareup.okhttp3</groupId>
39+
<artifactId>okhttp</artifactId>
40+
<version>${version.okhttp}</version>
41+
<scope>test</scope>
42+
</dependency>
43+
<dependency>
44+
<groupId>com.squareup.okhttp3</groupId>
45+
<artifactId>logging-interceptor</artifactId>
46+
<version>${version.okhttp}</version>
47+
<scope>test</scope>
48+
</dependency>
3749
</dependencies>
3850

3951

apm-agent-plugins/apm-servlet-plugin/src/test/java/co/elastic/apm/servlet/ServletInstrumentationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ private void testInstrumentation(ElasticApmInstrumentation instrumentation, int
9797
final Response response = get(path);
9898
assertThat(response.code()).isEqualTo(200);
9999
assertThat(response.body().string()).isEqualTo("Hello World!");
100+
100101
if (expectedTransactions > 0) {
101102
reporter.getFirstTransaction(500);
102103
}

elastic-apm-agent/pom.xml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,6 @@
4444
<pattern>com.lmax</pattern>
4545
<shadedPattern>co.elastic.apm.shaded.lmax</shadedPattern>
4646
</relocation>
47-
<relocation>
48-
<pattern>okhttp</pattern>
49-
<shadedPattern>co.elastic.apm.shaded.okhttp</shadedPattern>
50-
</relocation>
51-
<relocation>
52-
<pattern>okio</pattern>
53-
<shadedPattern>co.elastic.apm.shaded.okio</shadedPattern>
54-
</relocation>
5547
<relocation>
5648
<pattern>org.slf4j</pattern>
5749
<shadedPattern>co.elastic.apm.shaded.slf4j</shadedPattern>

0 commit comments

Comments
 (0)