Search in sources :

Example 6 with Pair

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);
}
Also used : MetricMetadata(com.signalfx.codahale.reporter.MetricMetadata) SignalFxReporterFactory(com.nike.riposte.metrics.codahale.contrib.SignalFxReporterFactory) TimeUnit(java.util.concurrent.TimeUnit) RollingWindowTimerBuilder(com.nike.riposte.metrics.codahale.impl.SignalFxEndpointMetricsHandler.RollingWindowTimerBuilder) Pair(com.nike.internal.util.Pair) Test(org.junit.Test)

Example 7 with Pair

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;
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) ArrayList(java.util.ArrayList) Pair(com.nike.internal.util.Pair)

Example 8 with Pair

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();
    }
}
Also used : SimpleChannelInboundHandler(io.netty.channel.SimpleChannelInboundHandler) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) SocketChannel(io.netty.channel.socket.SocketChannel) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) SocketChannel(io.netty.channel.socket.SocketChannel) Channel(io.netty.channel.Channel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) HttpClientCodec(io.netty.handler.codec.http.HttpClientCodec) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ChannelPipeline(io.netty.channel.ChannelPipeline) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) HttpObjectAggregator(io.netty.handler.codec.http.HttpObjectAggregator) CompletableFuture(java.util.concurrent.CompletableFuture) EventLoopGroup(io.netty.channel.EventLoopGroup) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) HttpObject(io.netty.handler.codec.http.HttpObject) Bootstrap(io.netty.bootstrap.Bootstrap) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) Pair(com.nike.internal.util.Pair) TimeoutException(java.util.concurrent.TimeoutException)

Example 9 with Pair

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);
}
Also used : AbstractConfiguration(org.apache.commons.configuration.AbstractConfiguration) MainClassUtils(com.nike.riposte.util.MainClassUtils) Collection(java.util.Collection) ConfigurationManager(com.netflix.config.ConfigurationManager) Set(java.util.Set) Server(com.nike.riposte.server.Server) IOException(java.io.IOException) Pair(com.nike.internal.util.Pair) ServerConfig(com.nike.riposte.server.config.ServerConfig) Function(java.util.function.Function) Collectors(java.util.stream.Collectors) LinkedHashSet(java.util.LinkedHashSet) LinkedHashSet(java.util.LinkedHashSet) IOException(java.io.IOException) AbstractConfiguration(org.apache.commons.configuration.AbstractConfiguration) Collection(java.util.Collection)

Example 10 with Pair

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();
    }
}
Also used : SocketChannel(io.netty.channel.socket.SocketChannel) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) HttpClientCodec(io.netty.handler.codec.http.HttpClientCodec) CompletableFuture(java.util.concurrent.CompletableFuture) HttpObject(io.netty.handler.codec.http.HttpObject) Bootstrap(io.netty.bootstrap.Bootstrap) DefaultErrorDTO(com.nike.backstopper.model.DefaultErrorDTO) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) Pair(com.nike.internal.util.Pair) TimeoutException(java.util.concurrent.TimeoutException) SimpleChannelInboundHandler(io.netty.channel.SimpleChannelInboundHandler) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) HttpRequest(io.netty.handler.codec.http.HttpRequest) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) DefaultErrorContractDTO(com.nike.backstopper.model.DefaultErrorContractDTO) SocketChannel(io.netty.channel.socket.SocketChannel) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) Channel(io.netty.channel.Channel) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ChannelPipeline(io.netty.channel.ChannelPipeline) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) HttpObjectAggregator(io.netty.handler.codec.http.HttpObjectAggregator) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) EventLoopGroup(io.netty.channel.EventLoopGroup) HttpObject(io.netty.handler.codec.http.HttpObject) ApiError(com.nike.backstopper.apierror.ApiError) SampleCoreApiError(com.nike.backstopper.apierror.sample.SampleCoreApiError) Test(org.junit.Test)

Aggregations

Pair (com.nike.internal.util.Pair)12 Test (org.junit.Test)6 Bootstrap (io.netty.bootstrap.Bootstrap)4 Channel (io.netty.channel.Channel)4 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)4 ChannelPipeline (io.netty.channel.ChannelPipeline)4 EventLoopGroup (io.netty.channel.EventLoopGroup)4 SimpleChannelInboundHandler (io.netty.channel.SimpleChannelInboundHandler)4 NioEventLoopGroup (io.netty.channel.nio.NioEventLoopGroup)4 IOException (java.io.IOException)4 DownstreamChannelClosedUnexpectedlyException (com.nike.riposte.server.error.exception.DownstreamChannelClosedUnexpectedlyException)3 DownstreamIdleChannelTimeoutException (com.nike.riposte.server.error.exception.DownstreamIdleChannelTimeoutException)3 HostnameResolutionException (com.nike.riposte.server.error.exception.HostnameResolutionException)3 DataProvider (com.tngtech.java.junit.dataprovider.DataProvider)3 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)3 ApiError (com.nike.backstopper.apierror.ApiError)2 WrapperException (com.nike.backstopper.exception.WrapperException)2 DownstreamIdleChannelTimeoutHandler (com.nike.riposte.client.asynchttp.netty.downstreampipeline.DownstreamIdleChannelTimeoutHandler)2 LastOutboundMessageSendFullResponseInfo (com.nike.riposte.server.channelpipeline.message.LastOutboundMessageSendFullResponseInfo)2 NativeIoExceptionWrapper (com.nike.riposte.server.error.exception.NativeIoExceptionWrapper)2