diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml
index b389df6fe..850be6922 100644
--- a/powertools-batch/pom.xml
+++ b/powertools-batch/pom.xml
@@ -50,6 +50,16 @@
powertools-serialization
${project.version}
+
+ software.amazon.lambda
+ powertools-common
+ ${project.version}
+
+
+ software.amazon.awssdk
+ sdk-core
+ provided
+
@@ -57,12 +67,6 @@
junit-jupiter-api
test
-
- org.slf4j
- slf4j-simple
- 2.0.17
- test
-
org.assertj
assertj-core
@@ -83,6 +87,11 @@
slf4j-simple
test
+
+ software.amazon.awssdk
+ s3
+ test
+
-
\ No newline at end of file
+
diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptor.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptor.java
new file mode 100644
index 000000000..f49dbe5c5
--- /dev/null
+++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.batch.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-batch module is on the classpath.
+ */
+public final class BatchUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("batch");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-batch/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-batch/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..51764f87f
--- /dev/null
+++ b/powertools-batch/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.batch.internal.BatchUserAgentInterceptor
diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptorTest.java
new file mode 100644
index 000000000..2841a1724
--- /dev/null
+++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.batch.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class BatchUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/BATCH/");
+ }
+}
diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml
index ca4e7536f..d49fcc2bc 100644
--- a/powertools-cloudformation/pom.xml
+++ b/powertools-cloudformation/pom.xml
@@ -42,6 +42,10 @@
software.amazon.awssdk
url-connection-client
+
+ software.amazon.awssdk
+ sdk-core
+
com.amazonaws
aws-lambda-java-core
@@ -58,6 +62,11 @@
org.aspectj
aspectjrt
+
+ software.amazon.lambda
+ powertools-common
+ ${project.version}
+
@@ -102,6 +111,11 @@
test-jar
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptor.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptor.java
new file mode 100644
index 000000000..c225512d1
--- /dev/null
+++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.cloudformation.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-cloudformation module is on the classpath.
+ */
+public final class CloudformationUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("cloudformation");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json
index 218382888..092ef9b54 100644
--- a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json
+++ b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json
@@ -428,5 +428,9 @@
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.cloudformation.internal.CloudformationUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json
index f3b58337b..cbbfb270d 100644
--- a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json
+++ b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json
@@ -30,6 +30,8 @@
"pattern":"\\Qorg/eclipse/jetty/version/build.properties\\E"
}, {
"pattern":"\\Qorg/publicsuffix/list/effective_tld_names.dat\\E"
+ }, {
+ "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E"
}]},
"bundles":[{
"name":"jakarta.servlet.LocalStrings",
diff --git a/powertools-cloudformation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-cloudformation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..172ca1d2c
--- /dev/null
+++ b/powertools-cloudformation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.cloudformation.internal.CloudformationUserAgentInterceptor
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptorTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptorTest.java
new file mode 100644
index 000000000..ee500d006
--- /dev/null
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.cloudformation.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class CloudformationUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/CLOUDFORMATION/");
+ }
+}
diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java
index d2e592902..7deca89f1 100644
--- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java
+++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java
@@ -18,26 +18,27 @@
import java.io.IOException;
import java.io.InputStream;
+import java.util.Locale;
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 final 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 String SDK_USER_AGENT_APP_ID = "sdk.ua.appId";
private static final Logger LOG = LoggerFactory.getLogger(UserAgentConfigurator.class);
private static final String NO_OP = "no-op";
private static final String POWERTOOLS_VERSION = getProjectVersion();
- private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTEnv/"
+ private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTENV/"
+ PT_EXEC_ENV_VARIABLE;
private UserAgentConfigurator() {
@@ -53,7 +54,6 @@ 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.
@@ -64,28 +64,46 @@ static String getProjectVersion() {
* @return the version of the project as configured in the given properties file
*/
static String getVersionFromProperties(String propertyFileName, String versionKey) {
-
- InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFileName);
-
- if (is != null) {
- try {
+ try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFileName)) {
+ if (is != null) {
Properties properties = new Properties();
properties.load(is);
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);
}
+ } catch (IOException e) {
+ LOG.warn("Unable to read {} file. Using default version.", propertyFileName);
+ LOG.debug("Exception:", e);
}
return NA;
}
+ /**
+ * Configures the AWS SDK to use Powertools user agent by setting the sdk.ua.appId system property.
+ * If the property is already set and not empty, appends the Powertools user agent with a "/" separator.
+ * This should be called during library initialization to ensure the user agent is properly configured.
+ */
+ public static void configureUserAgent(String ptFeature) {
+ try {
+ String existingValue = System.getProperty(SDK_USER_AGENT_APP_ID);
+ String powertoolsUserAgent = getUserAgent(ptFeature);
+
+ if (existingValue != null && !existingValue.isEmpty()) {
+ System.setProperty(SDK_USER_AGENT_APP_ID, existingValue + "/" + powertoolsUserAgent);
+ } else {
+ System.setProperty(SDK_USER_AGENT_APP_ID, powertoolsUserAgent);
+ }
+ } catch (Exception e) {
+ // We don't re-raise since we don't want to break the user if something in this logic doesn't work
+ LOG.warn("Unable to configure user agent system property", e);
+ }
+ }
+
/**
* Retrieves the user agent string for the Powertools for AWS Lambda.
- * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTEnv/{PT_EXEC_ENV}
+ * 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"
@@ -96,7 +114,6 @@ static String getVersionFromProperties(String propertyFileName, String versionKe
* @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 = USER_AGENT_PATTERN.replace(PT_EXEC_ENV_VARIABLE, ptExecEnv);
@@ -105,7 +122,7 @@ public static String getUserAgent(String ptFeature) {
ptFeature = NO_OP;
}
return userAgent
- .replace(PT_FEATURE_VARIABLE, ptFeature)
+ .replace(PT_FEATURE_VARIABLE, ptFeature.toUpperCase(Locale.ROOT))
.replace(PT_EXEC_ENV_VARIABLE, ptExecEnv);
}
}
diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java
index 0c7935a55..fbe4529d8 100644
--- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java
+++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java
@@ -31,11 +31,9 @@
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 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() {
@@ -91,7 +89,7 @@ void testGetUserAgent() {
assertThat(userAgent)
.isNotNull()
- .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/NA");
+ .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA");
}
@@ -101,7 +99,7 @@ void testGetUserAgent_NoFeature() {
assertThat(userAgent)
.isNotNull()
- .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA");
+ .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA");
}
@Test
@@ -110,7 +108,7 @@ void testGetUserAgent_NullFeature() {
assertThat(userAgent)
.isNotNull()
- .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA");
+ .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA");
}
@Test
@@ -120,7 +118,34 @@ void testGetUserAgent_SetAWSExecutionEnv() {
assertThat(userAgent)
.isNotNull()
- .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8");
+ .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/AWS_Lambda_java8");
+ }
+
+ @Test
+ void testConfigureUserAgent() {
+ System.clearProperty("sdk.ua.appId");
+ UserAgentConfigurator.configureUserAgent("test-feature");
+
+ assertThat(System.getProperty("sdk.ua.appId"))
+ .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA");
+ }
+
+ @Test
+ void testConfigureUserAgent_WithExistingValue() {
+ System.setProperty("sdk.ua.appId", "UserValueABC123");
+ UserAgentConfigurator.configureUserAgent("test-feature");
+
+ assertThat(System.getProperty("sdk.ua.appId"))
+ .isEqualTo("UserValueABC123/PT/TEST-FEATURE/" + VERSION + " PTENV/NA");
+ }
+
+ @Test
+ void testConfigureUserAgent_WithEmptyExistingValue() {
+ System.setProperty("sdk.ua.appId", "");
+ UserAgentConfigurator.configureUserAgent("test-feature");
+
+ assertThat(System.getProperty("sdk.ua.appId"))
+ .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA");
}
}
diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml
index 191d75eeb..885c9c9cd 100644
--- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml
+++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml
@@ -57,6 +57,10 @@
+
+ software.amazon.awssdk
+ sdk-core
+
org.crac
crac
@@ -94,6 +98,11 @@
2.2.0
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptor.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptor.java
new file mode 100644
index 000000000..98d7a7440
--- /dev/null
+++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.idempotency.dynamodb.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-idempotency-dynamodb module is on the classpath.
+ */
+public final class IdempotencyDynamodbUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("idempotency-dynamodb");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json
index f0ba9c4c2..6d6fbceb3 100644
--- a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json
+++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json
@@ -321,5 +321,9 @@
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.idempotency.dynamodb.internal.IdempotencyDynamodbUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..a04caa403
--- /dev/null
+++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.idempotency.dynamodb.internal.IdempotencyDynamodbUserAgentInterceptor
diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptorTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptorTest.java
new file mode 100644
index 000000000..e6940a760
--- /dev/null
+++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.idempotency.dynamodb.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class IdempotencyDynamodbUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/IDEMPOTENCY-DYNAMODB/");
+ }
+}
diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml
index cac2706b7..65cd7051d 100644
--- a/powertools-kafka/pom.xml
+++ b/powertools-kafka/pom.xml
@@ -78,6 +78,16 @@
aws-lambda-java-serialization
${lambda-serialization.version}
+
+ software.amazon.lambda
+ powertools-common
+ ${project.version}
+
+
+ software.amazon.awssdk
+ sdk-core
+ provided
+
@@ -120,6 +130,11 @@
assertj-core
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptor.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptor.java
new file mode 100644
index 000000000..2db4789b3
--- /dev/null
+++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.kafka.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-kafka module is on the classpath.
+ */
+public final class KafkaUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("kafka");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-kafka/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-kafka/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..1ce363ad9
--- /dev/null
+++ b/powertools-kafka/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.kafka.internal.KafkaUserAgentInterceptor
diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptorTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptorTest.java
new file mode 100644
index 000000000..4323a42e9
--- /dev/null
+++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.kafka.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class KafkaUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/KAFKA/");
+ }
+}
\ No newline at end of file
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptor.java
new file mode 100644
index 000000000..87d179dd7
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.largemessages.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-largemessages module is on the classpath.
+ */
+public final class LargeMessagesUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("large-messages");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-large-messages/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-large-messages/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..ab5a6f378
--- /dev/null
+++ b/powertools-large-messages/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.largemessages.internal.LargeMessagesUserAgentInterceptor
diff --git a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptorTest.java b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptorTest.java
new file mode 100644
index 000000000..b32ee1176
--- /dev/null
+++ b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.largemessages.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class LargeMessagesUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/LARGE-MESSAGES/");
+ }
+}
\ No newline at end of file
diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml
index 92283b0cf..2b85a3752 100644
--- a/powertools-logging/powertools-logging-log4j/pom.xml
+++ b/powertools-logging/powertools-logging-log4j/pom.xml
@@ -39,6 +39,11 @@
org.apache.logging.log4j
log4j-layout-template-json
+
+ software.amazon.awssdk
+ sdk-core
+ provided
+
@@ -93,6 +98,11 @@
test-jar
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptor.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptor.java
new file mode 100644
index 000000000..510ee858c
--- /dev/null
+++ b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.logging.log4j.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-logging-log4j module is on the classpath.
+ */
+public final class Log4jUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("logging-log4j");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json
index adbd9e0c1..6cbbee583 100644
--- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json
+++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json
@@ -1083,5 +1083,9 @@
"name":"software.amazon.lambda.powertools.logging.log4j.BufferingAppender",
"queryAllDeclaredMethods":true,
"methods":[{"name":"createAppender","parameterTypes":["java.lang.String","org.apache.logging.log4j.core.Filter","org.apache.logging.log4j.core.Layout","org.apache.logging.log4j.core.config.AppenderRef[]","org.apache.logging.log4j.core.config.Configuration","java.lang.String","int","boolean"] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.logging.log4j.internal.Log4jUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json
index cf017fdeb..a4bcd55fa 100644
--- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json
+++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json
@@ -34,6 +34,8 @@
"pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E"
}, {
"pattern":"\\QStackTraceElementLayout.json\\E"
+ }, {
+ "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E"
}]},
"bundles":[]
}
diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..22150f4b7
--- /dev/null
+++ b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.logging.log4j.internal.Log4jUserAgentInterceptor
diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptorTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptorTest.java
new file mode 100644
index 000000000..77d5b06e3
--- /dev/null
+++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.logging.log4j.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class Log4jUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/LOGGING-LOG4J/");
+ }
+}
diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml
index ff0312001..17e39dda7 100644
--- a/powertools-logging/powertools-logging-logback/pom.xml
+++ b/powertools-logging/powertools-logging-logback/pom.xml
@@ -36,6 +36,11 @@
+
+ software.amazon.awssdk
+ sdk-core
+ provided
+
@@ -90,6 +95,11 @@
junit-pioneer
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptor.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptor.java
new file mode 100644
index 000000000..c35171a01
--- /dev/null
+++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.logging.logback.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-logging-logback module is on the classpath.
+ */
+public final class LogbackUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("logging-logback");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json
index dfc50427f..d4f4a4d7d 100644
--- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json
+++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json
@@ -179,5 +179,9 @@
"name":"software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder",
"queryAllPublicMethods":true,
"methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.logging.logback.internal.LogbackUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json
index 33d1d61c4..b60a39ad5 100644
--- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json
+++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json
@@ -10,6 +10,8 @@
"pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E"
}, {
"pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E"
+ }, {
+ "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E"
}]},
"bundles":[]
}
diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-logging/powertools-logging-logback/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..1ce49119f
--- /dev/null
+++ b/powertools-logging/powertools-logging-logback/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.logging.logback.internal.LogbackUserAgentInterceptor
diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptorTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptorTest.java
new file mode 100644
index 000000000..622343668
--- /dev/null
+++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.logging.logback.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class LogbackUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/LOGGING-LOGBACK/");
+ }
+}
diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml
index c1ac723f1..58eab8a45 100644
--- a/powertools-metrics/pom.xml
+++ b/powertools-metrics/pom.xml
@@ -73,6 +73,11 @@
org.apache.commons
commons-lang3
+
+ software.amazon.awssdk
+ sdk-core
+ provided
+
@@ -117,6 +122,11 @@
test-jar
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java
new file mode 100644
index 000000000..5a466cc3a
--- /dev/null
+++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.metrics.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the metrics module is on the classpath.
+ */
+public final class MetricsUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("metrics");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json
index 43b2822d6..533335782 100644
--- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json
+++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json
@@ -148,5 +148,9 @@
"name": "software.amazon.lambda.powertools.metrics.provider.MetricsProvider",
"allDeclaredClasses": true,
"queryAllPublicMethods": true
+ },
+ {
+ "name": "software.amazon.lambda.powertools.metrics.internal.MetricsUserAgentInterceptor",
+ "methods": [{ "name": "", "parameterTypes": [] }]
}
]
diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json
index d47298855..0667ee26a 100644
--- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json
+++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json
@@ -6,6 +6,9 @@
},
{
"pattern": "\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E"
+ },
+ {
+ "pattern": "\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E"
}
]
},
diff --git a/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..38e53da3e
--- /dev/null
+++ b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.metrics.internal.MetricsUserAgentInterceptor
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptorTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptorTest.java
new file mode 100644
index 000000000..673f9f7d4
--- /dev/null
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.metrics.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class MetricsUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/METRICS/");
+ }
+}
diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml
index bbb6a1111..b2c4f3426 100644
--- a/powertools-parameters/powertools-parameters-appconfig/pom.xml
+++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml
@@ -35,6 +35,10 @@
+
+ software.amazon.awssdk
+ sdk-core
+
org.aspectj
aspectjrt
@@ -82,6 +86,11 @@
aspectjweaver
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptor.java
new file mode 100644
index 000000000..01fc8d096
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.parameters.appconfig.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-parameters-appconfig module is on the classpath.
+ */
+public final class ParametersAppconfigUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("parameters-appconfig");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json
index 7e7b40197..b9ae934d6 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json
@@ -361,5 +361,9 @@
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.parameters.appconfig.internal.ParametersAppconfigUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..c37ecc083
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.parameters.appconfig.internal.ParametersAppconfigUserAgentInterceptor
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptorTest.java
new file mode 100644
index 000000000..124b71ef3
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.parameters.appconfig.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ParametersAppconfigUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/PARAMETERS-APPCONFIG/");
+ }
+}
\ No newline at end of file
diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
index fa969e585..e03227eb8 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml
+++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
@@ -36,6 +36,10 @@
+
+ software.amazon.awssdk
+ sdk-core
+
org.aspectj
aspectjrt
@@ -83,6 +87,11 @@
aspectjweaver
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptor.java
new file mode 100644
index 000000000..0b8b01dcb
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.parameters.dynamodb.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-parameters-dynamodb module is on the classpath.
+ */
+public final class ParametersDynamodbUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("parameters-dynamodb");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json
index 77e953aac..e49454b83 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json
@@ -322,5 +322,9 @@
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.parameters.dynamodb.internal.ParametersDynamodbUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..f7de6e9be
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.parameters.dynamodb.internal.ParametersDynamodbUserAgentInterceptor
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptorTest.java
new file mode 100644
index 000000000..f9c8ebea5
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.parameters.dynamodb.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ParametersDynamodbUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/PARAMETERS-DYNAMODB/");
+ }
+}
\ No newline at end of file
diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml
index 55c254f88..6a576f529 100644
--- a/powertools-parameters/powertools-parameters-secrets/pom.xml
+++ b/powertools-parameters/powertools-parameters-secrets/pom.xml
@@ -36,6 +36,10 @@
+
+ software.amazon.awssdk
+ sdk-core
+
org.aspectj
aspectjrt
@@ -83,6 +87,11 @@
aspectjweaver
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptor.java
new file mode 100644
index 000000000..e3eda5889
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.parameters.secrets.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-parameters-secrets module is on the classpath.
+ */
+public final class ParametersSecretsUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("parameters-secrets");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json
index 7dfaf1b03..097a30784 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json
@@ -319,5 +319,9 @@
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.parameters.secrets.internal.ParametersSecretsUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-secrets/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..ca08369c5
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.parameters.secrets.internal.ParametersSecretsUserAgentInterceptor
diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptorTest.java
new file mode 100644
index 000000000..6d59ff717
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.parameters.secrets.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ParametersSecretsUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/PARAMETERS-SECRETS/");
+ }
+}
\ No newline at end of file
diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml
index d1dc88d84..7758fd906 100644
--- a/powertools-parameters/powertools-parameters-ssm/pom.xml
+++ b/powertools-parameters/powertools-parameters-ssm/pom.xml
@@ -36,6 +36,10 @@
+
+ software.amazon.awssdk
+ sdk-core
+
org.aspectj
aspectjrt
@@ -83,6 +87,11 @@
aspectjweaver
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptor.java
new file mode 100644
index 000000000..ad1ff65dc
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.parameters.ssm.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-parameters-ssm module is on the classpath.
+ */
+public final class ParametersSsmUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("parameters-ssm");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json
index 5bc2deb4a..a655e62ce 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json
@@ -337,5 +337,9 @@
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.parameters.ssm.internal.ParametersSsmUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-ssm/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..4cce863f6
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.parameters.ssm.internal.ParametersSsmUserAgentInterceptor
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptorTest.java
new file mode 100644
index 000000000..8f6db7e21
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.parameters.ssm.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ParametersSsmUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/PARAMETERS-SSM/");
+ }
+}
\ No newline at end of file
diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml
index 6081abd66..045e76cbf 100644
--- a/powertools-tracing/pom.xml
+++ b/powertools-tracing/pom.xml
@@ -46,6 +46,10 @@
software.amazon.awssdk
aws-core
+
+ software.amazon.awssdk
+ sdk-core
+
com.amazonaws
aws-lambda-java-core
@@ -118,6 +122,11 @@
assertj-core
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptor.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptor.java
new file mode 100644
index 000000000..489243517
--- /dev/null
+++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.tracing.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-tracing module is on the classpath.
+ */
+public final class TracingUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("tracing");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json
index 94a514dee..a71154276 100644
--- a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json
+++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json
@@ -361,5 +361,9 @@
{
"name":"sun.security.provider.SHA",
"methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"software.amazon.lambda.powertools.tracing.internal.TracingUserAgentInterceptor",
+ "methods":[{"name":"","parameterTypes":[] }]
}
]
diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json
index 2ac72d18f..64408b8b6 100644
--- a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json
+++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json
@@ -26,6 +26,8 @@
"pattern":"\\Qcommons-logging.properties\\E"
}, {
"pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E"
+ }, {
+ "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E"
}]},
"bundles":[]
}
diff --git a/powertools-tracing/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-tracing/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..5f15a8000
--- /dev/null
+++ b/powertools-tracing/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.tracing.internal.TracingUserAgentInterceptor
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptorTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptorTest.java
new file mode 100644
index 000000000..b24f6c6f7
--- /dev/null
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.tracing.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class TracingUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/TRACING/");
+ }
+}
\ No newline at end of file
diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml
index 1c048e66a..6ecee16a1 100644
--- a/powertools-validation/pom.xml
+++ b/powertools-validation/pom.xml
@@ -75,6 +75,11 @@
org.crac
crac
+
+ software.amazon.awssdk
+ sdk-core
+ provided
+
@@ -122,6 +127,11 @@
junit-jupiter-params
test
+
+ software.amazon.awssdk
+ s3
+ test
+
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptor.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptor.java
new file mode 100644
index 000000000..ee92ff367
--- /dev/null
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptor.java
@@ -0,0 +1,37 @@
+/*
+ * 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.validation.internal;
+
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+
+/**
+ * Global interceptor that configures the User-Agent for all AWS SDK clients
+ * when the powertools-validation module is on the classpath.
+ */
+public final class ValidationUserAgentInterceptor implements ExecutionInterceptor {
+ static {
+ UserAgentConfigurator.configureUserAgent("validation");
+ }
+
+ @Override
+ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
+ // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is
+ // loaded by AWS SDK Global Interceptors.
+ return context.request();
+ }
+}
diff --git a/powertools-validation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-validation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
new file mode 100644
index 000000000..bcaa3fabf
--- /dev/null
+++ b/powertools-validation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors
@@ -0,0 +1 @@
+software.amazon.lambda.powertools.validation.internal.ValidationUserAgentInterceptor
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptorTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptorTest.java
new file mode 100644
index 000000000..9bacf33f9
--- /dev/null
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptorTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.validation.internal;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ValidationUserAgentInterceptorTest {
+
+ @Test
+ void shouldConfigureUserAgentWhenCreatingAwsSdkClient() {
+ // WHEN creating an AWS SDK client, the interceptor should be loaded
+ // We use S3 client but it can be any arbitrary AWS SDK client
+ S3Client.builder().region(Region.US_EAST_1).build();
+
+ // THEN the user agent system property should be set
+ String userAgent = System.getProperty("sdk.ua.appId");
+ assertThat(userAgent).contains("PT/VALIDATION/");
+ }
+}