use of io.datarouter.httpclient.response.exception.DatarouterHttpCircuitBreakerException in project datarouter by hotpads.
the class DatarouterHttpClientIoExceptionCircuitBreaker method call.
public DatarouterHttpResponse call(CloseableHttpClient httpClient, DatarouterHttpRequest request, Consumer<HttpEntity> httpEntityConsumer, HttpClientContext context, Supplier<Boolean> enableBreakers, Supplier<Boolean> traceInQueryString, Supplier<Boolean> debugLog) throws DatarouterHttpException {
CircuitBreakerState state = getState();
if (state == CircuitBreakerState.OPEN && enableBreakers.get()) {
incrementCounterOnStateChange("open");
throw new DatarouterHttpCircuitBreakerException(name, callResultQueue.getOriginalException());
}
DatarouterHttpException ex;
TracerTool.startSpan("http call " + request.getPath(), TraceSpanGroupType.HTTP);
Tracer tracer = TracerThreadLocal.get();
W3TraceContext traceContext;
if (tracer != null && tracer.getTraceContext().isPresent()) {
traceContext = tracer.getTraceContext().get().copy();
traceContext.updateParentIdAndAddTracestateMember();
} else {
count("traceContext null");
traceContext = new W3TraceContext(Trace2Dto.getCurrentTimeInNs());
}
String traceparent = traceContext.getTraceparent().toString();
if (traceInQueryString.get()) {
request.addGetParam(TRACEPARENT, traceparent);
}
HttpRequestBase internalHttpRequest = request.getRequest();
count("request");
logger.debug("traceparent={} passing to request={}", traceparent, request.getPath());
internalHttpRequest.addHeader(TRACEPARENT, traceparent);
internalHttpRequest.addHeader(TRACESTATE, traceContext.getTracestate().toString());
context.setAttribute(TRACEPARENT, traceContext.getTraceparent().toString());
if (debugLog.get()) {
logger.warn("sending http request method={} url={}", internalHttpRequest.getMethod(), internalHttpRequest.getURI());
}
long requestStartTimeNs = Trace2Dto.getCurrentTimeInNs();
try {
HttpResponse httpResponse = httpClient.execute(internalHttpRequest, context);
Duration duration = Duration.ofNanos(Trace2Dto.getCurrentTimeInNs() - requestStartTimeNs);
String entity = null;
int statusCode = httpResponse.getStatusLine().getStatusCode();
count("response " + statusCode);
boolean isBadStatusCode = statusCode >= HttpStatus.SC_BAD_REQUEST;
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
// skip the httpEntityConsumer in case of error because we are going to close the input stream
if (httpEntityConsumer != null && !isBadStatusCode) {
httpEntityConsumer.accept(httpEntity);
} else {
entity = EntityUtils.toString(httpEntity);
}
}
Optional<Traceparent> remoteTraceparent = Optional.ofNullable(httpResponse.getFirstHeader(TRACEPARENT)).map(Header::getValue).map(Traceparent::parse).filter(Optional::isPresent).map(Optional::get);
remoteTraceparent.ifPresent(tp -> TracerTool.appendToSpanInfo("remote parentId", tp.parentId));
if (remoteTraceparent.isPresent() && remoteTraceparent.get().shouldSample()) {
// if remote server has forced sample for trace, we also force sample the client's trace
TracerTool.setForceSample();
}
if (duration.compareTo(LOG_SLOW_REQUEST_THRESHOLD) > 0) {
logger.warn("Slow request target={} durationS={} remoteTraceparent={}", request.getPath(), duration.getSeconds(), remoteTraceparent.orElse(null));
}
DatarouterHttpResponse response = new DatarouterHttpResponse(httpResponse, context, statusCode, entity);
if (isBadStatusCode) {
TracerTool.appendToSpanInfo("bad status code", statusCode);
ex = new DatarouterHttpResponseException(response, duration, traceparent, request.getPath());
callResultQueue.insertFalseResultWithException(ex);
// no need to abort the connection, we received a response line, the connection is probably still good
response.tryClose();
throw ex;
}
if (state == CircuitBreakerState.HALF_OPEN) {
callResultQueue.reset();
incrementCounterOnStateChange("closing");
logger.error("Half opened circuit now closing. CircuitName={}", name);
}
callResultQueue.insertTrueResult();
return response;
} catch (IOException e) {
count("IOException");
TracerTool.appendToSpanInfo("exception", e.getMessage());
ex = new DatarouterHttpConnectionAbortedException(e, TimeUnit.NANOSECONDS.toMillis(requestStartTimeNs), traceparent, request.getPath());
callResultQueue.insertFalseResultWithException(ex);
} catch (CancellationException e) {
count("CancellationException");
TracerTool.appendToSpanInfo("exception", e.getMessage());
ex = new DatarouterHttpRequestInterruptedException(e, TimeUnit.NANOSECONDS.toMillis(requestStartTimeNs), traceparent, request.getPath());
callResultQueue.insertFalseResultWithException(ex);
} finally {
TracerTool.finishSpan();
}
// connection might have gone bad, destroying it
if (internalHttpRequest != null) {
forceAbortRequestUnchecked(internalHttpRequest);
}
throw ex;
}
Aggregations