added BackendMetricPropagationTest and addressed comments

This commit is contained in:
MV Shiva Prasad 2025-07-21 13:58:10 +05:30
parent 6741e945e3
commit bc1c18275d
18 changed files with 218 additions and 73 deletions

View File

@ -57,7 +57,7 @@ dependencies {
task javadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += files(android.getBootClasspath())
// classpath += files(android.getBootClasspath())
classpath += files({
android.libraryVariants.collect { variant ->
variant.javaCompileProvider.get().classpath

View File

@ -46,6 +46,7 @@ import io.grpc.xds.Endpoints.DropOverload;
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
import io.grpc.xds.ThreadSafeRandom.ThreadSafeRandomImpl;
import io.grpc.xds.XdsNameResolverProvider.CallCounterProvider;
import io.grpc.xds.client.BackendMetricPropagation;
import io.grpc.xds.client.Bootstrapper.ServerInfo;
import io.grpc.xds.client.LoadStatsManager2.ClusterDropStats;
import io.grpc.xds.client.LoadStatsManager2.ClusterLocalityStats;

View File

@ -31,6 +31,7 @@ import io.grpc.NameResolver.ConfigOrError;
import io.grpc.Status;
import io.grpc.xds.Endpoints.DropOverload;
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
import io.grpc.xds.client.BackendMetricPropagation;
import io.grpc.xds.client.Bootstrapper.ServerInfo;
import java.util.ArrayList;
import java.util.Collections;

View File

@ -55,6 +55,7 @@ import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
import io.grpc.xds.PriorityLoadBalancerProvider.PriorityLbConfig;
import io.grpc.xds.PriorityLoadBalancerProvider.PriorityLbConfig.PriorityChildConfig;
import io.grpc.xds.XdsEndpointResource.EdsUpdate;
import io.grpc.xds.client.BackendMetricPropagation;
import io.grpc.xds.client.Bootstrapper.ServerInfo;
import io.grpc.xds.client.Locality;
import io.grpc.xds.client.XdsClient;
@ -191,7 +192,8 @@ final class ClusterResolverLoadBalancer extends LoadBalancer {
if (instance.type == DiscoveryMechanism.Type.EDS) {
state = new EdsClusterState(instance.cluster, instance.edsServiceName,
instance.lrsServerInfo, instance.maxConcurrentRequests, instance.tlsContext,
instance.filterMetadata, instance.outlierDetection, instance.backendMetricPropagation);
instance.filterMetadata, instance.outlierDetection,
instance.backendMetricPropagation);
} else { // logical DNS
state = new LogicalDnsClusterState(instance.cluster, instance.dnsHostName,
instance.lrsServerInfo, instance.maxConcurrentRequests, instance.tlsContext,
@ -803,7 +805,8 @@ final class ClusterResolverLoadBalancer extends LoadBalancer {
private static Map<String, PriorityChildConfig> generateEdsBasedPriorityChildConfigs(
String cluster, @Nullable String edsServiceName, @Nullable ServerInfo lrsServerInfo,
@Nullable Long maxConcurrentRequests, @Nullable UpstreamTlsContext tlsContext,
Map<String, Struct> filterMetadata, @Nullable BackendMetricPropagation backendMetricPropagation,
Map<String, Struct> filterMetadata,
@Nullable BackendMetricPropagation backendMetricPropagation,
@Nullable OutlierDetection outlierDetection, Object endpointLbConfig,
LoadBalancerRegistry lbRegistry, Map<String,
Map<Locality, Integer>> prioritizedLocalityWeights, List<DropOverload> dropOverloads) {
@ -811,7 +814,8 @@ final class ClusterResolverLoadBalancer extends LoadBalancer {
for (String priority : prioritizedLocalityWeights.keySet()) {
ClusterImplConfig clusterImplConfig =
new ClusterImplConfig(cluster, edsServiceName, lrsServerInfo, maxConcurrentRequests,
dropOverloads, endpointLbConfig, tlsContext, filterMetadata, backendMetricPropagation);
dropOverloads, endpointLbConfig, tlsContext,
filterMetadata, backendMetricPropagation);
LoadBalancerProvider clusterImplLbProvider =
lbRegistry.getProvider(XdsLbPolicies.CLUSTER_IMPL_POLICY_NAME);
Object priorityChildPolicy = GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(

View File

@ -29,6 +29,7 @@ import io.grpc.NameResolver.ConfigOrError;
import io.grpc.Status;
import io.grpc.xds.EnvoyServerProtoData.OutlierDetection;
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
import io.grpc.xds.client.BackendMetricPropagation;
import io.grpc.xds.client.Bootstrapper.ServerInfo;
import java.util.List;
import java.util.Map;
@ -138,7 +139,7 @@ public final class ClusterResolverLoadBalancerProvider extends LoadBalancerProvi
final OutlierDetection outlierDetection;
final Map<String, Struct> filterMetadata;
@Nullable
final BackendMetricPropagation backendMetricPropagation;
final BackendMetricPropagation backendMetricPropagation;
enum Type {
EDS,
@ -165,9 +166,11 @@ public final class ClusterResolverLoadBalancerProvider extends LoadBalancerProvi
static DiscoveryMechanism forEds(String cluster, @Nullable String edsServiceName,
@Nullable ServerInfo lrsServerInfo, @Nullable Long maxConcurrentRequests,
@Nullable UpstreamTlsContext tlsContext, Map<String, Struct> filterMetadata,
OutlierDetection outlierDetection, @Nullable BackendMetricPropagation backendMetricPropagation) {
return new DiscoveryMechanism(cluster, Type.EDS, edsServiceName, null, lrsServerInfo,
maxConcurrentRequests, tlsContext, filterMetadata, outlierDetection, backendMetricPropagation);
OutlierDetection outlierDetection,
@Nullable BackendMetricPropagation backendMetricPropagation) {
return new DiscoveryMechanism(cluster, Type.EDS, edsServiceName,
null, lrsServerInfo, maxConcurrentRequests, tlsContext,
filterMetadata, outlierDetection, backendMetricPropagation);
}
static DiscoveryMechanism forLogicalDns(String cluster, String dnsHostName,
@ -182,7 +185,8 @@ public final class ClusterResolverLoadBalancerProvider extends LoadBalancerProvi
@Override
public int hashCode() {
return Objects.hash(cluster, type, lrsServerInfo, maxConcurrentRequests, tlsContext,
edsServiceName, dnsHostName, filterMetadata, outlierDetection, backendMetricPropagation);
edsServiceName, dnsHostName, filterMetadata,
outlierDetection, backendMetricPropagation);
}
@Override

View File

@ -47,10 +47,10 @@ import io.grpc.internal.ServiceConfigUtil.LbConfig;
import io.grpc.xds.EnvoyServerProtoData.OutlierDetection;
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
import io.grpc.xds.XdsClusterResource.CdsUpdate;
import io.grpc.xds.client.BackendMetricPropagation;
import io.grpc.xds.client.XdsClient.ResourceUpdate;
import io.grpc.xds.client.XdsResourceType;
import io.grpc.xds.internal.security.CommonTlsContextUtil;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@ -336,7 +336,7 @@ class XdsClusterResource extends XdsResourceType<CdsUpdate> {
return StructOrError.fromStruct(CdsUpdate.forEds(
clusterName, edsServiceName, lrsServerInfo, maxConcurrentRequests, upstreamTlsContext,
outlierDetection, isHttp11ProxyAvailable, backendMetricPropagation));
outlierDetection, isHttp11ProxyAvailable, backendMetricPropagation));
} else if (type.equals(Cluster.DiscoveryType.LOGICAL_DNS)) {
if (!cluster.hasLoadAssignment()) {
return StructOrError.fromError(
@ -372,7 +372,7 @@ class XdsClusterResource extends XdsResourceType<CdsUpdate> {
Locale.US, "%s:%d", socketAddress.getAddress(), socketAddress.getPortValue());
return StructOrError.fromStruct(CdsUpdate.forLogicalDns(
clusterName, dnsHostName, lrsServerInfo, maxConcurrentRequests,
upstreamTlsContext, isHttp11ProxyAvailable, backendMetricPropagation));
upstreamTlsContext, isHttp11ProxyAvailable, backendMetricPropagation));
}
return StructOrError.fromError(
"Cluster " + clusterName + ": unsupported built-in discovery type: " + type);

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.grpc.xds;
package io.grpc.xds.client;
import static com.google.common.base.Preconditions.checkNotNull;
@ -55,7 +55,8 @@ public final class BackendMetricPropagation {
* @param metricSpecs list of metric specification strings from CDS resource
* @return BackendMetricPropagation instance
*/
public static BackendMetricPropagation fromMetricSpecs(@Nullable java.util.List<String> metricSpecs) {
public static BackendMetricPropagation fromMetricSpecs(
@Nullable java.util.List<String> metricSpecs) {
if (metricSpecs == null || metricSpecs.isEmpty()) {
return new BackendMetricPropagation(false, false, false, false, ImmutableSet.of());
}
@ -89,7 +90,6 @@ public final class BackendMetricPropagation {
namedMetricKeysBuilder.add(metricKey);
}
}
break;
}
}

View File

@ -25,7 +25,6 @@ import com.google.common.base.Supplier;
import com.google.common.collect.Sets;
import io.grpc.Internal;
import io.grpc.Status;
import io.grpc.xds.BackendMetricPropagation;
import io.grpc.xds.client.Stats.BackendLoadMetricStats;
import io.grpc.xds.client.Stats.ClusterStats;
import io.grpc.xds.client.Stats.DroppedRequests;
@ -129,8 +128,8 @@ public final class LoadStatsManager2 {
if (!localityStats.containsKey(locality)) {
localityStats.put(
locality,
ReferenceCounted.wrap(new ClusterLocalityStats(
cluster, edsServiceName, locality, stopwatchSupplier.get(), backendMetricPropagation)));
ReferenceCounted.wrap(new ClusterLocalityStats(cluster, edsServiceName,
locality, stopwatchSupplier.get(), backendMetricPropagation)));
}
ReferenceCounted<ClusterLocalityStats> ref = localityStats.get(locality);
ref.retain();
@ -421,7 +420,8 @@ public final class LoadStatsManager2 {
if (!loadMetricStatsMap.containsKey(metricName)) {
loadMetricStatsMap.put(metricName, new BackendLoadMetricStats(1, cpuUtilization));
} else {
loadMetricStatsMap.get(metricName).addMetricValueAndIncrementRequestsFinished(cpuUtilization);
loadMetricStatsMap.get(metricName)
.addMetricValueAndIncrementRequestsFinished(cpuUtilization);
}
}
}
@ -437,7 +437,8 @@ public final class LoadStatsManager2 {
if (!loadMetricStatsMap.containsKey(metricName)) {
loadMetricStatsMap.put(metricName, new BackendLoadMetricStats(1, memUtilization));
} else {
loadMetricStatsMap.get(metricName).addMetricValueAndIncrementRequestsFinished(memUtilization);
loadMetricStatsMap.get(metricName)
.addMetricValueAndIncrementRequestsFinished(memUtilization);
}
}
}
@ -451,9 +452,11 @@ public final class LoadStatsManager2 {
if (shouldPropagate) {
String metricName = "application_utilization";
if (!loadMetricStatsMap.containsKey(metricName)) {
loadMetricStatsMap.put(metricName, new BackendLoadMetricStats(1, applicationUtilization));
loadMetricStatsMap.put(
metricName, new BackendLoadMetricStats(1, applicationUtilization));
} else {
loadMetricStatsMap.get(metricName).addMetricValueAndIncrementRequestsFinished(applicationUtilization);
loadMetricStatsMap.get(metricName)
.addMetricValueAndIncrementRequestsFinished(applicationUtilization);
}
}
}

View File

@ -27,7 +27,6 @@ import com.google.common.util.concurrent.MoreExecutors;
import com.google.protobuf.Any;
import io.grpc.ExperimentalApi;
import io.grpc.Status;
import io.grpc.xds.BackendMetricPropagation;
import io.grpc.xds.client.Bootstrapper.ServerInfo;
import java.net.URI;
import java.net.URISyntaxException;
@ -385,7 +384,7 @@ public abstract class XdsClient {
public LoadStatsManager2.ClusterLocalityStats addClusterLocalityStats(
Bootstrapper.ServerInfo serverInfo, String clusterName, @Nullable String edsServiceName,
Locality locality) {
throw new UnsupportedOperationException();
return addClusterLocalityStats(serverInfo, clusterName, edsServiceName, locality, null);
}
/**

View File

@ -37,7 +37,6 @@ import io.grpc.SynchronizationContext;
import io.grpc.SynchronizationContext.ScheduledHandle;
import io.grpc.internal.BackoffPolicy;
import io.grpc.internal.TimeProvider;
import io.grpc.xds.BackendMetricPropagation;
import io.grpc.xds.client.Bootstrapper.AuthorityInfo;
import io.grpc.xds.client.Bootstrapper.ServerInfo;
import io.grpc.xds.client.XdsClient.ResourceStore;
@ -409,16 +408,7 @@ public final class XdsClientImpl extends XdsClient implements ResourceStore {
public LoadStatsManager2.ClusterLocalityStats addClusterLocalityStats(
final ServerInfo serverInfo, String clusterName, @Nullable String edsServiceName,
Locality locality) {
LoadStatsManager2 loadStatsManager = loadStatsManagerMap.get(serverInfo);
LoadStatsManager2.ClusterLocalityStats loadCounter =
loadStatsManager.getClusterLocalityStats(clusterName, edsServiceName, locality);
syncContext.execute(new Runnable() {
@Override
public void run() {
serverLrsClientMap.get(serverInfo).startLoadReporting();
}
});
return loadCounter;
return addClusterLocalityStats(serverInfo, clusterName, edsServiceName, locality, null);
}
@Override

View File

@ -252,7 +252,7 @@ public class CdsLoadBalancer2Test {
CLUSTER, EDS_SERVICE_NAME, lrsServerInfo, 100L, upstreamTlsContext,
Collections.emptyMap(), io.grpc.xds.EnvoyServerProtoData.OutlierDetection.create(
null, null, null, null, SuccessRateEjection.create(null, null, null, null),
FailurePercentageEjection.create(null, null, null, null)))));
FailurePercentageEjection.create(null, null, null, null)), null)));
assertThat(
GracefulSwitchLoadBalancerAccessor.getChildProvider(childLbConfig.lbConfig).getPolicyName())
.isEqualTo("wrr_locality_experimental");
@ -300,7 +300,7 @@ public class CdsLoadBalancer2Test {
Arrays.asList(
DiscoveryMechanism.forLogicalDns(
CLUSTER, "dns.example.com:1111", lrsServerInfo, 100L, upstreamTlsContext,
Collections.emptyMap())));
Collections.emptyMap(), null)));
assertThat(
GracefulSwitchLoadBalancerAccessor.getChildProvider(childLbConfig.lbConfig).getPolicyName())
.isEqualTo("wrr_locality_experimental");
@ -335,7 +335,7 @@ public class CdsLoadBalancer2Test {
assertThat(childLbConfig.discoveryMechanisms).isEqualTo(
Arrays.asList(
DiscoveryMechanism.forEds(
CLUSTER, EDS_SERVICE_NAME, null, 100L, null, Collections.emptyMap(), null)));
CLUSTER, EDS_SERVICE_NAME, null, 100L, null, Collections.emptyMap(), null, null)));
cluster = EDS_CLUSTER.toBuilder()
.setCircuitBreakers(CircuitBreakers.newBuilder()
@ -351,7 +351,7 @@ public class CdsLoadBalancer2Test {
assertThat(childLbConfig.discoveryMechanisms).isEqualTo(
Arrays.asList(
DiscoveryMechanism.forEds(
CLUSTER, EDS_SERVICE_NAME, null, 200L, null, Collections.emptyMap(), null)));
CLUSTER, EDS_SERVICE_NAME, null, 200L, null, Collections.emptyMap(), null, null)));
}
@Test
@ -366,7 +366,7 @@ public class CdsLoadBalancer2Test {
assertThat(childLbConfig.discoveryMechanisms).isEqualTo(
Arrays.asList(
DiscoveryMechanism.forEds(
CLUSTER, EDS_SERVICE_NAME, null, null, null, Collections.emptyMap(), null)));
CLUSTER, EDS_SERVICE_NAME, null, null, null, Collections.emptyMap(), null, null)));
controlPlaneService.setXdsConfig(ADS_TYPE_URL_CDS, ImmutableMap.of());
@ -398,7 +398,7 @@ public class CdsLoadBalancer2Test {
assertThat(childLbConfig.discoveryMechanisms).isEqualTo(
Arrays.asList(
DiscoveryMechanism.forEds(
clusterName, EDS_SERVICE_NAME, null, null, null, Collections.emptyMap(), null)));
clusterName, EDS_SERVICE_NAME, null, null, null, Collections.emptyMap(), null, null)));
assertThat(this.lastXdsConfig.getClusters()).containsKey(clusterName);
shutdownLoadBalancer();
@ -465,11 +465,11 @@ public class CdsLoadBalancer2Test {
assertThat(childLbConfig.discoveryMechanisms).isEqualTo(
Arrays.asList(
DiscoveryMechanism.forEds(
cluster3, EDS_SERVICE_NAME, null, 100L, null, Collections.emptyMap(), null),
cluster3, EDS_SERVICE_NAME, null, 100L, null, Collections.emptyMap(), null, null),
DiscoveryMechanism.forEds(
cluster4, EDS_SERVICE_NAME, null, null, null, Collections.emptyMap(), null),
cluster4, EDS_SERVICE_NAME, null, null, null, Collections.emptyMap(), null, null),
DiscoveryMechanism.forLogicalDns(
cluster2, "dns.example.com:1111", null, null, null, Collections.emptyMap())));
cluster2, "dns.example.com:1111", null, null, null, Collections.emptyMap(), null)));
assertThat(
GracefulSwitchLoadBalancerAccessor.getChildProvider(childLbConfig.lbConfig).getPolicyName())
.isEqualTo("ring_hash_experimental"); // dominated by top-level cluster's config

View File

@ -68,6 +68,7 @@ import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
import io.grpc.xds.WeightedTargetLoadBalancerProvider.WeightedPolicySelection;
import io.grpc.xds.WeightedTargetLoadBalancerProvider.WeightedTargetConfig;
import io.grpc.xds.XdsNameResolverProvider.CallCounterProvider;
import io.grpc.xds.client.BackendMetricPropagation;
import io.grpc.xds.client.Bootstrapper.ServerInfo;
import io.grpc.xds.client.LoadReportClient;
import io.grpc.xds.client.LoadStatsManager2;
@ -260,7 +261,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
FakeLoadBalancer childBalancer = Iterables.getOnlyElement(downstreamBalancers);
@ -281,7 +282,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
FakeLoadBalancer leafBalancer = Iterables.getOnlyElement(downstreamBalancers);
@ -312,7 +313,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
FakeLoadBalancer leafBalancer = Iterables.getOnlyElement(downstreamBalancers);
@ -336,7 +337,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
FakeLoadBalancer leafBalancer = Iterables.getOnlyElement(downstreamBalancers);
@ -431,7 +432,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(pickFirstProvider,
pickFirstConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint1 = makeAddress("endpoint-addr1", locality1);
EquivalentAddressGroup endpoint2 = makeAddress("endpoint-addr2", locality2);
deliverAddressesAndConfig(Arrays.asList(endpoint1, endpoint2), config);
@ -521,7 +522,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.singletonList(DropOverload.create("throttle", 500_000)),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
when(mockRandom.nextInt(anyInt())).thenReturn(499_999, 999_999, 1_000_000);
@ -555,7 +556,7 @@ public class ClusterImplLoadBalancerTest {
Collections.singletonList(DropOverload.create("lb", 1_000_000)),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
loadBalancer.acceptResolvedAddresses(
ResolvedAddresses.newBuilder()
.setAddresses(Collections.singletonList(endpoint))
@ -604,7 +605,7 @@ public class ClusterImplLoadBalancerTest {
maxConcurrentRequests, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
assertThat(downstreamBalancers).hasSize(1); // one leaf balancer
@ -651,7 +652,7 @@ public class ClusterImplLoadBalancerTest {
maxConcurrentRequests, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
result = currentPicker.pickSubchannel(pickSubchannelArgs);
@ -699,7 +700,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
assertThat(downstreamBalancers).hasSize(1); // one leaf balancer
@ -750,7 +751,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
// One locality with two endpoints.
EquivalentAddressGroup endpoint1 = makeAddress("endpoint-addr1", locality);
EquivalentAddressGroup endpoint2 = makeAddress("endpoint-addr2", locality);
@ -790,7 +791,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint1 = makeAddress("endpoint-addr1", locality,
"authority-host-name");
deliverAddressesAndConfig(Arrays.asList(endpoint1), config);
@ -841,7 +842,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
EquivalentAddressGroup endpoint1 = makeAddress("endpoint-addr1", locality,
"authority-host-name");
deliverAddressesAndConfig(Arrays.asList(endpoint1), config);
@ -889,7 +890,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
upstreamTlsContext, Collections.emptyMap());
upstreamTlsContext, Collections.emptyMap(), null);
// One locality with two endpoints.
EquivalentAddressGroup endpoint1 = makeAddress("endpoint-addr1", locality);
EquivalentAddressGroup endpoint2 = makeAddress("endpoint-addr2", locality);
@ -914,7 +915,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
null, Collections.emptyMap());
null, Collections.emptyMap(), null);
deliverAddressesAndConfig(Arrays.asList(endpoint1, endpoint2), config);
assertThat(Iterables.getOnlyElement(downstreamBalancers)).isSameInstanceAs(leafBalancer);
subchannel = leafBalancer.helper.createSubchannel(args); // creates new connections
@ -931,7 +932,7 @@ public class ClusterImplLoadBalancerTest {
null, Collections.<DropOverload>emptyList(),
GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(
weightedTargetProvider, weightedTargetConfig),
upstreamTlsContext, Collections.emptyMap());
upstreamTlsContext, Collections.emptyMap(), null);
deliverAddressesAndConfig(Arrays.asList(endpoint1, endpoint2), config);
assertThat(Iterables.getOnlyElement(downstreamBalancers)).isSameInstanceAs(leafBalancer);
subchannel = leafBalancer.helper.createSubchannel(args); // creates new connections
@ -1241,8 +1242,9 @@ public class ClusterImplLoadBalancerTest {
@Override
public ClusterLocalityStats addClusterLocalityStats(
ServerInfo lrsServerInfo, String clusterName, @Nullable String edsServiceName,
Locality locality) {
return loadStatsManager.getClusterLocalityStats(clusterName, edsServiceName, locality);
Locality locality, BackendMetricPropagation backendMetricPropagation) {
return loadStatsManager.getClusterLocalityStats(
clusterName, edsServiceName, locality, backendMetricPropagation);
}
@Override

View File

@ -139,16 +139,16 @@ public class ClusterResolverLoadBalancerTest {
FailurePercentageEjection.create(100, 100, 100, 100));
private final DiscoveryMechanism edsDiscoveryMechanism1 =
DiscoveryMechanism.forEds(CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, tlsContext,
Collections.emptyMap(), null);
Collections.emptyMap(), null, null);
private final DiscoveryMechanism edsDiscoveryMechanism2 =
DiscoveryMechanism.forEds(CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_INFO, 200L, tlsContext,
Collections.emptyMap(), null);
Collections.emptyMap(), null, null);
private final DiscoveryMechanism edsDiscoveryMechanismWithOutlierDetection =
DiscoveryMechanism.forEds(CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, tlsContext,
Collections.emptyMap(), outlierDetection);
Collections.emptyMap(), outlierDetection, null);
private final DiscoveryMechanism logicalDnsDiscoveryMechanism =
DiscoveryMechanism.forLogicalDns(CLUSTER_DNS, DNS_HOST_NAME, LRS_SERVER_INFO, 300L, null,
Collections.emptyMap());
Collections.emptyMap(), null);
private final SynchronizationContext syncContext = new SynchronizationContext(
new Thread.UncaughtExceptionHandler() {

View File

@ -491,7 +491,7 @@ public class GcpAuthenticationFilterTest {
parsedMetadata.put("FILTER_INSTANCE_NAME", new AudienceWrapper("TEST_AUDIENCE"));
try {
CdsUpdate.Builder cdsUpdate = CdsUpdate.forEds(
CLUSTER_NAME, EDS_NAME, null, null, null, null, false)
CLUSTER_NAME, EDS_NAME, null, null, null, null, false, null)
.lbPolicyConfig(getWrrLbConfigAsMap());
return cdsUpdate.parsedMetadata(parsedMetadata.build()).build();
} catch (IOException ex) {
@ -504,7 +504,7 @@ public class GcpAuthenticationFilterTest {
parsedMetadata.put("FILTER_INSTANCE_NAME", new AudienceWrapper("NEW_TEST_AUDIENCE"));
try {
CdsUpdate.Builder cdsUpdate = CdsUpdate.forEds(
CLUSTER_NAME, EDS_NAME, null, null, null, null, false)
CLUSTER_NAME, EDS_NAME, null, null, null, null, false, null)
.lbPolicyConfig(getWrrLbConfigAsMap());
return cdsUpdate.parsedMetadata(parsedMetadata.build()).build();
} catch (IOException ex) {
@ -516,7 +516,7 @@ public class GcpAuthenticationFilterTest {
ImmutableMap.Builder<String, Object> parsedMetadata = ImmutableMap.builder();
parsedMetadata.put("FILTER_INSTANCE_NAME", "TEST_AUDIENCE");
CdsUpdate.Builder cdsUpdate = CdsUpdate.forEds(
CLUSTER_NAME, EDS_NAME, null, null, null, null, false)
CLUSTER_NAME, EDS_NAME, null, null, null, null, false, null)
.lbPolicyConfig(getWrrLbConfigAsMap());
return cdsUpdate.parsedMetadata(parsedMetadata.build()).build();
}

View File

@ -154,7 +154,6 @@ public class XdsClientFederationTest {
}
}
/**
* Assures that when an {@link XdsClient} is asked to add cluster locality stats it appropriately
* starts {@link LoadReportClient}s to do that.

View File

@ -1235,7 +1235,7 @@ public class XdsNameResolverTest {
FakeXdsClient xdsClient, String... clusterNames) {
for (String clusterName : clusterNames) {
CdsUpdate.Builder forEds = CdsUpdate
.forEds(clusterName, clusterName, null, null, null, null, false)
.forEds(clusterName, clusterName, null, null, null, null, false, null)
.roundRobinLbPolicy();
xdsClient.deliverCdsUpdate(clusterName, forEds.build());
EdsUpdate edsUpdate = new EdsUpdate(clusterName,

View File

@ -272,7 +272,7 @@ public class XdsTestUtils {
XdsEndpointResource.EdsUpdate edsUpdate = new XdsEndpointResource.EdsUpdate(
EDS_NAME, lbEndpointsMap, Collections.emptyList());
XdsClusterResource.CdsUpdate cdsUpdate = XdsClusterResource.CdsUpdate.forEds(
CLUSTER_NAME, EDS_NAME, serverInfo, null, null, null, false)
CLUSTER_NAME, EDS_NAME, serverInfo, null, null, null, false, null)
.lbPolicyConfig(getWrrLbConfigAsMap()).build();
XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig(
CLUSTER_NAME, cdsUpdate, new EndpointConfig(StatusOr.fromValue(edsUpdate)));

View File

@ -0,0 +1,142 @@
/*
* Copyright 2025 The gRPC Authors
*
* 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 io.grpc.xds.client;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Unit tests for {@link BackendMetricPropagation}.
*/
@RunWith(JUnit4.class)
public class BackendMetricPropagationTest {
@Test
public void fromMetricSpecs_nullInput() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(null);
assertThat(config.propagateCpuUtilization).isFalse();
assertThat(config.propagateMemUtilization).isFalse();
assertThat(config.propagateApplicationUtilization).isFalse();
assertThat(config.shouldPropagateNamedMetric("any")).isFalse();
}
@Test
public void fromMetricSpecs_emptyInput() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(ImmutableList.of());
assertThat(config.propagateCpuUtilization).isFalse();
assertThat(config.propagateMemUtilization).isFalse();
assertThat(config.propagateApplicationUtilization).isFalse();
assertThat(config.shouldPropagateNamedMetric("any")).isFalse();
}
@Test
public void fromMetricSpecs_partialStandardMetrics() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
ImmutableList.of("cpu_utilization", "mem_utilization"));
assertThat(config.propagateCpuUtilization).isTrue();
assertThat(config.propagateMemUtilization).isTrue();
assertThat(config.propagateApplicationUtilization).isFalse();
assertThat(config.shouldPropagateNamedMetric("any")).isFalse();
}
@Test
public void fromMetricSpecs_allStandardMetrics() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
ImmutableList.of("cpu_utilization", "mem_utilization", "application_utilization"));
assertThat(config.propagateCpuUtilization).isTrue();
assertThat(config.propagateMemUtilization).isTrue();
assertThat(config.propagateApplicationUtilization).isTrue();
assertThat(config.shouldPropagateNamedMetric("any")).isFalse();
}
@Test
public void fromMetricSpecs_wildcardNamedMetrics() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
ImmutableList.of("named_metrics.*"));
assertThat(config.propagateCpuUtilization).isFalse();
assertThat(config.propagateMemUtilization).isFalse();
assertThat(config.propagateApplicationUtilization).isFalse();
assertThat(config.shouldPropagateNamedMetric("any_key")).isTrue();
assertThat(config.shouldPropagateNamedMetric("another_key")).isTrue();
}
@Test
public void fromMetricSpecs_specificNamedMetrics() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
ImmutableList.of("named_metrics.foo", "named_metrics.bar"));
assertThat(config.shouldPropagateNamedMetric("foo")).isTrue();
assertThat(config.shouldPropagateNamedMetric("bar")).isTrue();
assertThat(config.shouldPropagateNamedMetric("baz")).isFalse();
assertThat(config.shouldPropagateNamedMetric("any")).isFalse();
}
@Test
public void fromMetricSpecs_mixedStandardAndNamed() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
ImmutableList.of("cpu_utilization", "named_metrics.foo", "named_metrics.bar"));
assertThat(config.propagateCpuUtilization).isTrue();
assertThat(config.propagateMemUtilization).isFalse();
assertThat(config.shouldPropagateNamedMetric("foo")).isTrue();
assertThat(config.shouldPropagateNamedMetric("bar")).isTrue();
assertThat(config.shouldPropagateNamedMetric("baz")).isFalse();
}
@Test
public void fromMetricSpecs_wildcardAndSpecificNamedMetrics() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
ImmutableList.of("named_metrics.foo", "named_metrics.*"));
assertThat(config.shouldPropagateNamedMetric("foo")).isTrue();
assertThat(config.shouldPropagateNamedMetric("bar")).isTrue();
assertThat(config.shouldPropagateNamedMetric("any_other_key")).isTrue();
}
@Test
public void fromMetricSpecs_malformedAndUnknownSpecs_areIgnored() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
asList(
"cpu_utilization", // valid
null, // ignored
"disk_utilization", // ignored
"named_metrics.", // ignored, empty key
"named_metrics.valid" // valid
));
assertThat(config.propagateCpuUtilization).isTrue();
assertThat(config.propagateMemUtilization).isFalse();
assertThat(config.shouldPropagateNamedMetric("disk_utilization")).isFalse();
assertThat(config.shouldPropagateNamedMetric("valid")).isTrue();
assertThat(config.shouldPropagateNamedMetric("")).isFalse(); // from the empty key
}
@Test
public void fromMetricSpecs_duplicateSpecs_areHandledGracefully() {
BackendMetricPropagation config = BackendMetricPropagation.fromMetricSpecs(
ImmutableList.of(
"cpu_utilization",
"named_metrics.foo",
"cpu_utilization",
"named_metrics.foo"));
assertThat(config.propagateCpuUtilization).isTrue();
assertThat(config.shouldPropagateNamedMetric("foo")).isTrue();
assertThat(config.shouldPropagateNamedMetric("bar")).isFalse();
}
}