Skip to content

Commit bea4c04

Browse files
authored
User agent suffixing for PPAF and PPCB enablement. (Azure#45197)
* Added user agent suffixing if PPAF / PPCB are opted into at client-level. * Added user agent suffixing if PPAF / PPCB are opted into at client-level. * Added user agent suffixing if PPAF / PPCB are opted into at client-level. * Added user agent suffixing if PPAF / PPCB are opted into at client-level. * Added user agent suffixing if PPAF / PPCB are opted into at client-level. * Addressing review comments. * Addressing review comments.
1 parent 9c496b3 commit bea4c04

File tree

5 files changed

+103
-4
lines changed

5 files changed

+103
-4
lines changed

sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/UserAgentContainerTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,33 @@
66
import com.azure.cosmos.CosmosAsyncClient;
77
import com.azure.cosmos.CosmosClientBuilder;
88
import com.azure.cosmos.implementation.directconnectivity.ReflectionUtils;
9+
import org.testng.annotations.DataProvider;
910
import org.testng.annotations.Test;
1011

12+
import java.util.ArrayList;
13+
import java.util.Arrays;
14+
import java.util.HashSet;
15+
import java.util.List;
16+
import java.util.Set;
17+
1118
import static org.assertj.core.api.Assertions.assertThat;
1219

1320
public class UserAgentContainerTest {
1421
private final static String SPACE = " ";
1522
private final static int TIMEOUT = 40000;
1623

24+
@DataProvider(name = "userAgentSuffixFeatureEnablementFlags")
25+
public Object[][] userAgentSuffixFeatureEnablementFlags() {
26+
return new Object[][]{
27+
{Arrays.asList(UserAgentFeatureFlags.PerPartitionAutomaticFailover, UserAgentFeatureFlags.PerPartitionCircuitBreaker), "|F3"},
28+
{Arrays.asList(UserAgentFeatureFlags.PerPartitionCircuitBreaker, UserAgentFeatureFlags.PerPartitionAutomaticFailover), "|F3"},
29+
{Arrays.asList(UserAgentFeatureFlags.PerPartitionAutomaticFailover), "|F1"},
30+
{Arrays.asList(UserAgentFeatureFlags.PerPartitionCircuitBreaker), "|F2"},
31+
{new ArrayList<>(), ""},
32+
{null, ""}
33+
};
34+
}
35+
1736
@Test(groups = {"unit"})
1837
public void userAgentContainerSetSuffix() {
1938
String expectedStringFixedPart = getUserAgentFixedPart();
@@ -53,6 +72,25 @@ public void userAgentContainerSetSuffix() {
5372
}
5473
}
5574

75+
@Test(groups = {"unit"}, dataProvider = "userAgentSuffixFeatureEnablementFlags")
76+
public void userAgentContainerSetSuffixWithFeatureEnablementFlags(
77+
List<UserAgentFeatureFlags> userAgentFeatureFlags,
78+
String expectedUserAgentFeatureFlagSuffix) {
79+
String expectedStringFixedPart = getUserAgentFixedPart();
80+
Set<UserAgentFeatureFlags> uniqueUserAgentFeatureFlags = userAgentFeatureFlags != null ? new HashSet<>(userAgentFeatureFlags) : null;
81+
82+
//With suffix less than 64 character
83+
String userProvidedSuffix = "test-application-id";
84+
UserAgentContainer userAgentContainer = new UserAgentContainer();
85+
userAgentContainer.setSuffix(userProvidedSuffix);
86+
userAgentContainer.setFeatureEnabledFlagsAsSuffix(uniqueUserAgentFeatureFlags);
87+
88+
String expectedString = expectedStringFixedPart + SPACE + userProvidedSuffix +
89+
((!Strings.isNullOrEmpty(expectedUserAgentFeatureFlagSuffix)) ?
90+
expectedUserAgentFeatureFlagSuffix : Strings.Emtpy);
91+
assertThat(userAgentContainer.getUserAgent()).isEqualTo(expectedString);
92+
}
93+
5694
@Test(groups = {"emulator"}, timeOut = TIMEOUT)
5795
public void UserAgentIntegration() {
5896
String userProvidedSuffix = "test-application-id";

sdk/cosmos/azure-cosmos/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#### Other Changes
1717
* Added the `vectorIndexShardKeys` to the vectorIndexSpec for QuantizedFlat and DiskANN vector search. - [PR 44007](https://github.com/Azure/azure-sdk-for-java/pull/44007)
18+
* Added user agent suffixing if Per-Partition Automatic Failover or Per-Partition Circuit Breaker are enabled at client scope. - [PR 45197](https://github.com/Azure/azure-sdk-for-java/pull/45197)
1819

1920
### 4.68.0 (2025-03-20)
2021

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,15 @@
111111
import java.util.Arrays;
112112
import java.util.Collection;
113113
import java.util.Collections;
114+
import java.util.EnumSet;
114115
import java.util.HashMap;
115116
import java.util.HashSet;
116117
import java.util.Iterator;
117118
import java.util.List;
118119
import java.util.Locale;
119120
import java.util.Map;
120121
import java.util.NoSuchElementException;
122+
import java.util.Set;
121123
import java.util.UUID;
122124
import java.util.concurrent.ConcurrentHashMap;
123125
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -564,7 +566,8 @@ private RxDocumentClientImpl(URI serviceEndpoint,
564566
this.userAgentContainer = new UserAgentContainer();
565567

566568
String userAgentSuffix = this.connectionPolicy.getUserAgentSuffix();
567-
if (userAgentSuffix != null && userAgentSuffix.length() > 0) {
569+
570+
if (userAgentSuffix != null && !userAgentSuffix.isEmpty()) {
568571
userAgentContainer.setSuffix(userAgentSuffix);
569572
}
570573

@@ -786,6 +789,8 @@ public void init(CosmosClientMetadataCachesSnapshot metadataCachesSnapshot, Func
786789
&& readConsistencyStrategy != ReadConsistencyStrategy.SESSION
787790
&& !sessionCapturingOverrideEnabled);
788791
this.sessionContainer.setDisableSessionCapturing(updatedDisableSessionCapturing);
792+
793+
this.addUserAgentSuffix(this.userAgentContainer, EnumSet.allOf(UserAgentFeatureFlags.class));
789794
} catch (Exception e) {
790795
logger.error("unexpected failure in initializing client.", e);
791796
close();
@@ -1360,6 +1365,19 @@ private static <T> Flux<FeedResponse<T>> getFeedResponseFluxWithTimeout(
13601365
});
13611366
}
13621367

1368+
private void addUserAgentSuffix(UserAgentContainer userAgentContainer, Set<UserAgentFeatureFlags> userAgentFeatureFlags) {
1369+
1370+
if (!this.globalPartitionEndpointManagerForPerPartitionAutomaticFailover.isPerPartitionAutomaticFailoverEnabled()) {
1371+
userAgentFeatureFlags.remove(UserAgentFeatureFlags.PerPartitionAutomaticFailover);
1372+
}
1373+
1374+
if (!this.globalPartitionEndpointManagerForPerPartitionCircuitBreaker.getCircuitBreakerConfig().isPartitionLevelCircuitBreakerEnabled()) {
1375+
userAgentFeatureFlags.remove(UserAgentFeatureFlags.PerPartitionCircuitBreaker);
1376+
}
1377+
1378+
userAgentContainer.setFeatureEnabledFlagsAsSuffix(userAgentFeatureFlags);
1379+
}
1380+
13631381
@Override
13641382
public Flux<FeedResponse<Database>> queryDatabases(String query, QueryFeedOperationState state) {
13651383
return queryDatabases(new SqlQuerySpec(query), state);

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/UserAgentContainer.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33

44
package com.azure.cosmos.implementation;
55

6-
import java.net.IDN;
7-
import java.net.URLEncoder;
8-
import java.nio.charset.StandardCharsets;
96
import java.text.Normalizer;
7+
import java.util.Set;
108
import java.util.regex.Pattern;
119

1210
/**
@@ -37,6 +35,20 @@ public String getSuffix() {
3735
return this.suffix;
3836
}
3937

38+
public void setFeatureEnabledFlagsAsSuffix(Set<UserAgentFeatureFlags> userAgentFeatureFlags) {
39+
if (userAgentFeatureFlags == null || userAgentFeatureFlags.isEmpty()) {
40+
return;
41+
}
42+
43+
int value = 0;
44+
45+
for (UserAgentFeatureFlags userAgentFeatureFlag : userAgentFeatureFlags) {
46+
value += userAgentFeatureFlag.getValue();
47+
}
48+
49+
this.userAgent = this.userAgent + "|F" + value;
50+
}
51+
4052
public void setSuffix(String suffix) {
4153
if (suffix.length() > maxSuffixLength) {
4254
suffix = suffix.substring(0, maxSuffixLength);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.cosmos.implementation;
5+
6+
/**
7+
* An enum representing various flags whose opt-in context will appear in the user agent suffix.
8+
* <p>
9+
* IMPORTANT: When adding a new flag, please ensure the following:
10+
* <ul>
11+
* <li>The value of the flag in the enum should follow the pattern FlagName(1 << (n - 1)) where n is the effective ordinal of the flag in the enum.</li>
12+
* <li>The value of the flag should be unique and not overlap with other flags.</li>
13+
* <li>Please keep the value consistent with that of other SDKs - (e.g. see - <a href="https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos/src/Diagnostics/UserAgentFeatureFlags.cs">UserAgentFeatureFlags.cs</a>) for more details.</li>
14+
* </ul>
15+
* </p>
16+
*/
17+
public enum UserAgentFeatureFlags {
18+
PerPartitionAutomaticFailover(1),
19+
PerPartitionCircuitBreaker(1 << 1);
20+
21+
private final int value;
22+
23+
UserAgentFeatureFlags(int value) {
24+
this.value = value;
25+
}
26+
27+
public int getValue() {
28+
return this.value;
29+
}
30+
}

0 commit comments

Comments
 (0)