@ -23,6 +23,7 @@
# include <cstdlib>
# include "absl/strings/str_cat.h"
# include "absl/strings/str_join.h"
# include <grpc/impl/codegen/log.h>
# include <grpc/support/alloc.h>
@ -125,8 +126,11 @@ const char* XdsApi::kCdsTypeUrl = "type.googleapis.com/envoy.api.v2.Cluster";
const char * XdsApi : : kEdsTypeUrl =
" type.googleapis.com/envoy.api.v2.ClusterLoadAssignment " ;
XdsApi : : XdsApi ( const XdsBootstrap : : Node * node )
: node_ ( node ) ,
XdsApi : : XdsApi ( XdsClient * client , TraceFlag * tracer ,
const XdsBootstrap : : Node * node )
: client_ ( client ) ,
tracer_ ( tracer ) ,
node_ ( node ) ,
build_version_ ( absl : : StrCat ( " gRPC C-core " , GPR_PLATFORM_STRING , " " ,
grpc_version_string ( ) ) ) ,
user_agent_name_ ( absl : : StrCat ( " gRPC C-core " , GPR_PLATFORM_STRING ) ) { }
@ -289,6 +293,162 @@ envoy_api_v2_DiscoveryRequest* CreateDiscoveryRequest(
return request ;
}
inline absl : : string_view UpbStringToAbsl ( const upb_strview & str ) {
return absl : : string_view ( str . data , str . size ) ;
}
inline void AddStringField ( const char * name , const upb_strview & value ,
std : : vector < std : : string > * fields ,
bool add_if_empty = false ) {
if ( value . size > 0 | | add_if_empty ) {
fields - > emplace_back (
absl : : StrCat ( name , " : \" " , UpbStringToAbsl ( value ) , " \" " ) ) ;
}
}
inline void AddLocalityField ( int indent_level ,
const envoy_api_v2_core_Locality * locality ,
std : : vector < std : : string > * fields ) {
std : : string indent =
absl : : StrJoin ( std : : vector < std : : string > ( indent_level , " " ) , " " ) ;
// region
std : : string field = absl : : StrCat ( indent , " region " ) ;
AddStringField ( field . c_str ( ) , envoy_api_v2_core_Locality_region ( locality ) ,
fields ) ;
// zone
field = absl : : StrCat ( indent , " zone " ) ;
AddStringField ( field . c_str ( ) , envoy_api_v2_core_Locality_zone ( locality ) ,
fields ) ;
// sub_zone
field = absl : : StrCat ( indent , " sub_zone " ) ;
AddStringField ( field . c_str ( ) , envoy_api_v2_core_Locality_sub_zone ( locality ) ,
fields ) ;
}
void AddNodeLogFields ( const envoy_api_v2_core_Node * node ,
std : : vector < std : : string > * fields ) {
fields - > emplace_back ( " node { " ) ;
// id
AddStringField ( " id " , envoy_api_v2_core_Node_id ( node ) , fields ) ;
// metadata
const google_protobuf_Struct * metadata =
envoy_api_v2_core_Node_metadata ( node ) ;
if ( metadata ! = nullptr ) {
fields - > emplace_back ( " metadata { " ) ;
size_t num_entries ;
const google_protobuf_Struct_FieldsEntry * const * entries =
google_protobuf_Struct_fields ( metadata , & num_entries ) ;
for ( size_t i = 0 ; i < num_entries ; + + i ) {
fields - > emplace_back ( " field { " ) ;
// key
AddStringField ( " key " ,
google_protobuf_Struct_FieldsEntry_key ( entries [ i ] ) ,
fields ) ;
// value
const google_protobuf_Value * value =
google_protobuf_Struct_FieldsEntry_value ( entries [ i ] ) ;
if ( value ! = nullptr ) {
std : : string value_str ;
if ( google_protobuf_Value_has_string_value ( value ) ) {
value_str = absl : : StrCat (
" string_value: \" " ,
UpbStringToAbsl ( google_protobuf_Value_string_value ( value ) ) , " \" " ) ;
} else if ( google_protobuf_Value_has_null_value ( value ) ) {
value_str = " null_value: NULL_VALUE " ;
} else if ( google_protobuf_Value_has_number_value ( value ) ) {
value_str = absl : : StrCat ( " double_value: " ,
google_protobuf_Value_number_value ( value ) ) ;
} else if ( google_protobuf_Value_has_bool_value ( value ) ) {
value_str = absl : : StrCat ( " bool_value: " ,
google_protobuf_Value_bool_value ( value ) ) ;
} else if ( google_protobuf_Value_has_struct_value ( value ) ) {
value_str = " struct_value: <not printed> " ;
} else if ( google_protobuf_Value_has_list_value ( value ) ) {
value_str = " list_value: <not printed> " ;
} else {
value_str = " <unknown> " ;
}
fields - > emplace_back ( absl : : StrCat ( " value { " , value_str , " } " ) ) ;
}
fields - > emplace_back ( " } " ) ;
}
fields - > emplace_back ( " } " ) ;
}
// locality
const envoy_api_v2_core_Locality * locality =
envoy_api_v2_core_Node_locality ( node ) ;
if ( locality ! = nullptr ) {
fields - > emplace_back ( " locality { " ) ;
AddLocalityField ( 2 , locality , fields ) ;
fields - > emplace_back ( " } " ) ;
}
// build_version
AddStringField ( " build_version " , envoy_api_v2_core_Node_build_version ( node ) ,
fields ) ;
// user_agent_name
AddStringField ( " user_agent_name " ,
envoy_api_v2_core_Node_user_agent_name ( node ) , fields ) ;
// user_agent_version
AddStringField ( " user_agent_version " ,
envoy_api_v2_core_Node_user_agent_version ( node ) , fields ) ;
// client_features
size_t num_client_features ;
const upb_strview * client_features =
envoy_api_v2_core_Node_client_features ( node , & num_client_features ) ;
for ( size_t i = 0 ; i < num_client_features ; + + i ) {
AddStringField ( " client_features " , client_features [ i ] , fields ) ;
}
fields - > emplace_back ( " } " ) ;
}
void MaybeLogDiscoveryRequest ( XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_DiscoveryRequest * request ) {
if ( GRPC_TRACE_FLAG_ENABLED ( * tracer ) & &
gpr_should_log ( GPR_LOG_SEVERITY_DEBUG ) ) {
// TODO(roth): When we can upgrade upb, use upb textformat code to dump
// the raw proto instead of doing this manually.
std : : vector < std : : string > fields ;
// version_info
AddStringField ( " version_info " ,
envoy_api_v2_DiscoveryRequest_version_info ( request ) ,
& fields ) ;
// node
const envoy_api_v2_core_Node * node =
envoy_api_v2_DiscoveryRequest_node ( request ) ;
if ( node ! = nullptr ) AddNodeLogFields ( node , & fields ) ;
// resource_names
size_t num_resource_names ;
const upb_strview * resource_names =
envoy_api_v2_DiscoveryRequest_resource_names ( request ,
& num_resource_names ) ;
for ( size_t i = 0 ; i < num_resource_names ; + + i ) {
AddStringField ( " resource_names " , resource_names [ i ] , & fields ) ;
}
// type_url
AddStringField ( " type_url " , envoy_api_v2_DiscoveryRequest_type_url ( request ) ,
& fields ) ;
// response_nonce
AddStringField ( " response_nonce " ,
envoy_api_v2_DiscoveryRequest_response_nonce ( request ) ,
& fields ) ;
// error_detail
const struct google_rpc_Status * error_detail =
envoy_api_v2_DiscoveryRequest_error_detail ( request ) ;
if ( error_detail ! = nullptr ) {
fields . emplace_back ( " error_detail { " ) ;
// code
int32_t code = google_rpc_Status_code ( error_detail ) ;
if ( code ! = 0 ) fields . emplace_back ( absl : : StrCat ( " code: " , code ) ) ;
// message
AddStringField ( " message " , google_rpc_Status_message ( error_detail ) ,
& fields ) ;
fields . emplace_back ( " } " ) ;
}
gpr_log ( GPR_DEBUG , " [xds_client %p] constructed ADS request: %s " , client ,
absl : : StrJoin ( fields , " \n " ) . c_str ( ) ) ;
}
}
grpc_slice SerializeDiscoveryRequest ( upb_arena * arena ,
envoy_api_v2_DiscoveryRequest * request ) {
size_t output_length ;
@ -305,6 +465,7 @@ grpc_slice XdsApi::CreateUnsupportedTypeNackRequest(const std::string& type_url,
upb : : Arena arena ;
envoy_api_v2_DiscoveryRequest * request = CreateDiscoveryRequest (
arena . ptr ( ) , type_url . c_str ( ) , /*version=*/ " " , nonce , error ) ;
MaybeLogDiscoveryRequest ( client_ , tracer_ , request ) ;
return SerializeDiscoveryRequest ( arena . ptr ( ) , request ) ;
}
@ -326,6 +487,7 @@ grpc_slice XdsApi::CreateLdsRequest(const std::string& server_name,
envoy_api_v2_DiscoveryRequest_add_resource_names (
request , upb_strview_make ( server_name . data ( ) , server_name . size ( ) ) ,
arena . ptr ( ) ) ;
MaybeLogDiscoveryRequest ( client_ , tracer_ , request ) ;
return SerializeDiscoveryRequest ( arena . ptr ( ) , request ) ;
}
@ -348,6 +510,7 @@ grpc_slice XdsApi::CreateRdsRequest(const std::string& route_config_name,
request ,
upb_strview_make ( route_config_name . data ( ) , route_config_name . size ( ) ) ,
arena . ptr ( ) ) ;
MaybeLogDiscoveryRequest ( client_ , tracer_ , request ) ;
return SerializeDiscoveryRequest ( arena . ptr ( ) , request ) ;
}
@ -371,6 +534,7 @@ grpc_slice XdsApi::CreateCdsRequest(const std::set<StringView>& cluster_names,
request , upb_strview_make ( cluster_name . data ( ) , cluster_name . size ( ) ) ,
arena . ptr ( ) ) ;
}
MaybeLogDiscoveryRequest ( client_ , tracer_ , request ) ;
return SerializeDiscoveryRequest ( arena . ptr ( ) , request ) ;
}
@ -394,11 +558,347 @@ grpc_slice XdsApi::CreateEdsRequest(
upb_strview_make ( eds_service_name . data ( ) , eds_service_name . size ( ) ) ,
arena . ptr ( ) ) ;
}
MaybeLogDiscoveryRequest ( client_ , tracer_ , request ) ;
return SerializeDiscoveryRequest ( arena . ptr ( ) , request ) ;
}
namespace {
void MaybeLogDiscoveryResponse ( XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_DiscoveryResponse * response ) {
if ( GRPC_TRACE_FLAG_ENABLED ( * tracer ) & &
gpr_should_log ( GPR_LOG_SEVERITY_DEBUG ) ) {
// TODO(roth): When we can upgrade upb, use upb textformat code to dump
// the raw proto instead of doing this manually.
std : : vector < std : : string > fields ;
// version_info
AddStringField ( " version_info " ,
envoy_api_v2_DiscoveryResponse_version_info ( response ) ,
& fields ) ;
// resources
size_t num_resources ;
envoy_api_v2_DiscoveryResponse_resources ( response , & num_resources ) ;
fields . emplace_back (
absl : : StrCat ( " resources: < " , num_resources , " element(s)> " ) ) ;
// type_url
AddStringField ( " type_url " ,
envoy_api_v2_DiscoveryResponse_type_url ( response ) , & fields ) ;
// nonce
AddStringField ( " nonce " , envoy_api_v2_DiscoveryResponse_nonce ( response ) ,
& fields ) ;
gpr_log ( GPR_DEBUG , " [xds_client %p] received response: %s " , client ,
absl : : StrJoin ( fields , " \n " ) . c_str ( ) ) ;
}
}
void MaybeLogRouteConfiguration (
XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_RouteConfiguration * route_config ) {
if ( GRPC_TRACE_FLAG_ENABLED ( * tracer ) & &
gpr_should_log ( GPR_LOG_SEVERITY_DEBUG ) ) {
// TODO(roth): When we can upgrade upb, use upb textformat code to dump
// the raw proto instead of doing this manually.
std : : vector < std : : string > fields ;
// name
AddStringField ( " name " , envoy_api_v2_RouteConfiguration_name ( route_config ) ,
& fields ) ;
// virtual_hosts
size_t num_virtual_hosts ;
const envoy_api_v2_route_VirtualHost * const * virtual_hosts =
envoy_api_v2_RouteConfiguration_virtual_hosts ( route_config ,
& num_virtual_hosts ) ;
for ( size_t i = 0 ; i < num_virtual_hosts ; + + i ) {
const auto * virtual_host = virtual_hosts [ i ] ;
fields . push_back ( " virtual_hosts { " ) ;
// name
AddStringField (
" name " , envoy_api_v2_route_VirtualHost_name ( virtual_host ) , & fields ) ;
// domains
size_t num_domains ;
const upb_strview * const domains =
envoy_api_v2_route_VirtualHost_domains ( virtual_host , & num_domains ) ;
for ( size_t j = 0 ; j < num_domains ; + + j ) {
AddStringField ( " domains " , domains [ j ] , & fields ) ;
}
// routes
size_t num_routes ;
const envoy_api_v2_route_Route * const * routes =
envoy_api_v2_route_VirtualHost_routes ( virtual_host , & num_routes ) ;
for ( size_t j = 0 ; j < num_routes ; + + j ) {
const auto * route = routes [ j ] ;
fields . push_back ( " route { " ) ;
// name
AddStringField ( " name " , envoy_api_v2_route_Route_name ( route ) ,
& fields ) ;
// match
const envoy_api_v2_route_RouteMatch * match =
envoy_api_v2_route_Route_match ( route ) ;
if ( match ! = nullptr ) {
fields . emplace_back ( " match { " ) ;
// path matching
if ( envoy_api_v2_route_RouteMatch_has_prefix ( match ) ) {
AddStringField ( " prefix " ,
envoy_api_v2_route_RouteMatch_prefix ( match ) , & fields ,
/*add_if_empty=*/ true ) ;
} else if ( envoy_api_v2_route_RouteMatch_has_path ( match ) ) {
AddStringField ( " path " ,
envoy_api_v2_route_RouteMatch_path ( match ) , & fields ,
/*add_if_empty=*/ true ) ;
} else if ( envoy_api_v2_route_RouteMatch_has_regex ( match ) ) {
AddStringField ( " regex " ,
envoy_api_v2_route_RouteMatch_regex ( match ) , & fields ,
/*add_if_empty=*/ true ) ;
} else if ( envoy_api_v2_route_RouteMatch_has_safe_regex ( match ) ) {
fields . emplace_back ( " safe_regex: <not printed> " ) ;
} else {
fields . emplace_back ( " <unknown path matching type> " ) ;
}
// header matching
size_t num_headers ;
envoy_api_v2_route_RouteMatch_headers ( match , & num_headers ) ;
if ( num_headers > 0 ) {
fields . emplace_back (
absl : : StrCat ( " headers: < " , num_headers , " element(s)> " ) ) ;
}
fields . emplace_back ( " } " ) ;
}
// action
if ( envoy_api_v2_route_Route_has_route ( route ) ) {
const envoy_api_v2_route_RouteAction * action =
envoy_api_v2_route_Route_route ( route ) ;
fields . emplace_back ( " route { " ) ;
if ( envoy_api_v2_route_RouteAction_has_cluster ( action ) ) {
AddStringField ( " cluster " ,
envoy_api_v2_route_RouteAction_cluster ( action ) ,
& fields ) ;
} else if ( envoy_api_v2_route_RouteAction_has_cluster_header (
action ) ) {
AddStringField (
" cluster_header " ,
envoy_api_v2_route_RouteAction_cluster_header ( action ) , & fields ) ;
} else if ( envoy_api_v2_route_RouteAction_has_weighted_clusters (
action ) ) {
fields . emplace_back ( " weighted_clusters: <not printed> " ) ;
}
fields . emplace_back ( " } " ) ;
} else if ( envoy_api_v2_route_Route_has_redirect ( route ) ) {
fields . emplace_back ( " redirect: <not printed> " ) ;
} else if ( envoy_api_v2_route_Route_has_direct_response ( route ) ) {
fields . emplace_back ( " direct_response: <not printed> " ) ;
} else if ( envoy_api_v2_route_Route_has_filter_action ( route ) ) {
fields . emplace_back ( " filter_action: <not printed> " ) ;
}
fields . push_back ( " } " ) ;
}
fields . push_back ( " } " ) ;
}
gpr_log ( GPR_DEBUG , " [xds_client %p] RouteConfiguration: %s " , client ,
absl : : StrJoin ( fields , " \n " ) . c_str ( ) ) ;
}
}
void MaybeLogCluster ( XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_Cluster * cluster ) {
if ( GRPC_TRACE_FLAG_ENABLED ( * tracer ) & &
gpr_should_log ( GPR_LOG_SEVERITY_DEBUG ) ) {
// TODO(roth): When we can upgrade upb, use upb textformat code to dump
// the raw proto instead of doing this manually.
std : : vector < std : : string > fields ;
// name
AddStringField ( " name " , envoy_api_v2_Cluster_name ( cluster ) , & fields ) ;
// type
if ( envoy_api_v2_Cluster_has_type ( cluster ) ) {
fields . emplace_back (
absl : : StrCat ( " type: " , envoy_api_v2_Cluster_type ( cluster ) ) ) ;
} else if ( envoy_api_v2_Cluster_has_cluster_type ( cluster ) ) {
fields . emplace_back ( " cluster_type: <not printed> " ) ;
} else {
fields . emplace_back ( " <unknown type> " ) ;
}
// eds_cluster_config
const envoy_api_v2_Cluster_EdsClusterConfig * eds_cluster_config =
envoy_api_v2_Cluster_eds_cluster_config ( cluster ) ;
if ( eds_cluster_config ! = nullptr ) {
fields . emplace_back ( " eds_cluster_config { " ) ;
// eds_config
const struct envoy_api_v2_core_ConfigSource * eds_config =
envoy_api_v2_Cluster_EdsClusterConfig_eds_config ( eds_cluster_config ) ;
if ( eds_config ! = nullptr ) {
if ( envoy_api_v2_core_ConfigSource_has_ads ( eds_config ) ) {
fields . emplace_back ( " eds_config { ads {} } " ) ;
} else {
fields . emplace_back ( " eds_config: <non-ADS type> " ) ;
}
}
// service_name
AddStringField ( " service_name " ,
envoy_api_v2_Cluster_EdsClusterConfig_service_name (
eds_cluster_config ) ,
& fields ) ;
fields . emplace_back ( " } " ) ;
}
// lb_policy
fields . emplace_back (
absl : : StrCat ( " lb_policy: " , envoy_api_v2_Cluster_lb_policy ( cluster ) ) ) ;
// lrs_server
const envoy_api_v2_core_ConfigSource * lrs_server =
envoy_api_v2_Cluster_lrs_server ( cluster ) ;
if ( lrs_server ! = nullptr ) {
if ( envoy_api_v2_core_ConfigSource_has_self ( lrs_server ) ) {
fields . emplace_back ( " lrs_server { self {} } " ) ;
} else {
fields . emplace_back ( " lrs_server: <non-self type> " ) ;
}
}
gpr_log ( GPR_DEBUG , " [xds_client %p] Cluster: %s " , client ,
absl : : StrJoin ( fields , " \n " ) . c_str ( ) ) ;
}
}
void MaybeLogClusterLoadAssignment (
XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_ClusterLoadAssignment * cla ) {
if ( GRPC_TRACE_FLAG_ENABLED ( * tracer ) & &
gpr_should_log ( GPR_LOG_SEVERITY_DEBUG ) ) {
// TODO(roth): When we can upgrade upb, use upb textformat code to dump
// the raw proto instead of doing this manually.
std : : vector < std : : string > fields ;
// cluster_name
AddStringField ( " cluster_name " ,
envoy_api_v2_ClusterLoadAssignment_cluster_name ( cla ) ,
& fields ) ;
// endpoints
size_t num_localities ;
const struct envoy_api_v2_endpoint_LocalityLbEndpoints * const *
locality_endpoints =
envoy_api_v2_ClusterLoadAssignment_endpoints ( cla , & num_localities ) ;
for ( size_t i = 0 ; i < num_localities ; + + i ) {
const auto * locality_endpoint = locality_endpoints [ i ] ;
fields . emplace_back ( " endpoints { " ) ;
// locality
const auto * locality =
envoy_api_v2_endpoint_LocalityLbEndpoints_locality ( locality_endpoint ) ;
if ( locality ! = nullptr ) {
fields . emplace_back ( " locality { " ) ;
AddLocalityField ( 2 , locality , & fields ) ;
fields . emplace_back ( " } " ) ;
}
// lb_endpoints
size_t num_lb_endpoints ;
const envoy_api_v2_endpoint_LbEndpoint * const * lb_endpoints =
envoy_api_v2_endpoint_LocalityLbEndpoints_lb_endpoints (
locality_endpoint , & num_lb_endpoints ) ;
for ( size_t j = 0 ; j < num_lb_endpoints ; + + j ) {
const auto * lb_endpoint = lb_endpoints [ j ] ;
fields . emplace_back ( " lb_endpoints { " ) ;
// health_status
uint32_t health_status =
envoy_api_v2_endpoint_LbEndpoint_health_status ( lb_endpoint ) ;
if ( health_status > 0 ) {
fields . emplace_back (
absl : : StrCat ( " health_status: " , health_status ) ) ;
}
// endpoint
const envoy_api_v2_endpoint_Endpoint * endpoint =
envoy_api_v2_endpoint_LbEndpoint_endpoint ( lb_endpoint ) ;
if ( endpoint ! = nullptr ) {
fields . emplace_back ( " endpoint { " ) ;
// address
const auto * address =
envoy_api_v2_endpoint_Endpoint_address ( endpoint ) ;
if ( address ! = nullptr ) {
fields . emplace_back ( " address { " ) ;
// socket_address
const auto * socket_address =
envoy_api_v2_core_Address_socket_address ( address ) ;
if ( socket_address ! = nullptr ) {
fields . emplace_back ( " socket_address { " ) ;
// address
AddStringField (
" address " ,
envoy_api_v2_core_SocketAddress_address ( socket_address ) ,
& fields ) ;
// port_value
if ( envoy_api_v2_core_SocketAddress_has_port_value (
socket_address ) ) {
fields . emplace_back (
absl : : StrCat ( " port_value: " ,
envoy_api_v2_core_SocketAddress_port_value (
socket_address ) ) ) ;
} else {
fields . emplace_back ( " <non-numeric port> " ) ;
}
fields . emplace_back ( " } " ) ;
} else {
fields . emplace_back ( " <non-socket address> " ) ;
}
fields . emplace_back ( " } " ) ;
}
fields . emplace_back ( " } " ) ;
}
fields . emplace_back ( " } " ) ;
}
// load_balancing_weight
const google_protobuf_UInt32Value * lb_weight =
envoy_api_v2_endpoint_LocalityLbEndpoints_load_balancing_weight (
locality_endpoint ) ;
if ( lb_weight ! = nullptr ) {
fields . emplace_back (
absl : : StrCat ( " load_balancing_weight { value: " ,
google_protobuf_UInt32Value_value ( lb_weight ) , " } " ) ) ;
}
// priority
uint32_t priority =
envoy_api_v2_endpoint_LocalityLbEndpoints_priority ( locality_endpoint ) ;
if ( priority > 0 ) {
fields . emplace_back ( absl : : StrCat ( " priority: " , priority ) ) ;
}
fields . emplace_back ( " } " ) ;
}
// policy
const envoy_api_v2_ClusterLoadAssignment_Policy * policy =
envoy_api_v2_ClusterLoadAssignment_policy ( cla ) ;
if ( policy ! = nullptr ) {
fields . emplace_back ( " policy { " ) ;
// drop_overloads
size_t num_drop_overloads ;
const envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload * const *
drop_overloads =
envoy_api_v2_ClusterLoadAssignment_Policy_drop_overloads (
policy , & num_drop_overloads ) ;
for ( size_t i = 0 ; i < num_drop_overloads ; + + i ) {
auto * drop_overload = drop_overloads [ i ] ;
fields . emplace_back ( " drop_overloads { " ) ;
// category
AddStringField (
" category " ,
envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload_category (
drop_overload ) ,
& fields ) ;
// drop_percentage
const auto * drop_percentage =
envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload_drop_percentage (
drop_overload ) ;
if ( drop_percentage ! = nullptr ) {
fields . emplace_back ( " drop_percentage { " ) ;
fields . emplace_back ( absl : : StrCat (
" numerator: " ,
envoy_type_FractionalPercent_numerator ( drop_percentage ) ) ) ;
fields . emplace_back ( absl : : StrCat (
" denominator: " ,
envoy_type_FractionalPercent_denominator ( drop_percentage ) ) ) ;
fields . emplace_back ( " } " ) ;
}
fields . emplace_back ( " } " ) ;
}
// overprovisioning_factor
fields . emplace_back ( " } " ) ;
}
gpr_log ( GPR_DEBUG , " [xds_client %p] ClusterLoadAssignment: %s " , client ,
absl : : StrJoin ( fields , " \n " ) . c_str ( ) ) ;
}
}
// Better match type has smaller value.
enum MatchType {
EXACT_MATCH ,
@ -449,8 +949,10 @@ MatchType DomainPatternMatchType(const std::string& domain_pattern) {
}
grpc_error * RouteConfigParse (
XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_RouteConfiguration * route_config ,
const std : : string & expected_server_name , XdsApi : : RdsUpdate * rds_update ) {
MaybeLogRouteConfiguration ( client , tracer , route_config ) ;
// Get the virtual hosts.
size_t size ;
const envoy_api_v2_route_VirtualHost * const * virtual_hosts =
@ -540,17 +1042,15 @@ grpc_error* RouteConfigParse(
return GRPC_ERROR_NONE ;
}
grpc_error * LdsResponseParse ( const envoy_api_v2_DiscoveryResponse * response ,
grpc_error * LdsResponseParse ( XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_DiscoveryResponse * response ,
const std : : string & expected_server_name ,
XdsApi : : LdsUpdate * lds_update , upb_arena * arena ) {
absl : : optional < XdsApi : : LdsUpdate > * lds_update ,
upb_arena * arena ) {
// Get the resources from the response.
size_t size ;
const google_protobuf_Any * const * resources =
envoy_api_v2_DiscoveryResponse_resources ( response , & size ) ;
if ( size < 1 ) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" LDS response contains 0 resource. " ) ;
}
for ( size_t i = 0 ; i < size ; + + i ) {
// Check the type_url of the resource.
const upb_strview type_url = google_protobuf_Any_type_url ( resources [ i ] ) ;
@ -590,14 +1090,11 @@ grpc_error* LdsResponseParse(const envoy_api_v2_DiscoveryResponse* response,
envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_config (
http_connection_manager ) ;
XdsApi : : RdsUpdate rds_update ;
grpc_error * error =
RouteConfigParse ( route_config , expected_server_name , & rds_update ) ;
grpc_error * error = RouteConfigParse ( client , tracer , route_config ,
expected_server_name , & rds_update ) ;
if ( error ! = GRPC_ERROR_NONE ) return error ;
lds_update - > rds_update . emplace ( std : : move ( rds_update ) ) ;
const upb_strview route_config_name =
envoy_api_v2_RouteConfiguration_name ( route_config ) ;
lds_update - > route_config_name =
std : : string ( route_config_name . data , route_config_name . size ) ;
lds_update - > emplace ( ) ;
( * lds_update ) - > rds_update . emplace ( std : : move ( rds_update ) ) ;
return GRPC_ERROR_NONE ;
}
// Validate that RDS must be used to get the route_config dynamically.
@ -613,26 +1110,24 @@ grpc_error* LdsResponseParse(const envoy_api_v2_DiscoveryResponse* response,
const upb_strview route_config_name =
envoy_config_filter_network_http_connection_manager_v2_Rds_route_config_name (
rds ) ;
lds_update - > route_config_name =
lds_update - > emplace ( ) ;
( * lds_update ) - > route_config_name =
std : : string ( route_config_name . data , route_config_name . size ) ;
return GRPC_ERROR_NONE ;
}
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" No listener found for expected server name. " ) ;
return GRPC_ERROR_NONE ;
}
grpc_error * RdsResponseParse ( const envoy_api_v2_DiscoveryResponse * response ,
grpc_error * RdsResponseParse ( XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_DiscoveryResponse * response ,
const std : : string & expected_server_name ,
const std : : string & expected_route_config_name ,
XdsApi : : RdsUpdate * rds_update , upb_arena * arena ) {
absl : : optional < XdsApi : : RdsUpdate > * rds_update ,
upb_arena * arena ) {
// Get the resources from the response.
size_t size ;
const google_protobuf_Any * const * resources =
envoy_api_v2_DiscoveryResponse_resources ( response , & size ) ;
if ( size < 1 ) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" RDS response contains 0 resource. " ) ;
}
for ( size_t i = 0 ; i < size ; + + i ) {
// Check the type_url of the resource.
const upb_strview type_url = google_protobuf_Any_type_url ( resources [ i ] ) ;
@ -655,27 +1150,24 @@ grpc_error* RdsResponseParse(const envoy_api_v2_DiscoveryResponse* response,
if ( ! upb_strview_eql ( name , expected_name ) ) continue ;
// Parse the route_config.
XdsApi : : RdsUpdate local_rds_update ;
grpc_error * error =
RouteConfigParse ( route_config , expected_server_name , & local_rds_update ) ;
grpc_error * error = RouteConfigParse (
client , tracer , route_config , expected_server_name , & local_rds_update ) ;
if ( error ! = GRPC_ERROR_NONE ) return error ;
* rds_update = std : : move ( local_rds_update ) ;
rds_update - > emplace ( std : : move ( local_rds_update ) ) ;
return GRPC_ERROR_NONE ;
}
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" No route config found for expected name. " ) ;
return GRPC_ERROR_NONE ;
}
grpc_error * CdsResponseParse ( const envoy_api_v2_DiscoveryResponse * response ,
grpc_error * CdsResponseParse ( XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_DiscoveryResponse * response ,
const std : : set < StringView > & expected_cluster_names ,
XdsApi : : CdsUpdateMap * cds_update_map ,
upb_arena * arena ) {
// Get the resources from the response.
size_t size ;
const google_protobuf_Any * const * resources =
envoy_api_v2_DiscoveryResponse_resources ( response , & size ) ;
if ( size < 1 ) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" CDS response contains 0 resource. " ) ;
}
// Parse all the resources in the CDS response.
for ( size_t i = 0 ; i < size ; + + i ) {
XdsApi : : CdsUpdate cds_update ;
@ -691,6 +1183,14 @@ grpc_error* CdsResponseParse(const envoy_api_v2_DiscoveryResponse* response,
if ( cluster = = nullptr ) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING ( " Can't decode cluster. " ) ;
}
MaybeLogCluster ( client , tracer , cluster ) ;
// Ignore unexpected cluster names.
upb_strview cluster_name = envoy_api_v2_Cluster_name ( cluster ) ;
StringView cluster_name_strview ( cluster_name . data , cluster_name . size ) ;
if ( expected_cluster_names . find ( cluster_name_strview ) = =
expected_cluster_names . end ( ) ) {
continue ;
}
// Check the cluster_discovery_type.
if ( ! envoy_api_v2_Cluster_has_type ( cluster ) ) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING ( " DiscoveryType not found. " ) ;
@ -729,7 +1229,6 @@ grpc_error* CdsResponseParse(const envoy_api_v2_DiscoveryResponse* response,
}
cds_update . lrs_load_reporting_server_name . emplace ( " " ) ;
}
upb_strview cluster_name = envoy_api_v2_Cluster_name ( cluster ) ;
cds_update_map - > emplace ( std : : string ( cluster_name . data , cluster_name . size ) ,
std : : move ( cds_update ) ) ;
}
@ -849,6 +1348,7 @@ grpc_error* DropParseAndAppend(
}
grpc_error * EdsResponsedParse (
XdsClient * client , TraceFlag * tracer ,
const envoy_api_v2_DiscoveryResponse * response ,
const std : : set < StringView > & expected_eds_service_names ,
XdsApi : : EdsUpdateMap * eds_update_map , upb_arena * arena ) {
@ -856,10 +1356,6 @@ grpc_error* EdsResponsedParse(
size_t size ;
const google_protobuf_Any * const * resources =
envoy_api_v2_DiscoveryResponse_resources ( response , & size ) ;
if ( size < 1 ) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" EDS response contains 0 resource. " ) ;
}
for ( size_t i = 0 ; i < size ; + + i ) {
XdsApi : : EdsUpdate eds_update ;
// Check the type_url of the resource.
@ -878,6 +1374,7 @@ grpc_error* EdsResponsedParse(
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" Can't parse cluster_load_assignment. " ) ;
}
MaybeLogClusterLoadAssignment ( client , tracer , cluster_load_assignment ) ;
// Check the cluster name (which actually means eds_service_name). Ignore
// unexpected names.
upb_strview cluster_name = envoy_api_v2_ClusterLoadAssignment_cluster_name (
@ -934,8 +1431,10 @@ grpc_error* EdsResponsedParse(
grpc_error * XdsApi : : ParseAdsResponse (
const grpc_slice & encoded_response , const std : : string & expected_server_name ,
const std : : string & expected_route_config_name ,
const std : : set < StringView > & expected_cluster_names ,
const std : : set < StringView > & expected_eds_service_names ,
LdsUpdate * lds_update , RdsUpdate * rds_update , CdsUpdateMap * cds_update_map ,
absl : : optional < LdsUpdate > * lds_update ,
absl : : optional < RdsUpdate > * rds_update , CdsUpdateMap * cds_update_map ,
EdsUpdateMap * eds_update_map , std : : string * version , std : : string * nonce ,
std : : string * type_url ) {
upb : : Arena arena ;
@ -950,6 +1449,7 @@ grpc_error* XdsApi::ParseAdsResponse(
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" Can't decode the whole response. " ) ;
}
MaybeLogDiscoveryResponse ( client_ , tracer_ , response ) ;
// Record the type_url, the version_info, and the nonce of the response.
upb_strview type_url_strview =
envoy_api_v2_DiscoveryResponse_type_url ( response ) ;
@ -961,17 +1461,19 @@ grpc_error* XdsApi::ParseAdsResponse(
* nonce = std : : string ( nonce_strview . data , nonce_strview . size ) ;
// Parse the response according to the resource type.
if ( * type_url = = kLdsTypeUrl ) {
return LdsResponseParse ( response , expected_server_name , lds_updat e ,
arena . ptr ( ) ) ;
return LdsResponseParse ( client_ , tracer_ , response , expected_server_name ,
lds_update , arena . ptr ( ) ) ;
} else if ( * type_url = = kRdsTypeUrl ) {
return RdsResponseParse ( response , expected_server_name ,
return RdsResponseParse ( client_ , tracer_ , response , expected_server_name ,
expected_route_config_name , rds_update ,
arena . ptr ( ) ) ;
} else if ( * type_url = = kCdsTypeUrl ) {
return CdsResponseParse ( response , cds_update_map , arena . ptr ( ) ) ;
return CdsResponseParse ( client_ , tracer_ , response , expected_cluster_names ,
cds_update_map , arena . ptr ( ) ) ;
} else if ( * type_url = = kEdsTypeUrl ) {
return EdsResponsedParse ( response , expected_eds_service_names ,
eds_update_map , arena . ptr ( ) ) ;
return EdsResponsedParse ( client_ , tracer_ , response ,
expected_eds_service_names , eds_update_map ,
arena . ptr ( ) ) ;
} else {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING (
" Unsupported ADS resource type. " ) ;
@ -980,6 +1482,121 @@ grpc_error* XdsApi::ParseAdsResponse(
namespace {
void MaybeLogLrsRequest (
XdsClient * client , TraceFlag * tracer ,
const envoy_service_load_stats_v2_LoadStatsRequest * request ) {
if ( GRPC_TRACE_FLAG_ENABLED ( * tracer ) & &
gpr_should_log ( GPR_LOG_SEVERITY_DEBUG ) ) {
// TODO(roth): When we can upgrade upb, use upb textformat code to dump
// the raw proto instead of doing this manually.
std : : vector < std : : string > fields ;
// node
const auto * node =
envoy_service_load_stats_v2_LoadStatsRequest_node ( request ) ;
if ( node ! = nullptr ) {
AddNodeLogFields ( node , & fields ) ;
}
// cluster_stats
size_t num_cluster_stats ;
const struct envoy_api_v2_endpoint_ClusterStats * const * cluster_stats =
envoy_service_load_stats_v2_LoadStatsRequest_cluster_stats (
request , & num_cluster_stats ) ;
for ( size_t i = 0 ; i < num_cluster_stats ; + + i ) {
const auto * cluster_stat = cluster_stats [ i ] ;
fields . emplace_back ( " cluster_stats { " ) ;
// cluster_name
AddStringField (
" cluster_name " ,
envoy_api_v2_endpoint_ClusterStats_cluster_name ( cluster_stat ) ,
& fields ) ;
// cluster_service_name
AddStringField (
" cluster_service_name " ,
envoy_api_v2_endpoint_ClusterStats_cluster_service_name ( cluster_stat ) ,
& fields ) ;
// upstream_locality_stats
size_t num_stats ;
const envoy_api_v2_endpoint_UpstreamLocalityStats * const * stats =
envoy_api_v2_endpoint_ClusterStats_upstream_locality_stats (
cluster_stat , & num_stats ) ;
for ( size_t j = 0 ; j < num_stats ; + + j ) {
const auto * stat = stats [ j ] ;
fields . emplace_back ( " upstream_locality_stats { " ) ;
// locality
const auto * locality =
envoy_api_v2_endpoint_UpstreamLocalityStats_locality ( stat ) ;
if ( locality ! = nullptr ) {
fields . emplace_back ( " locality { " ) ;
AddLocalityField ( 3 , locality , & fields ) ;
fields . emplace_back ( " } " ) ;
}
// total_successful_requests
fields . emplace_back ( absl : : StrCat (
" total_successful_requests: " ,
envoy_api_v2_endpoint_UpstreamLocalityStats_total_successful_requests (
stat ) ) ) ;
// total_requests_in_progress
fields . emplace_back ( absl : : StrCat (
" total_requests_in_progress: " ,
envoy_api_v2_endpoint_UpstreamLocalityStats_total_requests_in_progress (
stat ) ) ) ;
// total_error_requests
fields . emplace_back ( absl : : StrCat (
" total_error_requests: " ,
envoy_api_v2_endpoint_UpstreamLocalityStats_total_error_requests (
stat ) ) ) ;
// total_issued_requests
fields . emplace_back ( absl : : StrCat (
" total_issued_requests: " ,
envoy_api_v2_endpoint_UpstreamLocalityStats_total_issued_requests (
stat ) ) ) ;
fields . emplace_back ( " } " ) ;
}
// total_dropped_requests
fields . emplace_back ( absl : : StrCat (
" total_dropped_requests: " ,
envoy_api_v2_endpoint_ClusterStats_total_dropped_requests (
cluster_stat ) ) ) ;
// dropped_requests
size_t num_drops ;
const envoy_api_v2_endpoint_ClusterStats_DroppedRequests * const * drops =
envoy_api_v2_endpoint_ClusterStats_dropped_requests ( cluster_stat ,
& num_drops ) ;
for ( size_t j = 0 ; j < num_drops ; + + j ) {
const auto * drop = drops [ j ] ;
fields . emplace_back ( " dropped_requests { " ) ;
// category
AddStringField (
" category " ,
envoy_api_v2_endpoint_ClusterStats_DroppedRequests_category ( drop ) ,
& fields ) ;
// dropped_count
fields . emplace_back ( absl : : StrCat (
" dropped_count: " ,
envoy_api_v2_endpoint_ClusterStats_DroppedRequests_dropped_count (
drop ) ) ) ;
fields . emplace_back ( " } " ) ;
}
// load_report_interval
const auto * load_report_interval =
envoy_api_v2_endpoint_ClusterStats_load_report_interval ( cluster_stat ) ;
if ( load_report_interval ! = nullptr ) {
fields . emplace_back ( " load_report_interval { " ) ;
fields . emplace_back ( absl : : StrCat (
" seconds: " ,
google_protobuf_Duration_seconds ( load_report_interval ) ) ) ;
fields . emplace_back (
absl : : StrCat ( " nanos: " ,
google_protobuf_Duration_nanos ( load_report_interval ) ) ) ;
fields . emplace_back ( " } " ) ;
}
fields . emplace_back ( " } " ) ;
}
gpr_log ( GPR_DEBUG , " [xds_client %p] constructed LRS request: %s " , client ,
absl : : StrJoin ( fields , " \n " ) . c_str ( ) ) ;
}
}
grpc_slice SerializeLrsRequest (
const envoy_service_load_stats_v2_LoadStatsRequest * request ,
upb_arena * arena ) {
@ -1002,6 +1619,7 @@ grpc_slice XdsApi::CreateLrsInitialRequest(const std::string& server_name) {
arena . ptr ( ) ) ;
PopulateNode ( arena . ptr ( ) , node_ , build_version_ , user_agent_name_ ,
server_name , node_msg ) ;
MaybeLogLrsRequest ( client_ , tracer_ , request ) ;
return SerializeLrsRequest ( request , arena . ptr ( ) ) ;
}
@ -1114,6 +1732,7 @@ grpc_slice XdsApi::CreateLrsRequest(
google_protobuf_Duration_set_seconds ( load_report_interval , timespec . tv_sec ) ;
google_protobuf_Duration_set_nanos ( load_report_interval , timespec . tv_nsec ) ;
}
MaybeLogLrsRequest ( client_ , tracer_ , request ) ;
return SerializeLrsRequest ( request , arena . ptr ( ) ) ;
}