Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,25 +82,52 @@ static String getVersionFromProperties(String propertyFileName, String versionKe

/**
* 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.
* Preserves any user-provided value and replaces any existing Powertools user agent.
* Enforces a 50 character limit to comply with AWS SDK recommendations.
* 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);
String newValue;

if (existingValue != null && !existingValue.isEmpty()) {
System.setProperty(SDK_USER_AGENT_APP_ID, existingValue + "/" + powertoolsUserAgent);
if (existingValue == null || existingValue.isEmpty()) {
newValue = powertoolsUserAgent;
} else {
System.setProperty(SDK_USER_AGENT_APP_ID, powertoolsUserAgent);
String userValue = extractUserValue(existingValue);
if (userValue.isEmpty()) {
newValue = powertoolsUserAgent;
} else {
newValue = userValue + "/" + powertoolsUserAgent;
}
}

if (newValue.length() <= 50) {
System.setProperty(SDK_USER_AGENT_APP_ID, newValue);
}
} 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);
}
}

/**
* Extracts the user-provided value from the existing user agent string by removing any Powertools user agent.
* A Powertools user agent follows the pattern "PT/{FEATURE}/{VERSION} PTENV/{ENV}".
*
* @param existingValue the existing user agent string
* @return the user-provided value without Powertools user agent, or empty string if none exists
*/
static String extractUserValue(String existingValue) {
if (existingValue == null || existingValue.isEmpty()) {
return "";
}
// Remove Powertools user agent pattern: PT/{FEATURE}/{VERSION} PTENV/{ENV}
String result = existingValue.replaceAll("/?PT/[^/]+/[^ ]+ PTENV/[^ ]+", "");
return result.trim();
}

/**
* Retrieves the user agent string for the Powertools for AWS Lambda.
* It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTENV/{PT_EXEC_ENV}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,72 @@ void testConfigureUserAgent() {
}

@Test
void testConfigureUserAgent_WithExistingValue() {
void testConfigureUserAgent_WithExistingUserValue() {
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_ReplacePowertoolsUserAgent() {
System.setProperty("sdk.ua.appId", "PT/BATCH/" + VERSION + " PTENV/NA");
UserAgentConfigurator.configureUserAgent("logging-log4j");

assertThat(System.getProperty("sdk.ua.appId"))
.isEqualTo("PT/LOGGING-LOG4J/" + VERSION + " PTENV/NA");
}

@Test
void testConfigureUserAgent_PreserveUserValueAndReplacePowertools() {
System.setProperty("sdk.ua.appId", "UserValue/PT/BATCH/" + VERSION + " PTENV/NA");
UserAgentConfigurator.configureUserAgent("tracing");

assertThat(System.getProperty("sdk.ua.appId"))
.isEqualTo("UserValue/PT/TRACING/" + VERSION + " PTENV/NA");
}

@Test
void testConfigureUserAgent_ExceedsLimit() {
System.setProperty("sdk.ua.appId", "VeryLongUserValueThatExceedsTheLimitWhenCombined");
UserAgentConfigurator.configureUserAgent("test-feature");

// Should not update if it would exceed 50 characters
assertThat(System.getProperty("sdk.ua.appId"))
.isEqualTo("VeryLongUserValueThatExceedsTheLimitWhenCombined");
}

@Test
void testExtractUserValue_NoUserValue() {
String result = UserAgentConfigurator.extractUserValue("PT/BATCH/" + VERSION + " PTENV/NA");
assertThat(result).isEmpty();
}

@Test
void testExtractUserValue_WithUserValue() {
String result = UserAgentConfigurator.extractUserValue("UserValue/PT/BATCH/" + VERSION + " PTENV/NA");
assertThat(result).isEqualTo("UserValue");
}

@Test
void testExtractUserValue_EmptyString() {
String result = UserAgentConfigurator.extractUserValue("");
assertThat(result).isEmpty();
}

@Test
void testExtractUserValue_NullString() {
String result = UserAgentConfigurator.extractUserValue(null);
assertThat(result).isEmpty();
}

@Test
void testExtractUserValue_OnlyUserValue() {
String result = UserAgentConfigurator.extractUserValue("MyCustomValue");
assertThat(result).isEqualTo("MyCustomValue");
}

@Test
void testConfigureUserAgent_WithEmptyExistingValue() {
System.setProperty("sdk.ua.appId", "");
Expand All @@ -148,4 +206,25 @@ void testConfigureUserAgent_WithEmptyExistingValue() {
.isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA");
}

@Test
@SetEnvironmentVariable(key = AWS_EXECUTION_ENV, value = "AWS_Lambda_java11")
void testConfigureUserAgent_MultipleUtilities() {
System.clearProperty("sdk.ua.appId");

// First utility
UserAgentConfigurator.configureUserAgent("batch");
assertThat(System.getProperty("sdk.ua.appId"))
.isEqualTo("PT/BATCH/" + VERSION + " PTENV/AWS_Lambda_java11");

// Second utility - should replace, not append
UserAgentConfigurator.configureUserAgent("logging-log4j");
assertThat(System.getProperty("sdk.ua.appId"))
.isEqualTo("PT/LOGGING-LOG4J/" + VERSION + " PTENV/AWS_Lambda_java11");

// Third utility - should replace again
UserAgentConfigurator.configureUserAgent("tracing");
assertThat(System.getProperty("sdk.ua.appId"))
.isEqualTo("PT/TRACING/" + VERSION + " PTENV/AWS_Lambda_java11");
}

}
Loading