
com.undefinedlabs.scope.network.HttpClientImpl Maven / Gradle / Ivy
package com.undefinedlabs.scope.network;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import com.undefinedlabs.scope.logger.ScopeLogger;
import com.undefinedlabs.scope.logger.ScopeLoggerResolver;
import com.undefinedlabs.scope.settings.ScopeSettings;
import com.undefinedlabs.scope.settings.credentials.CredentialsUtils;
import com.undefinedlabs.scope.settings.credentials.ScopeCredentials;
import com.undefinedlabs.scope.utils.StringUtils;
import com.undefinedlabs.scope.utils.props.SystemProps;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class HttpClientImpl implements HttpClient {
private static final ScopeLogger LOGGER = ScopeLoggerResolver.INSTANCE.get();
private static final int DEFAULT_TOTAL_RETRIES = 3;
private static final long DEFAULT_BACKOFF_RETRY = 1000;
private static final int DEFAULT_CONNECTION_POOL_SIZE = 5;
private static final long DEFAULT_CONNECTION_KEEP_ALIVE_DURATION = 300000;
private final int totalRetries;
private final long backoffRetry;
private final String apiEndpoint;
private final OkHttpClient okHttpClient;
public HttpClientImpl(final Builder builder) {
totalRetries = builder.totalRetries;
backoffRetry = builder.backoffRetry;
apiEndpoint = builder.credentials.getApiEndpoint();
okHttpClient =
new OkHttpClient.Builder()
.connectionPool(
new ConnectionPool(
builder.poolSize, builder.keepAliveDuration, TimeUnit.MILLISECONDS))
.addInterceptor(new UserAgentFilter(builder.userAgent))
.addInterceptor(new ApiKeyFilter(builder.credentials.getApiKey()))
.build();
}
@Override
public Response get(final String path) {
final Request request =
new Request.Builder().url(HttpClientUtils.INSTANCE.createUrl(apiEndpoint, path)).build();
return execute(request);
}
@Override
public Response post(final String path, final RequestBody requestBody) throws NetworkException {
final Request request =
new Request.Builder()
.url(HttpClientUtils.INSTANCE.createUrl(apiEndpoint, path))
.post(requestBody)
.build();
return execute(request);
}
Response execute(final Request originalReq) {
final String idReq = UUID.randomUUID().toString();
final String url = originalReq.url().toString();
int retries = totalRetries;
boolean mustRetry = false;
Response lastResponse = null;
Throwable lastError = null;
do {
if (lastResponse != null) {
lastResponse.close();
}
final Request request = originalReq.newBuilder().build();
final long startReqTimestamp = System.currentTimeMillis();
try {
lastResponse = okHttpClient.newCall(request).execute();
HttpClientUtils.INSTANCE.logRequestExecutionDuration(
idReq, url, startReqTimestamp, originalReq.body(), lastResponse);
if (!lastResponse.isSuccessful()) {
mustRetry = lastResponse.code() >= 500 && lastResponse.code() != 501;
} else {
if (mustRetry) {
LOGGER.info(
"[idReq:"
+ idReq
+ "] ScopeAgent --> Backend ("
+ url
+ ") successful after "
+ (DEFAULT_TOTAL_RETRIES - retries)
+ " retries.");
}
}
} catch (final Throwable e) {
LOGGER.error("[idReq:" + idReq + "] -- Error ScopeAgent --> Backend (" + url + "): " + e);
lastError = e;
mustRetry = false;
}
if (retries == 0) {
mustRetry = false;
}
if (mustRetry) {
try {
Thread.sleep(backoffRetry);
} catch (final InterruptedException ignored) {
// Ignored
}
LOGGER.debug(
"[idReq:"
+ idReq
+ "] -- Retrying ScopeAgent --> Backend ("
+ url
+ "). Left "
+ retries
+ " retries.");
retries -= 1;
}
} while (mustRetry);
if (lastError != null) {
throw new NetworkException(lastError);
}
return lastResponse;
}
public static class Builder {
private final ScopeCredentials credentials;
private final int poolSize;
private final long keepAliveDuration;
private final String userAgent;
private int totalRetries;
private long backoffRetry;
public Builder(final ScopeSettings settings) {
try {
credentials =
CredentialsUtils.INSTANCE.extractFromDsn(
(String) settings.getSetting(ScopeSettings.SCOPE_DSN));
final Object connectionPoolSize =
settings.getSetting(ScopeSettings.SCOPE_TRACER_DISPATCHER_CONNECTIONS_POOL_SIZE);
final Object connectionKeepAliveDuration =
settings.getSetting(
ScopeSettings.SCOPE_TRACER_DISPATCHER_CONNECTIONS_KEEP_ALIVE_DURATION);
poolSize =
connectionPoolSize != null ? (int) connectionPoolSize : DEFAULT_CONNECTION_POOL_SIZE;
keepAliveDuration =
connectionKeepAliveDuration != null
? (long) connectionKeepAliveDuration
: DEFAULT_CONNECTION_KEEP_ALIVE_DURATION;
userAgent =
"scope-agent-java"
+ (StringUtils.isNotEmpty(SystemProps.AGENT_VERSION)
? "/" + SystemProps.AGENT_VERSION
: "");
totalRetries = DEFAULT_TOTAL_RETRIES;
backoffRetry = DEFAULT_BACKOFF_RETRY;
} catch (final Exception e) {
throw new IllegalArgumentException(e.getMessage());
}
}
public Builder withTotalRetries(final int totalRetries) {
this.totalRetries = totalRetries;
return this;
}
public Builder withBackoffRetry(final long backoffRetry) {
this.backoffRetry = backoffRetry;
return this;
}
public HttpClient build() {
return new HttpClientImpl(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy