use of com.nike.internal.util.Pair in project riposte by Nike-Inc.
the class SignalFxEndpointMetricsHandlerTest method two_arg_constructor_sets_fields_as_expected.
@Test
public void two_arg_constructor_sets_fields_as_expected() {
// given
SignalFxReporterFactory reporterFactoryMock = mock(SignalFxReporterFactory.class);
Pair<Pair<SignalFxReporter, MetricMetadata>, Pair<Long, TimeUnit>> wiredUpMocksAndData = wireUpReporterFactoryMockForConstructor(reporterFactoryMock, metricRegistryMock);
MetricMetadata expectedMetricMetadata = wiredUpMocksAndData.getLeft().getRight();
long expectedReportingInterval = wiredUpMocksAndData.getRight().getLeft();
TimeUnit expectedReportingTimeUnit = wiredUpMocksAndData.getRight().getRight();
// when
SignalFxEndpointMetricsHandler instance = new SignalFxEndpointMetricsHandler(reporterFactoryMock, metricRegistryMock);
// then
assertThat(instance.metricMetadata).isSameAs(expectedMetricMetadata);
assertThat(instance.metricRegistry).isSameAs(metricRegistryMock);
assertThat(instance.requestTimerBuilder).isInstanceOf(RollingWindowTimerBuilder.class);
RollingWindowTimerBuilder rwtb = (RollingWindowTimerBuilder) instance.requestTimerBuilder;
assertThat(rwtb.amount).isEqualTo(expectedReportingInterval);
assertThat(rwtb.timeUnit).isEqualTo(expectedReportingTimeUnit);
assertThat(instance.requestTimerDimensionConfigurator).isSameAs(DEFAULT_REQUEST_LATENCY_TIMER_DIMENSION_CONFIGURATOR);
}
use of com.nike.internal.util.Pair in project riposte by Nike-Inc.
the class AccessLogger method logMessageAdditions.
/**
* @param request
* The request to log; will not be null. This is the request that came into the application. WARNING: The
* content may have been released already, so you cannot rely on any of the methods that return the payload
* content in any form.
* @param finalResponseObject
* The {@link HttpResponse} that was the actual final response object sent to the client; may be null. NOTE:
* This should be preferred over {@code responseInfo} whenever both have overlapping data since this argument
* may have been modified by outbound handlers after being initially populated by {@code responseInfo}.
* @param responseInfo
* {@link com.nike.riposte.server.http.ResponseInfo} object that was initially used to build {@code
* finalResponseObject}; may be null. NOTE: {@code finalResponseObject} may have been modified by other outbound
* handlers (e.g. compression/gzip), so if it is non-null it should be preferred over this where possible.
*
* @return A list of key/value pairs of data that should be added to the access log message following {@link
* #combinedLogFormatPrefix(RequestInfo, HttpResponse, ResponseInfo)}. This will include some defaults specified in
* this method as well as anything returned by {@link #customApplicationLogMessageExtras(RequestInfo, HttpResponse,
* ResponseInfo, Long)}.
*/
protected List<Pair<String, String>> logMessageAdditions(RequestInfo<?> request, HttpResponse finalResponseObject, ResponseInfo responseInfo, Long elapsedTimeMillis) {
String httpStatusCode = null;
String contentLengthResponseHeader = null;
String transferEncodingResponseHeader = null;
String errorUid = null;
String responseTraceId = null;
String uncompressedRawContentLength = null;
String finalContentLength = null;
if (finalResponseObject != null && finalResponseObject.getStatus() != null)
httpStatusCode = String.valueOf(finalResponseObject.getStatus().code());
else if (responseInfo != null && responseInfo.getHttpStatusCode() != null)
httpStatusCode = String.valueOf(responseInfo.getHttpStatusCode());
HttpHeaders responseHeadersToUse = null;
if (finalResponseObject != null && finalResponseObject.headers() != null)
responseHeadersToUse = finalResponseObject.headers();
else if (responseInfo != null)
responseHeadersToUse = responseInfo.getHeaders();
if (responseHeadersToUse != null) {
contentLengthResponseHeader = responseHeadersToUse.get(CONTENT_LENGTH);
transferEncodingResponseHeader = responseHeadersToUse.get(TRANSFER_ENCODING);
errorUid = responseHeadersToUse.get("error_uid");
responseTraceId = responseHeadersToUse.get(TRACE_ID);
}
if (responseInfo != null) {
if (responseInfo.getUncompressedRawContentLength() != null)
uncompressedRawContentLength = String.valueOf(responseInfo.getUncompressedRawContentLength());
if (responseInfo.getFinalContentLength() != null)
finalContentLength = String.valueOf(responseInfo.getFinalContentLength());
}
List<Pair<String, String>> logMessageAdditions = new ArrayList<>();
logMessageAdditions.addAll(Arrays.asList(Pair.of("accept-Req", request.getHeaders().get(ACCEPT)), Pair.of("content-type-Req", request.getHeaders().get(CONTENT_TYPE)), Pair.of("content-length-Res", contentLengthResponseHeader), Pair.of("transfer_encoding-Res", transferEncodingResponseHeader), Pair.of("http_status_code-Res", httpStatusCode), Pair.of("error_uid-Res", errorUid), Pair.of(TRACE_ENABLED + "-Req", request.getHeaders().get(TRACE_ENABLED)), Pair.of(SPAN_ID + "-Req", request.getHeaders().get(SPAN_ID)), Pair.of(SPAN_NAME + "-Req", request.getHeaders().get(SPAN_NAME)), Pair.of(TRACE_ID + "-Req", request.getHeaders().get(TRACE_ID)), Pair.of(TRACE_ID + "-Res", responseTraceId), Pair.of("raw_content_length-Req", String.valueOf(request.getRawContentLengthInBytes())), Pair.of("raw_content_length-Res", uncompressedRawContentLength), Pair.of("final_content_length-Res", finalContentLength), Pair.of("elapsed_time_millis", String.valueOf(elapsedTimeMillis))));
List<Pair<String, String>> customApplicationLogMessageExtras = customApplicationLogMessageExtras(request, finalResponseObject, responseInfo, elapsedTimeMillis);
if (customApplicationLogMessageExtras != null)
logMessageAdditions.addAll(customApplicationLogMessageExtras);
return logMessageAdditions;
}
use of com.nike.internal.util.Pair in project riposte by Nike-Inc.
the class ComponentTestUtils method executeRequest.
public static Pair<Integer, String> executeRequest(HttpRequest request, int port, int incompleteCallTimeoutMillis) throws Exception {
Bootstrap bootstrap = new Bootstrap();
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
CompletableFuture<Pair<Integer, String>> responseFromServer = new CompletableFuture<>();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpClientCodec());
p.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
p.addLast(new SimpleChannelInboundHandler<HttpObject>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof FullHttpResponse) {
// Store the proxyServer response for asserting on later.
FullHttpResponse responseMsg = (FullHttpResponse) msg;
responseFromServer.complete(Pair.of(responseMsg.getStatus().code(), responseMsg.content().toString(UTF_8)));
} else {
// Should never happen.
throw new RuntimeException("Received unexpected message type: " + msg.getClass());
}
}
});
}
});
// Connect to the proxyServer.
Channel ch = bootstrap.connect("localhost", port).sync().channel();
// Send the request.
ch.writeAndFlush(request);
// Wait for the response to be received
try {
responseFromServer.get(incompleteCallTimeoutMillis, TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
fail("The call took much longer than expected without receiving a response. " + "Cancelling this test - it's not working properly", ex);
} finally {
ch.close();
}
// If we reach here then the call should be complete.
return responseFromServer.get();
} finally {
eventLoopGroup.shutdownGracefully();
}
}
use of com.nike.internal.util.Pair in project riposte by Nike-Inc.
the class ArchaiusServer method infrastructureInit.
/**
* Initializes the Archaius system and configures the Netty leak detection level (if necessary).
* DO NOT CALL THIS DIRECTLY. Use {@link #launchServer(String[])} when you're ready to start the server.
*/
protected void infrastructureInit() {
MainClassUtils.setupJbossLoggingToUseSlf4j();
try {
Pair<String, String> appIdAndEnvironmentPair = MainClassUtils.getAppIdAndEnvironmentFromSystemProperties();
ConfigurationManager.loadCascadedPropertiesFromResources(appIdAndEnvironmentPair.getLeft());
} catch (IOException e) {
throw new RuntimeException("Error loading Archaius properties", e);
}
AbstractConfiguration appConfig = ConfigurationManager.getConfigInstance();
Function<String, Boolean> hasPropertyFunction = (propKey) -> appConfig.getProperty(propKey) != null;
Function<String, String> propertyExtractionFunction = (propKey) -> {
// Properties in Archaius might be a Collection or an Object.
Object propValObj = appConfig.getProperty(propKey);
return (propValObj instanceof Collection) ? ((Collection<?>) propValObj).stream().map(String::valueOf).collect(Collectors.joining(",")) : String.valueOf(propValObj);
};
Set<String> propKeys = new LinkedHashSet<>();
appConfig.getKeys().forEachRemaining(propKeys::add);
MainClassUtils.logApplicationPropertiesIfDebugActionsEnabled(hasPropertyFunction, propertyExtractionFunction, propKeys, false);
MainClassUtils.setupNettyLeakDetectionLevel(hasPropertyFunction, propertyExtractionFunction);
}
use of com.nike.internal.util.Pair in project riposte by Nike-Inc.
the class VerifyTimeoutsAndProxyConnectionPoolingWorksComponentTest method verify_incomplete_call_is_timed_out.
@Test
public void verify_incomplete_call_is_timed_out() throws InterruptedException, TimeoutException, ExecutionException, IOException {
Bootstrap bootstrap = new Bootstrap();
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
CompletableFuture<Pair<String, String>> responseFromServer = new CompletableFuture<>();
// Create a raw netty HTTP client so we can fiddle with headers and intentionally create a bad request
// that should trigger the bad call timeout.
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpClientCodec());
p.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
p.addLast(new SimpleChannelInboundHandler<HttpObject>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof FullHttpResponse) {
// Store the server response for asserting on later.
FullHttpResponse responseMsg = (FullHttpResponse) msg;
responseFromServer.complete(Pair.of(responseMsg.content().toString(CharsetUtil.UTF_8), responseMsg.headers().get(HttpHeaders.Names.CONNECTION)));
} else {
// Should never happen.
throw new RuntimeException("Received unexpected message type: " + msg.getClass());
}
}
});
}
});
// Connect to the server.
Channel ch = bootstrap.connect("localhost", downstreamServerConfig.endpointsPort()).sync().channel();
// Create a bad HTTP request. This one will be bad because it has a non-zero content-length header,
// but we're sending no payload. The server should (correctly) sit and wait for payload bytes to
// arrive until it hits the timeout, at which point it should return the correct error response.
HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, LongDelayTestEndpoint.MATCHING_PATH);
request.headers().set(HttpHeaders.Names.HOST, "localhost");
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, "100");
long beforeCallTimeNanos = System.nanoTime();
// Send the bad request.
ch.writeAndFlush(request);
// Wait for the response to be received and the connection to be closed.
try {
ch.closeFuture().get(incompleteCallTimeoutMillis * 10, TimeUnit.MILLISECONDS);
responseFromServer.get(incompleteCallTimeoutMillis * 10, TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
fail("The call took much longer than expected without receiving a response. " + "Cancelling this test - it's not working properly", ex);
}
// If we reach here then the call should be complete.
long totalCallTimeMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - beforeCallTimeNanos);
// Verify that we got back the correct error response.
// It should be a MALFORMED_REQUEST with extra metadata explaining that the call was bad.
Pair<String, String> responseInfo = responseFromServer.get();
DefaultErrorContractDTO errorContract = objectMapper.readValue(responseInfo.getLeft(), DefaultErrorContractDTO.class);
assertThat(errorContract).isNotNull();
assertThat(errorContract.errors.size()).isEqualTo(1);
DefaultErrorDTO error = errorContract.errors.get(0);
ApiError expectedApiError = SampleCoreApiError.MALFORMED_REQUEST;
Map<String, Object> expectedMetadata = MapBuilder.builder("cause", (Object) "Unfinished/invalid HTTP request").build();
assertThat(error.code).isEqualTo(expectedApiError.getErrorCode());
assertThat(error.message).isEqualTo(expectedApiError.getMessage());
assertThat(error.metadata).isEqualTo(expectedMetadata);
// The server should have closed the connection even though we asked for keep-alive.
assertThat(responseInfo.getRight()).isEqualTo(HttpHeaders.Values.CLOSE);
// Total call time should be pretty close to incompleteCallTimeoutMillis give or take a few
// milliseconds, but due to the inability to account for slow machines running the unit tests,
// a server that isn't warmed up, etc, we can't put a ceiling on the wiggle room we'd need, so
// we'll just verify it took at least the minimum necessary amount of time.
assertThat(totalCallTimeMillis).isGreaterThanOrEqualTo(incompleteCallTimeoutMillis);
} finally {
eventLoopGroup.shutdownGracefully();
}
}
Aggregations