1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.http.crt.internal; 17 18 import static software.amazon.awssdk.http.HttpMetric.AVAILABLE_CONCURRENCY; 19 import static software.amazon.awssdk.http.HttpMetric.CONCURRENCY_ACQUIRE_DURATION; 20 import static software.amazon.awssdk.http.HttpMetric.LEASED_CONCURRENCY; 21 import static software.amazon.awssdk.http.HttpMetric.MAX_CONCURRENCY; 22 import static software.amazon.awssdk.http.HttpMetric.PENDING_CONCURRENCY_ACQUIRES; 23 import static software.amazon.awssdk.utils.NumericUtils.saturatedCast; 24 25 import java.io.IOException; 26 import java.time.Duration; 27 import javax.net.ssl.SSLHandshakeException; 28 import software.amazon.awssdk.annotations.SdkInternalApi; 29 import software.amazon.awssdk.crt.http.HttpClientConnection; 30 import software.amazon.awssdk.crt.http.HttpClientConnectionManager; 31 import software.amazon.awssdk.crt.http.HttpException; 32 import software.amazon.awssdk.crt.http.HttpManagerMetrics; 33 import software.amazon.awssdk.metrics.MetricCollector; 34 35 @SdkInternalApi 36 public final class CrtUtils { 37 public static final int CRT_TLS_NEGOTIATION_ERROR_CODE = 1029; 38 CrtUtils()39 private CrtUtils() { 40 } 41 wrapWithIoExceptionIfRetryable(HttpException httpException)42 public static Throwable wrapWithIoExceptionIfRetryable(HttpException httpException) { 43 Throwable toThrow = httpException; 44 45 if (HttpClientConnection.isErrorRetryable(httpException)) { 46 // IOExceptions get retried, and if the CRT says this error is retryable, 47 // it's semantically an IOException anyway. 48 toThrow = new IOException(httpException); 49 } 50 return toThrow; 51 } 52 wrapConnectionFailureException(Throwable throwable)53 public static Throwable wrapConnectionFailureException(Throwable throwable) { 54 Throwable toThrow = new IOException("An exception occurred when acquiring a connection", throwable); 55 if (throwable instanceof HttpException) { 56 HttpException httpException = (HttpException) throwable; 57 58 if (httpException.getErrorCode() == CRT_TLS_NEGOTIATION_ERROR_CODE) { 59 toThrow = new SSLHandshakeException(httpException.getMessage()); 60 } 61 } 62 63 return toThrow; 64 } 65 reportMetrics(HttpClientConnectionManager connManager, MetricCollector metricCollector, long acquireStartTime)66 public static void reportMetrics(HttpClientConnectionManager connManager, MetricCollector metricCollector, 67 long acquireStartTime) { 68 long acquireCompletionTime = System.nanoTime(); 69 Duration acquireTimeTaken = Duration.ofNanos(acquireCompletionTime - acquireStartTime); 70 metricCollector.reportMetric(CONCURRENCY_ACQUIRE_DURATION, acquireTimeTaken); 71 HttpManagerMetrics managerMetrics = connManager.getManagerMetrics(); 72 // currently this executor only handles HTTP 1.1. Until H2 is added, the max concurrency settings are 1:1 with TCP 73 // connections. When H2 is added, this code needs to be updated to handle stream multiplexing 74 metricCollector.reportMetric(MAX_CONCURRENCY, connManager.getMaxConnections()); 75 metricCollector.reportMetric(AVAILABLE_CONCURRENCY, saturatedCast(managerMetrics.getAvailableConcurrency())); 76 metricCollector.reportMetric(LEASED_CONCURRENCY, saturatedCast(managerMetrics.getLeasedConcurrency())); 77 metricCollector.reportMetric(PENDING_CONCURRENCY_ACQUIRES, saturatedCast(managerMetrics.getPendingConcurrencyAcquires())); 78 } 79 80 } 81