From 7179713e211d7c3c6357423b16ab65cf9b8490f9 Mon Sep 17 00:00:00 2001 From: Eleni Dimitropoulou <12170229+eldimi@users.noreply.github.com> Date: Wed, 2 Aug 2023 16:25:02 +0300 Subject: [PATCH] chore: Add powertools specific user-agent-suffix to the AWS SDK v2 clients (#1306) --- powertools-core/pom.xml | 11 ++ .../core/internal/UserAgentConfigurator.java | 111 ++++++++++++++++ .../resources-filtered/version.properties | 9 ++ .../internal/UserAgentConfiguratorTest.java | 122 ++++++++++++++++++ .../src/test/resources/test.properties | 1 + .../src/test/resources/unreadable.properties | 2 + .../persistence/DynamoDBPersistenceStore.java | 24 ++-- .../parameters/AppConfigProvider.java | 5 + .../powertools/parameters/BaseProvider.java | 1 + .../parameters/DynamoDbProvider.java | 4 + .../powertools/parameters/SSMProvider.java | 4 + .../parameters/SecretsProvider.java | 4 + .../lambda/powertools/sqs/SqsUtils.java | 18 ++- 13 files changed, 304 insertions(+), 12 deletions(-) create mode 100644 powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/UserAgentConfigurator.java create mode 100644 powertools-core/src/main/resources-filtered/version.properties create mode 100644 powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/UserAgentConfiguratorTest.java create mode 100644 powertools-core/src/test/resources/test.properties create mode 100644 powertools-core/src/test/resources/unreadable.properties diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml index 1adb64af8..78cd735b9 100644 --- a/powertools-core/pom.xml +++ b/powertools-core/pom.xml @@ -64,6 +64,11 @@ org.aspectj aspectjrt + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j.version} + @@ -104,6 +109,12 @@ + + + src/main/resources-filtered + true + + org.apache.maven.plugins diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/UserAgentConfigurator.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/UserAgentConfigurator.java new file mode 100644 index 000000000..354305d33 --- /dev/null +++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/UserAgentConfigurator.java @@ -0,0 +1,111 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.core.internal; + +import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Can be used to create a string that can server as a User-Agent suffix in requests made with the AWS SDK clients + */ +public class UserAgentConfigurator { + + public static final String NA = "NA"; + public static final String VERSION_KEY = "powertools.version"; + public static final String PT_FEATURE_VARIABLE = "${PT_FEATURE}"; + public static final String PT_EXEC_ENV_VARIABLE = "${PT_EXEC_ENV}"; + public static final String VERSION_PROPERTIES_FILENAME = "version.properties"; + public static final String AWS_EXECUTION_ENV = "AWS_EXECUTION_ENV"; + private static final Logger LOG = LoggerFactory.getLogger(UserAgentConfigurator.class); + private static final String NO_OP = "no-op"; + private static String ptVersion = getProjectVersion(); + private static String userAgentPattern = "PT/" + PT_FEATURE_VARIABLE + "/" + ptVersion + " PTEnv/" + + PT_EXEC_ENV_VARIABLE; + + private UserAgentConfigurator() { + throw new IllegalStateException("Utility class. Not meant to be instantiated"); + } + + /** + * Retrieves the project version from the version.properties file + * + * @return the project version + */ + static String getProjectVersion() { + return getVersionFromProperties(VERSION_PROPERTIES_FILENAME, VERSION_KEY); + } + + + /** + * Retrieves the project version from a properties file. + * The file should be in the resources folder. + * The version is retrieved from the property with the given key. + * + * @param propertyFileName the name of the properties file + * @param versionKey the key of the property that contains the version + * @return the version of the project as configured in the given properties file + */ + static String getVersionFromProperties(String propertyFileName, String versionKey) { + + URL propertiesFileURI = Thread.currentThread().getContextClassLoader().getResource(propertyFileName); + if (propertiesFileURI != null) { + try (FileInputStream fis = new FileInputStream(propertiesFileURI.getPath())) { + Properties properties = new Properties(); + properties.load(fis); + String version = properties.getProperty(versionKey); + if (version != null && !version.isEmpty()) { + return version; + } + } catch (IOException e) { + LOG.warn("Unable to read {} file. Using default version.", propertyFileName); + LOG.debug("Exception:", e); + } + } + return NA; + } + + /** + * Retrieves the user agent string for the Powertools for AWS Lambda. + * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTEnv/{PT_EXEC_ENV} + * The version of the project is automatically retrieved. + * The PT_EXEC_ENV is automatically retrieved from the AWS_EXECUTION_ENV environment variable. + * If it AWS_EXECUTION_ENV is not set, PT_EXEC_ENV defaults to "NA" + * + * @param ptFeature a custom feature to be added to the user agent string (e.g. idempotency). + * If null or empty, the default PT_FEATURE is used. + * The default PT_FEATURE is "no-op". + * @return the user agent string + */ + public static String getUserAgent(String ptFeature) { + + String awsExecutionEnv = getenv(AWS_EXECUTION_ENV); + String ptExecEnv = awsExecutionEnv != null ? awsExecutionEnv : NA; + String userAgent = userAgentPattern.replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); + + if (ptFeature == null || ptFeature.isEmpty()) { + ptFeature = NO_OP; + } + return userAgent + .replace(PT_FEATURE_VARIABLE, ptFeature) + .replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); + } +} diff --git a/powertools-core/src/main/resources-filtered/version.properties b/powertools-core/src/main/resources-filtered/version.properties new file mode 100644 index 000000000..5e95fb588 --- /dev/null +++ b/powertools-core/src/main/resources-filtered/version.properties @@ -0,0 +1,9 @@ +# The filtered properties can have variables that are filled in by system properties or project properties. +# See https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html +# +# The values are replaced before copying the resources to the main output directory. Therefore, as soon as the build phase is completed, +# the values should have been replaced if the properties are available and if 'filtering' is set to true in the pom.xml +# +# +# The ${project.version} is retrieved from the respective pom.xml property +powertools.version=${project.version} \ No newline at end of file diff --git a/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/UserAgentConfiguratorTest.java b/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/UserAgentConfiguratorTest.java new file mode 100644 index 000000000..00110077f --- /dev/null +++ b/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/UserAgentConfiguratorTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.core.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mockStatic; +import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.AWS_EXECUTION_ENV; +import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.VERSION_KEY; +import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.VERSION_PROPERTIES_FILENAME; +import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.getVersionFromProperties; + +import java.io.File; +import java.util.Objects; +import java.util.regex.Pattern; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +class UserAgentConfiguratorTest { + + private static final String SEM_VER_PATTERN = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; + private static final String VERSION = UserAgentConfigurator.getProjectVersion(); + + + @Test + void testGetVersion() { + + assertThat(VERSION) + .isNotNull() + .isNotEmpty(); + assertThat(Pattern.matches(SEM_VER_PATTERN, VERSION)).isTrue(); + } + + @Test + void testGetVersionFromProperties_WrongKey() { + String version = getVersionFromProperties(VERSION_PROPERTIES_FILENAME, "some invalid key"); + + assertThat(version) + .isNotNull() + .isEqualTo("NA"); + } + + @Test + void testGetVersionFromProperties_FileNotExist() { + String version = getVersionFromProperties("some file", VERSION_KEY); + + assertThat(version) + .isNotNull() + .isEqualTo("NA"); + } + + @Test + void testGetVersionFromProperties_InvalidFile() { + File f = new File(Objects.requireNonNull(Thread.currentThread().getContextClassLoader() + .getResource("unreadable.properties")).getPath()); + f.setReadable(false); + + String version = getVersionFromProperties("unreadable.properties", VERSION_KEY); + + assertThat(version).isEqualTo("NA"); + } + + @Test + void testGetVersionFromProperties_EmptyVersion() { + String version = getVersionFromProperties("test.properties", VERSION_KEY); + + assertThat(version).isEqualTo("NA"); + } + + @Test + void testGetUserAgent() { + String userAgent = UserAgentConfigurator.getUserAgent("test-feature"); + + assertThat(userAgent) + .isNotNull() + .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/NA"); + + } + + @Test + void testGetUserAgent_NoFeature() { + String userAgent = UserAgentConfigurator.getUserAgent(""); + + assertThat(userAgent) + .isNotNull() + .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + } + + @Test + void testGetUserAgent_NullFeature() { + String userAgent = UserAgentConfigurator.getUserAgent(null); + + assertThat(userAgent) + .isNotNull() + .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + } + + @Test + void testGetUserAgent_SetAWSExecutionEnv() { + try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) { + mockedSystemWrapper.when(() -> getenv(AWS_EXECUTION_ENV)).thenReturn("AWS_Lambda_java8"); + String userAgent = UserAgentConfigurator.getUserAgent("test-feature"); + + assertThat(userAgent) + .isNotNull() + .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8"); + } + } + +} diff --git a/powertools-core/src/test/resources/test.properties b/powertools-core/src/test/resources/test.properties new file mode 100644 index 000000000..65756b8dd --- /dev/null +++ b/powertools-core/src/test/resources/test.properties @@ -0,0 +1 @@ +powertools.version= \ No newline at end of file diff --git a/powertools-core/src/test/resources/unreadable.properties b/powertools-core/src/test/resources/unreadable.properties new file mode 100644 index 000000000..42ff4693f --- /dev/null +++ b/powertools-core/src/test/resources/unreadable.properties @@ -0,0 +1,2 @@ +# This is intentionally left empty +# It used during testing and is set to un-readable to fulfil the test purposes. \ No newline at end of file diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java index 7a023b4de..d7301b149 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java +++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java @@ -14,6 +14,18 @@ package software.amazon.lambda.powertools.idempotency.persistence; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.utils.StringUtils; +import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.idempotency.Constants; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_REGION_ENV; import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; @@ -25,11 +37,7 @@ import java.util.OptionalLong; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest; @@ -37,10 +45,6 @@ import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; -import software.amazon.awssdk.utils.StringUtils; -import software.amazon.lambda.powertools.idempotency.Constants; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; /** * DynamoDB version of the {@link PersistenceStore}. Will store idempotency data in DynamoDB.
@@ -49,6 +53,7 @@ public class DynamoDBPersistenceStore extends BasePersistenceStore implements PersistenceStore { private static final Logger LOG = LoggerFactory.getLogger(DynamoDBPersistenceStore.class); + public static final String IDEMPOTENCY = "idempotency"; private final String tableName; private final String keyAttr; @@ -92,6 +97,7 @@ private DynamoDBPersistenceStore(String tableName, if (idempotencyDisabledEnv == null || "false".equalsIgnoreCase(idempotencyDisabledEnv)) { this.dynamoDbClient = DynamoDbClient.builder() .httpClient(UrlConnectionHttpClient.builder().build()) + .overrideConfiguration(ClientOverrideConfiguration.builder().putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, UserAgentConfigurator.getUserAgent(IDEMPOTENCY)).build()) .region(Region.of(System.getenv(AWS_REGION_ENV))) .build(); } else { diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java index 130be25a3..0df05f875 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java @@ -17,12 +17,15 @@ import java.util.HashMap; import java.util.Map; import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse; import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest; +import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @@ -153,6 +156,8 @@ public AppConfigProvider build() { client = AppConfigDataClient.builder() .httpClientBuilder(UrlConnectionHttpClient.builder()) .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) .build(); } diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java index e7bfdf835..e6481c5da 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java @@ -31,6 +31,7 @@ */ @NotThreadSafe public abstract class BaseProvider implements ParamProvider { + public static final String PARAMETERS = "parameters"; protected final CacheManager cacheManager; private TransformationManager transformationManager; diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java index 2b0694a5d..499241927 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java @@ -18,6 +18,8 @@ import java.util.Map; import java.util.stream.Collectors; import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; @@ -26,6 +28,7 @@ import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.services.dynamodb.model.QueryRequest; import software.amazon.awssdk.services.dynamodb.model.QueryResponse; +import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @@ -132,6 +135,7 @@ private static DynamoDbClient createClient() { return DynamoDbClient.builder() .httpClientBuilder(UrlConnectionHttpClient.builder()) .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder().putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) .build(); } diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java index b24b1e319..4cfd8f899 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java @@ -18,6 +18,8 @@ import java.util.HashMap; import java.util.Map; import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.ssm.SsmClient; @@ -25,6 +27,7 @@ import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; import software.amazon.awssdk.utils.StringUtils; +import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; import software.amazon.lambda.powertools.parameters.transform.Transformer; @@ -248,6 +251,7 @@ private static SsmClient createClient() { return SsmClient.builder() .httpClientBuilder(UrlConnectionHttpClient.builder()) .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder().putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) .build(); } diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java index 99b87f84b..788367ea8 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java @@ -20,10 +20,13 @@ import java.util.Base64; import java.util.Map; import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; import software.amazon.lambda.powertools.parameters.transform.Transformer; @@ -158,6 +161,7 @@ private static SecretsManagerClient createClient() { return SecretsManagerClient.builder() .httpClientBuilder(UrlConnectionHttpClient.builder()) .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder().putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) .build(); } diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java index ace2a42d6..c838180fd 100644 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java +++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java @@ -27,8 +27,11 @@ import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.sqs.SqsClient; +import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.sqs.exception.SkippedMessageDueToFailedBatchException; import software.amazon.lambda.powertools.sqs.internal.BatchContext; import software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect; @@ -42,10 +45,10 @@ */ @Deprecated public final class SqsUtils { - private static final Logger LOG = LoggerFactory.getLogger(SqsUtils.class); + public static final String SQS = "sqs"; + private static final Logger LOG = LoggerFactory.getLogger(SqsUtils.class); private static final ObjectMapper objectMapper = new ObjectMapper(); - // The attribute on an SQS-FIFO message used to record the message group ID private static final String MESSAGE_GROUP_ID = "MessageGroupId"; private static SqsClient client; private static S3Client s3Client; @@ -497,7 +500,11 @@ public static List batchProcessor(final SQSEvent event, final List handlerReturn = new ArrayList<>(); if (client == null) { - client = SqsClient.create(); + client = (SqsClient) SqsClient.builder() + .overrideConfiguration(ClientOverrideConfiguration.builder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, + UserAgentConfigurator.getUserAgent(SQS)) + .build()); } BatchContext batchContext = new BatchContext(client); @@ -586,6 +593,11 @@ public static ObjectMapper objectMapper() { public static S3Client s3Client() { if (null == s3Client) { + s3Client = (S3Client) S3Client.builder() + .overrideConfiguration(ClientOverrideConfiguration.builder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, + UserAgentConfigurator.getUserAgent(SQS)) + .build()); SqsUtils.s3Client = S3Client.create(); }