@ -26,6 +26,7 @@
# include "src/core/ext/filters/client_channel/backup_poller.h"
# include "src/core/ext/filters/client_channel/backup_poller.h"
# include "src/core/lib/address_utils/sockaddr_utils.h"
# include "src/core/lib/address_utils/sockaddr_utils.h"
# include "src/core/lib/config/config_vars.h"
# include "src/core/lib/config/config_vars.h"
# include "src/proto/grpc/testing/xds/v3/orca_load_report.pb.h"
# include "test/cpp/end2end/connection_attempt_injector.h"
# include "test/cpp/end2end/connection_attempt_injector.h"
# include "test/cpp/end2end/xds/xds_end2end_test_lib.h"
# include "test/cpp/end2end/xds/xds_end2end_test_lib.h"
@ -1375,6 +1376,18 @@ INSTANTIATE_TEST_SUITE_P(
: : testing : : Values ( XdsTestType ( ) . set_enable_load_reporting ( ) ) ,
: : testing : : Values ( XdsTestType ( ) . set_enable_load_reporting ( ) ) ,
& XdsTestType : : Name ) ;
& XdsTestType : : Name ) ;
MATCHER_P2 ( LoadMetricEq , num_requests_finished_with_metric , total_metric_value ,
" equals LoadMetric " ) {
bool match = true ;
match & = : : testing : : ExplainMatchResult ( num_requests_finished_with_metric ,
arg . num_requests_finished_with_metric ,
result_listener ) ;
match & =
: : testing : : ExplainMatchResult ( : : testing : : DoubleEq ( total_metric_value ) ,
arg . total_metric_value , result_listener ) ;
return match ;
}
// Tests that the load report received at the balancer is correct.
// Tests that the load report received at the balancer is correct.
TEST_P ( ClientLoadReportingTest , Vanilla ) {
TEST_P ( ClientLoadReportingTest , Vanilla ) {
CreateAndStartBackends ( 4 ) ;
CreateAndStartBackends ( 4 ) ;
@ -1389,11 +1402,19 @@ TEST_P(ClientLoadReportingTest, Vanilla) {
size_t num_warmup_rpcs =
size_t num_warmup_rpcs =
WaitForAllBackends ( DEBUG_LOCATION , 0 , 4 , /*check_status=*/ nullptr ,
WaitForAllBackends ( DEBUG_LOCATION , 0 , 4 , /*check_status=*/ nullptr ,
WaitForBackendOptions ( ) . set_reset_counters ( false ) ) ;
WaitForBackendOptions ( ) . set_reset_counters ( false ) ) ;
// Send kNumRpcsPerAddress RPCs per server.
// Send kNumRpcsPerAddress RPCs per server with named metrics.
CheckRpcSendOk ( DEBUG_LOCATION , kNumRpcsPerAddress * backends_ . size ( ) ) ;
xds : : data : : orca : : v3 : : OrcaLoadReport backend_metrics ;
auto & named_metrics = ( * backend_metrics . mutable_named_metrics ( ) ) ;
named_metrics [ " foo " ] = 1.0 ;
named_metrics [ " bar " ] = 2.0 ;
CheckRpcSendOk ( DEBUG_LOCATION , kNumRpcsPerAddress * backends_ . size ( ) ,
RpcOptions ( ) . set_backend_metrics ( backend_metrics ) ) ;
named_metrics [ " foo " ] = 0.3 ;
named_metrics [ " bar " ] = 0.4 ;
for ( size_t i = 0 ; i < kNumFailuresPerAddress * backends_ . size ( ) ; + + i ) {
for ( size_t i = 0 ; i < kNumFailuresPerAddress * backends_ . size ( ) ; + + i ) {
CheckRpcSendFailure ( DEBUG_LOCATION , StatusCode : : FAILED_PRECONDITION , " " ,
CheckRpcSendFailure ( DEBUG_LOCATION , StatusCode : : FAILED_PRECONDITION , " " ,
RpcOptions ( ) . set_server_fail ( true ) ) ;
RpcOptions ( ) . set_server_fail ( true ) . set_backend_metrics (
backend_metrics ) ) ;
}
}
const size_t total_successful_rpcs_sent =
const size_t total_successful_rpcs_sent =
( kNumRpcsPerAddress * backends_ . size ( ) ) + num_warmup_rpcs ;
( kNumRpcsPerAddress * backends_ . size ( ) ) + num_warmup_rpcs ;
@ -1425,6 +1446,8 @@ TEST_P(ClientLoadReportingTest, Vanilla) {
: : testing : : Pair ( " locality1 " , : : testing : : _ ) ) ) ;
: : testing : : Pair ( " locality1 " , : : testing : : _ ) ) ) ;
size_t num_successful_rpcs = 0 ;
size_t num_successful_rpcs = 0 ;
size_t num_failed_rpcs = 0 ;
size_t num_failed_rpcs = 0 ;
std : : map < std : : string , ClientStats : : LocalityStats : : LoadMetric >
named_metrics_total ;
for ( const auto & p : client_stats . locality_stats ( ) ) {
for ( const auto & p : client_stats . locality_stats ( ) ) {
EXPECT_EQ ( p . second . total_requests_in_progress , 0U ) ;
EXPECT_EQ ( p . second . total_requests_in_progress , 0U ) ;
EXPECT_EQ (
EXPECT_EQ (
@ -1432,10 +1455,30 @@ TEST_P(ClientLoadReportingTest, Vanilla) {
p . second . total_successful_requests + p . second . total_error_requests ) ;
p . second . total_successful_requests + p . second . total_error_requests ) ;
num_successful_rpcs + = p . second . total_successful_requests ;
num_successful_rpcs + = p . second . total_successful_requests ;
num_failed_rpcs + = p . second . total_error_requests ;
num_failed_rpcs + = p . second . total_error_requests ;
for ( const auto & s : p . second . load_metrics ) {
named_metrics_total [ s . first ] + = s . second ;
}
}
}
EXPECT_EQ ( num_successful_rpcs , total_successful_rpcs_sent ) ;
EXPECT_EQ ( num_successful_rpcs , total_successful_rpcs_sent ) ;
EXPECT_EQ ( num_failed_rpcs , total_failed_rpcs_sent ) ;
EXPECT_EQ ( num_failed_rpcs , total_failed_rpcs_sent ) ;
EXPECT_EQ ( num_successful_rpcs + num_failed_rpcs , total_rpcs_sent ) ;
EXPECT_EQ ( num_successful_rpcs + num_failed_rpcs , total_rpcs_sent ) ;
EXPECT_THAT (
named_metrics_total ,
: : testing : : UnorderedElementsAre (
: : testing : : Pair (
" foo " ,
LoadMetricEq (
( kNumRpcsPerAddress + kNumFailuresPerAddress ) *
backends_ . size ( ) ,
( kNumRpcsPerAddress * backends_ . size ( ) ) * 1.0 +
( kNumFailuresPerAddress * backends_ . size ( ) ) * 0.3 ) ) ,
: : testing : : Pair (
" bar " ,
LoadMetricEq (
( kNumRpcsPerAddress + kNumFailuresPerAddress ) *
backends_ . size ( ) ,
( kNumRpcsPerAddress * backends_ . size ( ) ) * 2.0 +
( kNumFailuresPerAddress * backends_ . size ( ) ) * 0.4 ) ) ) ) ;
// The LRS service got a single request, and sent a single response.
// The LRS service got a single request, and sent a single response.
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > request_count ( ) ) ;
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > request_count ( ) ) ;
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > response_count ( ) ) ;
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > response_count ( ) ) ;
@ -1452,10 +1495,18 @@ TEST_P(ClientLoadReportingTest, SendAllClusters) {
// Wait until all backends are ready.
// Wait until all backends are ready.
size_t num_warmup_rpcs = WaitForAllBackends ( DEBUG_LOCATION ) ;
size_t num_warmup_rpcs = WaitForAllBackends ( DEBUG_LOCATION ) ;
// Send kNumRpcsPerAddress RPCs per server.
// Send kNumRpcsPerAddress RPCs per server.
CheckRpcSendOk ( DEBUG_LOCATION , kNumRpcsPerAddress * backends_ . size ( ) ) ;
xds : : data : : orca : : v3 : : OrcaLoadReport backend_metrics ;
auto & named_metrics = ( * backend_metrics . mutable_named_metrics ( ) ) ;
named_metrics [ " foo " ] = 1.0 ;
named_metrics [ " bar " ] = 2.0 ;
CheckRpcSendOk ( DEBUG_LOCATION , kNumRpcsPerAddress * backends_ . size ( ) ,
RpcOptions ( ) . set_backend_metrics ( backend_metrics ) ) ;
named_metrics [ " foo " ] = 0.3 ;
named_metrics [ " bar " ] = 0.4 ;
for ( size_t i = 0 ; i < kNumFailuresPerAddress * backends_ . size ( ) ; + + i ) {
for ( size_t i = 0 ; i < kNumFailuresPerAddress * backends_ . size ( ) ; + + i ) {
CheckRpcSendFailure ( DEBUG_LOCATION , StatusCode : : FAILED_PRECONDITION , " " ,
CheckRpcSendFailure ( DEBUG_LOCATION , StatusCode : : FAILED_PRECONDITION , " " ,
RpcOptions ( ) . set_server_fail ( true ) ) ;
RpcOptions ( ) . set_server_fail ( true ) . set_backend_metrics (
backend_metrics ) ) ;
}
}
// Check that each backend got the right number of requests.
// Check that each backend got the right number of requests.
for ( size_t i = 0 ; i < backends_ . size ( ) ; + + i ) {
for ( size_t i = 0 ; i < backends_ . size ( ) ; + + i ) {
@ -1476,6 +1527,29 @@ TEST_P(ClientLoadReportingTest, SendAllClusters) {
EXPECT_EQ ( kNumFailuresPerAddress * backends_ . size ( ) ,
EXPECT_EQ ( kNumFailuresPerAddress * backends_ . size ( ) ,
client_stats . total_error_requests ( ) ) ;
client_stats . total_error_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_dropped_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_dropped_requests ( ) ) ;
EXPECT_THAT (
client_stats . locality_stats ( ) ,
: : testing : : ElementsAre ( : : testing : : Pair (
" locality0 " ,
: : testing : : Field (
& ClientStats : : LocalityStats : : load_metrics ,
: : testing : : UnorderedElementsAre (
: : testing : : Pair (
" foo " ,
LoadMetricEq (
( kNumRpcsPerAddress + kNumFailuresPerAddress ) *
backends_ . size ( ) ,
( kNumRpcsPerAddress * backends_ . size ( ) ) * 1.0 +
( kNumFailuresPerAddress * backends_ . size ( ) ) *
0.3 ) ) ,
: : testing : : Pair (
" bar " ,
LoadMetricEq (
( kNumRpcsPerAddress + kNumFailuresPerAddress ) *
backends_ . size ( ) ,
( kNumRpcsPerAddress * backends_ . size ( ) ) * 2.0 +
( kNumFailuresPerAddress * backends_ . size ( ) ) *
0.4 ) ) ) ) ) ) ) ;
// The LRS service got a single request, and sent a single response.
// The LRS service got a single request, and sent a single response.
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > request_count ( ) ) ;
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > request_count ( ) ) ;
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > response_count ( ) ) ;
EXPECT_EQ ( 1U , balancer_ - > lrs_service ( ) - > response_count ( ) ) ;
@ -1515,6 +1589,11 @@ TEST_P(ClientLoadReportingTest, BalancerRestart) {
EXPECT_EQ ( 0U , client_stats . total_requests_in_progress ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_requests_in_progress ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_error_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_error_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_dropped_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_dropped_requests ( ) ) ;
EXPECT_THAT ( client_stats . locality_stats ( ) ,
: : testing : : ElementsAre ( : : testing : : Pair (
" locality0 " ,
: : testing : : Field ( & ClientStats : : LocalityStats : : load_metrics ,
: : testing : : IsEmpty ( ) ) ) ) ) ;
// Shut down the balancer.
// Shut down the balancer.
balancer_ - > Shutdown ( ) ;
balancer_ - > Shutdown ( ) ;
// We should continue using the last EDS response we received from the
// We should continue using the last EDS response we received from the
@ -1537,7 +1616,12 @@ TEST_P(ClientLoadReportingTest, BalancerRestart) {
// This tells us that we're now using the new serverlist.
// This tells us that we're now using the new serverlist.
num_rpcs + = WaitForAllBackends ( DEBUG_LOCATION , 2 , 4 ) ;
num_rpcs + = WaitForAllBackends ( DEBUG_LOCATION , 2 , 4 ) ;
// Send one RPC per backend.
// Send one RPC per backend.
CheckRpcSendOk ( DEBUG_LOCATION , 2 ) ;
xds : : data : : orca : : v3 : : OrcaLoadReport backend_metrics ;
auto & named_metrics = ( * backend_metrics . mutable_named_metrics ( ) ) ;
named_metrics [ " foo " ] = 1.0 ;
named_metrics [ " bar " ] = 2.0 ;
CheckRpcSendOk ( DEBUG_LOCATION , 2 ,
RpcOptions ( ) . set_backend_metrics ( backend_metrics ) ) ;
num_rpcs + = 2 ;
num_rpcs + = 2 ;
// Check client stats.
// Check client stats.
load_report = balancer_ - > lrs_service ( ) - > WaitForLoadReport ( ) ;
load_report = balancer_ - > lrs_service ( ) - > WaitForLoadReport ( ) ;
@ -1547,6 +1631,14 @@ TEST_P(ClientLoadReportingTest, BalancerRestart) {
EXPECT_EQ ( 0U , client_stats . total_requests_in_progress ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_requests_in_progress ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_error_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_error_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_dropped_requests ( ) ) ;
EXPECT_EQ ( 0U , client_stats . total_dropped_requests ( ) ) ;
EXPECT_THAT ( client_stats . locality_stats ( ) ,
: : testing : : ElementsAre ( : : testing : : Pair (
" locality0 " ,
: : testing : : Field (
& ClientStats : : LocalityStats : : load_metrics ,
: : testing : : UnorderedElementsAre (
: : testing : : Pair ( " foo " , LoadMetricEq ( 2 , 2.0 ) ) ,
: : testing : : Pair ( " bar " , LoadMetricEq ( 2 , 4.0 ) ) ) ) ) ) ) ;
}
}
// Tests load reporting when switching over from one cluster to another.
// Tests load reporting when switching over from one cluster to another.
@ -1600,7 +1692,10 @@ TEST_P(ClientLoadReportingTest, ChangeClusters) {
0UL ) ,
0UL ) ,
: : testing : : Field (
: : testing : : Field (
& ClientStats : : LocalityStats : : total_issued_requests ,
& ClientStats : : LocalityStats : : total_issued_requests ,
num_rpcs ) ) ) ) ) ,
num_rpcs ) ,
: : testing : : Field (
& ClientStats : : LocalityStats : : load_metrics ,
: : testing : : IsEmpty ( ) ) ) ) ) ) ,
: : testing : : Property ( & ClientStats : : total_dropped_requests , 0UL ) ) ) ) ;
: : testing : : Property ( & ClientStats : : total_dropped_requests , 0UL ) ) ) ) ;
// Change RDS resource to point to new cluster.
// Change RDS resource to point to new cluster.
RouteConfiguration new_route_config = default_route_config_ ;
RouteConfiguration new_route_config = default_route_config_ ;
@ -1638,7 +1733,10 @@ TEST_P(ClientLoadReportingTest, ChangeClusters) {
0UL ) ,
0UL ) ,
: : testing : : Field ( & ClientStats : : LocalityStats : :
: : testing : : Field ( & ClientStats : : LocalityStats : :
total_issued_requests ,
total_issued_requests ,
: : testing : : Le ( num_rpcs ) ) ) ) ) ) ,
: : testing : : Le ( num_rpcs ) ) ,
: : testing : : Field (
& ClientStats : : LocalityStats : : load_metrics ,
: : testing : : IsEmpty ( ) ) ) ) ) ) ,
: : testing : : Property ( & ClientStats : : total_dropped_requests , 0UL ) ) ,
: : testing : : Property ( & ClientStats : : total_dropped_requests , 0UL ) ) ,
: : testing : : AllOf (
: : testing : : AllOf (
: : testing : : Property ( & ClientStats : : cluster_name , kNewClusterName ) ,
: : testing : : Property ( & ClientStats : : cluster_name , kNewClusterName ) ,
@ -1660,7 +1758,10 @@ TEST_P(ClientLoadReportingTest, ChangeClusters) {
0UL ) ,
0UL ) ,
: : testing : : Field ( & ClientStats : : LocalityStats : :
: : testing : : Field ( & ClientStats : : LocalityStats : :
total_issued_requests ,
total_issued_requests ,
: : testing : : Le ( num_rpcs ) ) ) ) ) ) ,
: : testing : : Le ( num_rpcs ) ) ,
: : testing : : Field (
& ClientStats : : LocalityStats : : load_metrics ,
: : testing : : IsEmpty ( ) ) ) ) ) ) ,
: : testing : : Property ( & ClientStats : : total_dropped_requests , 0UL ) ) ) ) ;
: : testing : : Property ( & ClientStats : : total_dropped_requests , 0UL ) ) ) ) ;
size_t total_ok = 0 ;
size_t total_ok = 0 ;
for ( const ClientStats & client_stats : load_report ) {
for ( const ClientStats & client_stats : load_report ) {