From 733e904491e48a8edd4e49d12288be1797d69abc Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 19 Mar 2024 15:57:41 -0700 Subject: [PATCH 01/15] [XdsClient] implement non-per-call metrics (#36020) As per gRFC A78 (https://github.com/grpc/proposal/pull/419). Closes #36020 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36020 from markdroth:non_per_call_metrics_xds c1d9b464bf6249aa8ed6bc1a46142a9b09c2bf01 PiperOrigin-RevId: 617320495 --- BUILD | 1 + CMakeLists.txt | 1 + Package.swift | 1 + build_autogenerated.yaml | 4 + gRPC-C++.podspec | 2 + gRPC-Core.podspec | 2 + grpc.gemspec | 1 + package.xml | 1 + src/core/BUILD | 1 + src/core/ext/xds/xds_client.cc | 92 +- src/core/ext/xds/xds_client.h | 27 +- src/core/ext/xds/xds_client_grpc.cc | 210 +++- src/core/ext/xds/xds_client_grpc.h | 16 +- src/core/ext/xds/xds_metrics.h | 39 + src/core/ext/xds/xds_server_config_fetcher.cc | 5 +- src/core/lib/channel/metrics.cc | 10 + src/core/lib/channel/metrics.h | 4 +- test/core/xds/BUILD | 14 + test/core/xds/xds_client_fuzzer.cc | 47 +- test/core/xds/xds_client_fuzzer.proto | 7 + test/core/xds/xds_client_test.cc | 982 +++++++++++++++++- test/core/xds/xds_client_test_peer.h | 80 ++ .../xds/xds_cluster_resource_type_test.cc | 3 +- test/core/xds/xds_common_types_test.cc | 3 +- .../xds/xds_endpoint_resource_type_test.cc | 3 +- test/core/xds/xds_http_filters_test.cc | 3 +- .../xds/xds_listener_resource_type_test.cc | 3 +- .../xds_route_config_resource_type_test.cc | 3 +- test/cpp/end2end/xds/BUILD | 1 + test/cpp/end2end/xds/xds_core_end2end_test.cc | 167 +++ tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core.internal | 1 + 32 files changed, 1636 insertions(+), 99 deletions(-) create mode 100644 src/core/ext/xds/xds_metrics.h create mode 100644 test/core/xds/xds_client_test_peer.h diff --git a/BUILD b/BUILD index 3fca11ff4c7..bf8daacde4b 100644 --- a/BUILD +++ b/BUILD @@ -4274,6 +4274,7 @@ grpc_cc_library( "//src/core:ext/xds/xds_channel_args.h", "//src/core:ext/xds/xds_client.h", "//src/core:ext/xds/xds_client_stats.h", + "//src/core:ext/xds/xds_metrics.h", "//src/core:ext/xds/xds_resource_type.h", "//src/core:ext/xds/xds_resource_type_impl.h", "//src/core:ext/xds/xds_transport.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ef168cffd9..e022789d29a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33582,6 +33582,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/string.grpc.pb.h + test/core/util/fake_stats_plugin.cc test/cpp/end2end/test_service_impl.cc test/cpp/end2end/xds/xds_core_end2end_test.cc test/cpp/end2end/xds/xds_end2end_test_lib.cc diff --git a/Package.swift b/Package.swift index 0465d912aa5..f7b1930f099 100644 --- a/Package.swift +++ b/Package.swift @@ -1110,6 +1110,7 @@ let package = Package( "src/core/ext/xds/xds_lb_policy_registry.h", "src/core/ext/xds/xds_listener.cc", "src/core/ext/xds/xds_listener.h", + "src/core/ext/xds/xds_metrics.h", "src/core/ext/xds/xds_resource_type.h", "src/core/ext/xds/xds_resource_type_impl.h", "src/core/ext/xds/xds_route_config.cc", diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index adb59a57a16..973ec51a9ce 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -800,6 +800,7 @@ libs: - src/core/ext/xds/xds_http_stateful_session_filter.h - src/core/ext/xds/xds_lb_policy_registry.h - src/core/ext/xds/xds_listener.h + - src/core/ext/xds/xds_metrics.h - src/core/ext/xds/xds_resource_type.h - src/core/ext/xds/xds_resource_type_impl.h - src/core/ext/xds/xds_route_config.h @@ -20211,6 +20212,7 @@ targets: language: c++ headers: - test/core/util/scoped_env_var.h + - test/core/xds/xds_client_test_peer.h - test/core/xds/xds_transport_fake.h src: - src/proto/grpc/testing/xds/v3/base.proto @@ -20417,6 +20419,7 @@ targets: run: false language: c++ headers: + - test/core/util/fake_stats_plugin.h - test/core/util/scoped_env_var.h - test/cpp/end2end/counted_service.h - test/cpp/end2end/test_service_impl.h @@ -20456,6 +20459,7 @@ targets: - src/proto/grpc/testing/xds/v3/route.proto - src/proto/grpc/testing/xds/v3/router.proto - src/proto/grpc/testing/xds/v3/string.proto + - test/core/util/fake_stats_plugin.cc - test/cpp/end2end/test_service_impl.cc - test/cpp/end2end/xds/xds_core_end2end_test.cc - test/cpp/end2end/xds/xds_end2end_test_lib.cc diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index b8e6e3d892b..e4e0db337dc 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -881,6 +881,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_http_stateful_session_filter.h', 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.h', + 'src/core/ext/xds/xds_metrics.h', 'src/core/ext/xds/xds_resource_type.h', 'src/core/ext/xds/xds_resource_type_impl.h', 'src/core/ext/xds/xds_route_config.h', @@ -2145,6 +2146,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_http_stateful_session_filter.h', 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.h', + 'src/core/ext/xds/xds_metrics.h', 'src/core/ext/xds/xds_resource_type.h', 'src/core/ext/xds/xds_resource_type_impl.h', 'src/core/ext/xds/xds_route_config.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 67f256a60e3..73c31d9c6ed 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1226,6 +1226,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.cc', 'src/core/ext/xds/xds_listener.h', + 'src/core/ext/xds/xds_metrics.h', 'src/core/ext/xds/xds_resource_type.h', 'src/core/ext/xds/xds_resource_type_impl.h', 'src/core/ext/xds/xds_route_config.cc', @@ -2927,6 +2928,7 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_http_stateful_session_filter.h', 'src/core/ext/xds/xds_lb_policy_registry.h', 'src/core/ext/xds/xds_listener.h', + 'src/core/ext/xds/xds_metrics.h', 'src/core/ext/xds/xds_resource_type.h', 'src/core/ext/xds/xds_resource_type_impl.h', 'src/core/ext/xds/xds_route_config.h', diff --git a/grpc.gemspec b/grpc.gemspec index 1016f7ed774..4c7b75d8e43 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -1116,6 +1116,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/xds/xds_lb_policy_registry.h ) s.files += %w( src/core/ext/xds/xds_listener.cc ) s.files += %w( src/core/ext/xds/xds_listener.h ) + s.files += %w( src/core/ext/xds/xds_metrics.h ) s.files += %w( src/core/ext/xds/xds_resource_type.h ) s.files += %w( src/core/ext/xds/xds_resource_type_impl.h ) s.files += %w( src/core/ext/xds/xds_route_config.cc ) diff --git a/package.xml b/package.xml index c31c71f176b..834f8b1aa74 100644 --- a/package.xml +++ b/package.xml @@ -1098,6 +1098,7 @@ + diff --git a/src/core/BUILD b/src/core/BUILD index 857484df4f1..bbc92c0bb8e 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -5060,6 +5060,7 @@ grpc_cc_library( "load_file", "match", "metadata_batch", + "metrics", "pollset_set", "protobuf_any_upb", "protobuf_duration_upb", diff --git a/src/core/ext/xds/xds_client.cc b/src/core/ext/xds/xds_client.cc index c9c65ab3e51..a30c6ceafb0 100644 --- a/src/core/ext/xds/xds_client.cc +++ b/src/core/ext/xds/xds_client.cc @@ -150,7 +150,8 @@ class XdsClient::XdsChannel::AdsCall : public InternallyRefCounted { std::vector errors; std::map> resources_seen; - bool have_valid_resources = false; + uint64_t num_valid_resources = 0; + uint64_t num_invalid_resources = 0; RefCountedPtr read_delay_handle; }; @@ -783,6 +784,7 @@ void XdsClient::XdsChannel::AdsCall::AdsResponseParser::ParseResource( result_.errors.emplace_back( absl::StrCat(error_prefix, "incorrect resource type \"", type_url, "\" (should be \"", result_.type_url, "\")")); + ++result_.num_invalid_resources; return; } // Parse the resource. @@ -803,6 +805,7 @@ void XdsClient::XdsChannel::AdsCall::AdsResponseParser::ParseResource( // there's nothing more we can do here. result_.errors.emplace_back(absl::StrCat( error_prefix, decode_result.resource.status().ToString())); + ++result_.num_invalid_resources; return; } } @@ -818,6 +821,7 @@ void XdsClient::XdsChannel::AdsCall::AdsResponseParser::ParseResource( if (!parsed_resource_name.ok()) { result_.errors.emplace_back( absl::StrCat(error_prefix, "Cannot parse xDS resource name")); + ++result_.num_invalid_resources; return; } // Cancel resource-does-not-exist timer, if needed. @@ -877,10 +881,11 @@ void XdsClient::XdsChannel::AdsCall::AdsResponseParser::ParseResource( result_.read_delay_handle); UpdateResourceMetadataNacked(result_.version, decode_status.ToString(), update_time_, &resource_state.meta); + ++result_.num_invalid_resources; return; } // Resource is valid. - result_.have_valid_resources = true; + ++result_.num_valid_resources; // If it didn't change, ignore it. if (resource_state.resource != nullptr && result_.type->ResourcesEqual(resource_state.resource.get(), @@ -914,6 +919,7 @@ void XdsClient::XdsChannel::AdsCall::AdsResponseParser:: ResourceWrapperParsingFailed(size_t idx, absl::string_view message) { result_.errors.emplace_back( absl::StrCat("resource index ", idx, ": ", message)); + ++result_.num_invalid_resources; } // @@ -1157,13 +1163,19 @@ void XdsClient::XdsChannel::AdsCall::OnRecvMessage(absl::string_view payload) { } } // If we had valid resources or the update was empty, update the version. - if (result.have_valid_resources || result.errors.empty()) { + if (result.num_valid_resources > 0 || result.errors.empty()) { xds_channel()->resource_type_version_map_[result.type] = std::move(result.version); } // Send ACK or NACK. SendMessageLocked(result.type); } + // Update metrics. + if (xds_client()->metrics_reporter_ != nullptr) { + xds_client()->metrics_reporter_->ReportResourceUpdates( + xds_channel()->server_.server_uri(), result.type_url, + result.num_valid_resources, result.num_invalid_resources); + } } xds_client()->work_serializer_.DrainQueue(); } @@ -1484,10 +1496,13 @@ bool XdsClient::XdsChannel::LrsCall::IsCurrentCallOnChannel() const { // XdsClient // +constexpr absl::string_view XdsClient::kOldStyleAuthority; + XdsClient::XdsClient( std::unique_ptr bootstrap, OrphanablePtr transport_factory, std::shared_ptr engine, + std::unique_ptr metrics_reporter, std::string user_agent_name, std::string user_agent_version, Duration resource_request_timeout) : DualRefCounted( @@ -1500,7 +1515,8 @@ XdsClient::XdsClient( api_(this, &grpc_xds_client_trace, bootstrap_->node(), &def_pool_, std::move(user_agent_name), std::move(user_agent_version)), work_serializer_(engine), - engine_(std::move(engine)) { + engine_(std::move(engine)), + metrics_reporter_(std::move(metrics_reporter)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, "[xds_client %p] creating xds client", this); } @@ -1575,12 +1591,12 @@ void XdsClient::WatchResource(const XdsResourceType* type, } // Find server to use. const XdsBootstrap::XdsServer* xds_server = nullptr; - absl::string_view authority_name = resource_name->authority; - if (absl::ConsumePrefix(&authority_name, "xdstp:")) { - auto* authority = bootstrap_->LookupAuthority(std::string(authority_name)); + if (resource_name->authority != kOldStyleAuthority) { + auto* authority = + bootstrap_->LookupAuthority(std::string(resource_name->authority)); if (authority == nullptr) { fail(absl::UnavailableError( - absl::StrCat("authority \"", authority_name, + absl::StrCat("authority \"", resource_name->authority, "\" not present in bootstrap config"))); return; } @@ -1738,10 +1754,11 @@ const XdsResourceType* XdsClient::GetResourceTypeLocked( absl::StatusOr XdsClient::ParseXdsResourceName( absl::string_view name, const XdsResourceType* type) { // Old-style names use the empty string for authority. - // authority is prefixed with "old:" to indicate that it's an old-style - // name. + // authority is set to kOldStyleAuthority to indicate that it's an + // old-style name. if (!xds_federation_enabled_ || !absl::StartsWith(name, "xdstp:")) { - return XdsResourceName{"old:", {std::string(name), {}}}; + return XdsResourceName{std::string(kOldStyleAuthority), + {std::string(name), {}}}; } // New style name. Parse URI. auto uri = URI::Parse(name); @@ -1760,14 +1777,14 @@ absl::StatusOr XdsClient::ParseXdsResourceName( URI::QueryParam{std::string(p.first), std::string(p.second)}); } return XdsResourceName{ - absl::StrCat("xdstp:", uri->authority()), + uri->authority(), {std::string(path_parts.second), std::move(query_params)}}; } std::string XdsClient::ConstructFullXdsResourceName( absl::string_view authority, absl::string_view resource_type, const XdsResourceKey& key) { - if (absl::ConsumePrefix(&authority, "xdstp:")) { + if (authority != kOldStyleAuthority) { auto uri = URI::Create("xdstp", std::string(authority), absl::StrCat("/", resource_type, "/", key.id), key.query_params, /*fragment=*/""); @@ -2121,4 +2138,53 @@ void XdsClient::DumpClientConfig( } } +namespace { + +absl::string_view CacheStateForEntry(const XdsApi::ResourceMetadata& metadata, + bool resource_cached) { + switch (metadata.client_status) { + case XdsApi::ResourceMetadata::REQUESTED: + return "requested"; + case XdsApi::ResourceMetadata::DOES_NOT_EXIST: + return "does_not_exist"; + case XdsApi::ResourceMetadata::ACKED: + return "acked"; + case XdsApi::ResourceMetadata::NACKED: + return resource_cached ? "nacked_but_cached" : "nacked"; + } + Crash("unknown resource state"); +} + +} // namespace + +void XdsClient::ReportResourceCounts( + absl::FunctionRef func) { + ResourceCountLabels labels; + for (const auto& a : authority_state_map_) { // authority + labels.xds_authority = a.first; + for (const auto& t : a.second.resource_map) { // type + labels.resource_type = t.first->type_url(); + // Count the number of entries in each state. + std::map counts; + for (const auto& r : t.second) { // resource id + absl::string_view cache_state = + CacheStateForEntry(r.second.meta, r.second.resource != nullptr); + ++counts[cache_state]; + } + // Report the count for each state. + for (const auto& c : counts) { + labels.cache_state = c.first; + func(labels, c.second); + } + } + } +} + +void XdsClient::ReportServerConnections( + absl::FunctionRef func) { + for (const auto& p : xds_channel_map_) { + func(p.second->server_uri(), p.second->status().ok()); + } +} + } // namespace grpc_core diff --git a/src/core/ext/xds/xds_client.h b/src/core/ext/xds/xds_client.h index 038abfe5f29..a9ee6573e82 100644 --- a/src/core/ext/xds/xds_client.h +++ b/src/core/ext/xds/xds_client.h @@ -37,6 +37,7 @@ #include "src/core/ext/xds/xds_api.h" #include "src/core/ext/xds/xds_bootstrap.h" #include "src/core/ext/xds/xds_client_stats.h" +#include "src/core/ext/xds/xds_metrics.h" #include "src/core/ext/xds/xds_resource_type.h" #include "src/core/ext/xds/xds_transport.h" #include "src/core/lib/debug/trace.h" @@ -60,6 +61,9 @@ extern TraceFlag grpc_xds_client_refcount_trace; class XdsClient : public DualRefCounted { public: + // The authority reported for old-style (non-xdstp) resource names. + static constexpr absl::string_view kOldStyleAuthority = "#old"; + class ReadDelayHandle : public RefCounted { public: static RefCountedPtr NoWait() { return nullptr; } @@ -87,6 +91,7 @@ class XdsClient : public DualRefCounted { std::unique_ptr bootstrap, OrphanablePtr transport_factory, std::shared_ptr engine, + std::unique_ptr metrics_reporter, std::string user_agent_name, std::string user_agent_version, Duration resource_request_timeout = Duration::Seconds(15)); ~XdsClient() override; @@ -156,6 +161,8 @@ class XdsClient : public DualRefCounted { } protected: + Mutex* mu() ABSL_LOCK_RETURNED(&mu_) { return &mu_; } + // Dumps the active xDS config to the provided // envoy.service.status.v3.ClientConfig message including the config status // (e.g., CLIENT_REQUESTED, CLIENT_ACKED, CLIENT_NACKED). @@ -163,7 +170,22 @@ class XdsClient : public DualRefCounted { envoy_service_status_v3_ClientConfig* client_config) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_); - Mutex* mu() ABSL_LOCK_RETURNED(&mu_) { return &mu_; } + // Invokes func once for each combination of labels to report the + // resource count for those labels. + struct ResourceCountLabels { + absl::string_view xds_authority; + absl::string_view resource_type; + absl::string_view cache_state; + }; + void ReportResourceCounts( + absl::FunctionRef func) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_); + + // Invokes func once for each xDS server to report whether the + // connection to that server is working. + void ReportServerConnections( + absl::FunctionRef func) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_); private: friend testing::XdsClientTestPeer; @@ -221,6 +243,8 @@ class XdsClient : public DualRefCounted { bool delay_unsubscription) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + absl::string_view server_uri() const { return server_.server_uri(); } + private: void OnConnectivityFailure(absl::Status status); @@ -327,6 +351,7 @@ class XdsClient : public DualRefCounted { XdsApi api_; WorkSerializer work_serializer_; std::shared_ptr engine_; + std::unique_ptr metrics_reporter_; Mutex mu_; diff --git a/src/core/ext/xds/xds_client_grpc.cc b/src/core/ext/xds/xds_client_grpc.cc index d5e4447cc02..cbfee8e71fd 100644 --- a/src/core/ext/xds/xds_client_grpc.cc +++ b/src/core/ext/xds/xds_client_grpc.cc @@ -49,6 +49,7 @@ #include "src/core/ext/xds/xds_transport.h" #include "src/core/ext/xds/xds_transport_grpc.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/metrics.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/event_engine/default_event_engine.h" #include "src/core/lib/gprpp/debug_location.h" @@ -64,8 +65,6 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/error_utils.h" -namespace grpc_core { - // If gRPC is built with -DGRPC_XDS_USER_AGENT_NAME_SUFFIX="...", that string // will be appended to the user agent name reported to the xDS server. #ifdef GRPC_XDS_USER_AGENT_NAME_SUFFIX @@ -84,10 +83,90 @@ namespace grpc_core { #define GRPC_XDS_USER_AGENT_VERSION_SUFFIX_STRING "" #endif +namespace grpc_core { + +namespace { + +// Metric labels. +constexpr absl::string_view kMetricLabelXdsServer = "grpc.xds.server"; +constexpr absl::string_view kMetricLabelXdsAuthority = "grpc.xds.authority"; +constexpr absl::string_view kMetricLabelXdsResourceType = + "grpc.xds.resource_type"; +constexpr absl::string_view kMetricLabelXdsCacheState = "grpc.xds.cache_state"; + +const auto kMetricResourceUpdatesValid = + GlobalInstrumentsRegistry::RegisterUInt64Counter( + "grpc.xds_client.resource_updates_valid", + "EXPERIMENTAL. A counter of resources received that were considered " + "valid. The counter will be incremented even for resources that " + "have not changed.", + "{resource}", + {kMetricLabelTarget, kMetricLabelXdsServer, + kMetricLabelXdsResourceType}, + {}, false); + +const auto kMetricResourceUpdatesInvalid = + GlobalInstrumentsRegistry::RegisterUInt64Counter( + "grpc.xds_client.resource_updates_invalid", + "EXPERIMENTAL. A counter of resources received that were considered " + "invalid.", + "{resource}", + {kMetricLabelTarget, kMetricLabelXdsServer, + kMetricLabelXdsResourceType}, + {}, false); + +const auto kMetricConnected = + GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge( + "grpc.xds_client.connected", + "EXPERIMENTAL. Whether or not the xDS client currently has a " + "working ADS stream to the xDS server. For a given server, this " + "will be set to 0 when we have a connectivity failure or when the " + "ADS stream fails without seeing a response message, as per gRFC " + "A57. It will be set to 1 when we receive the first response on " + "an ADS stream.", + "{bool}", {kMetricLabelTarget, kMetricLabelXdsServer}, {}, false); + +const auto kMetricResources = + GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge( + "grpc.xds_client.resources", "EXPERIMENTAL. Number of xDS resources.", + "{resource}", + {kMetricLabelTarget, kMetricLabelXdsAuthority, + kMetricLabelXdsResourceType, kMetricLabelXdsCacheState}, + {}, false); + +} // namespace + +// +// GrpcXdsClient::MetricsReporter +// + +class GrpcXdsClient::MetricsReporter : public XdsMetricsReporter { + public: + explicit MetricsReporter(GrpcXdsClient& xds_client) + : xds_client_(xds_client) {} + + void ReportResourceUpdates(absl::string_view xds_server, + absl::string_view resource_type, + uint64_t num_valid_resources, + uint64_t num_invalid_resources) override { + xds_client_.stats_plugin_group_.AddCounter( + kMetricResourceUpdatesValid, num_valid_resources, + {xds_client_.key_, xds_server, resource_type}, {}); + xds_client_.stats_plugin_group_.AddCounter( + kMetricResourceUpdatesInvalid, num_invalid_resources, + {xds_client_.key_, xds_server, resource_type}, {}); + } + + private: + GrpcXdsClient& xds_client_; +}; + // // GrpcXdsClient // +constexpr absl::string_view GrpcXdsClient::kServerKey; + namespace { Mutex* g_mu = new Mutex; @@ -97,10 +176,6 @@ NoDestruct> g_xds_client_map ABSL_GUARDED_BY(*g_mu); char* g_fallback_bootstrap_config ABSL_GUARDED_BY(*g_mu) = nullptr; -} // namespace - -namespace { - absl::StatusOr GetBootstrapContents(const char* fallback_config) { // First, try GRPC_XDS_BOOTSTRAP env var. auto path = GetEnv("GRPC_XDS_BOOTSTRAP"); @@ -138,19 +213,6 @@ absl::StatusOr GetBootstrapContents(const char* fallback_config) { "not defined"); } -std::vector> GetAllXdsClients() { - MutexLock lock(g_mu); - std::vector> xds_clients; - for (const auto& key_client : *g_xds_client_map) { - auto xds_client = - key_client.second->RefIfNonZero(DEBUG_LOCATION, "DumpAllClientConfigs"); - if (xds_client != nullptr) { - xds_clients.emplace_back(xds_client.TakeAsSubclass()); - } - } - return xds_clients; -} - } // namespace absl::StatusOr> GrpcXdsClient::GetOrCreate( @@ -201,36 +263,20 @@ absl::StatusOr> GrpcXdsClient::GetOrCreate( return xds_client; } -// ABSL_NO_THREAD_SAFETY_ANALYSIS because we have to manually manage locks for -// individual XdsClients and compiler struggles with checking the validity -grpc_slice GrpcXdsClient::DumpAllClientConfigs() - ABSL_NO_THREAD_SAFETY_ANALYSIS { - auto xds_clients = GetAllXdsClients(); - upb::Arena arena; - // Contains strings that should survive till serialization - std::set string_pool; - auto response = envoy_service_status_v3_ClientStatusResponse_new(arena.ptr()); - // We lock each XdsClient mutex till we are done with the serialization to - // ensure that all data referenced from the UPB proto message stays alive. - for (const auto& xds_client : xds_clients) { - auto client_config = - envoy_service_status_v3_ClientStatusResponse_add_config(response, - arena.ptr()); - xds_client->mu()->Lock(); - xds_client->DumpClientConfig(&string_pool, arena.ptr(), client_config); - envoy_service_status_v3_ClientConfig_set_client_scope( - client_config, StdStringToUpbString(xds_client->key())); - } - // Serialize the upb message to bytes - size_t output_length; - char* output = envoy_service_status_v3_ClientStatusResponse_serialize( - response, arena.ptr(), &output_length); - for (const auto& xds_client : xds_clients) { - xds_client->mu()->Unlock(); +namespace { + +GlobalStatsPluginRegistry::StatsPluginGroup GetStatsPluginGroupForKey( + absl::string_view key) { + if (key == GrpcXdsClient::kServerKey) { + return GlobalStatsPluginRegistry::GetAllStatsPlugins(); } - return grpc_slice_from_cpp_string(std::string(output, output_length)); + // TODO(roth): How do we set the authority here? + StatsPlugin::ChannelScope scope(key, ""); + return GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope); } +} // namespace + GrpcXdsClient::GrpcXdsClient( absl::string_view key, std::unique_ptr bootstrap, const ChannelArgs& args, @@ -238,6 +284,7 @@ GrpcXdsClient::GrpcXdsClient( : XdsClient( std::move(bootstrap), std::move(transport_factory), grpc_event_engine::experimental::GetDefaultEventEngine(), + std::make_unique(*this), absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING, GRPC_XDS_USER_AGENT_NAME_SUFFIX_STRING), absl::StrCat("C-core ", grpc_version_string(), @@ -250,15 +297,22 @@ GrpcXdsClient::GrpcXdsClient( key_(key), certificate_provider_store_(MakeOrphanable( static_cast(this->bootstrap()) - .certificate_providers())) {} + .certificate_providers())), + stats_plugin_group_(GetStatsPluginGroupForKey(key_)), + registered_metric_callback_(stats_plugin_group_.RegisterCallback( + [this](CallbackMetricReporter& reporter) { + ReportCallbackMetrics(reporter); + }, + {kMetricConnected, kMetricResources})) {} void GrpcXdsClient::Orphan() { + registered_metric_callback_.reset(); + XdsClient::Orphan(); MutexLock lock(g_mu); auto it = g_xds_client_map->find(key_); if (it != g_xds_client_map->end() && it->second == this) { g_xds_client_map->erase(it); } - XdsClient::Orphan(); } grpc_pollset_set* GrpcXdsClient::interested_parties() const { @@ -266,6 +320,66 @@ grpc_pollset_set* GrpcXdsClient::interested_parties() const { ->interested_parties(); } +namespace { + +std::vector> GetAllXdsClients() { + MutexLock lock(g_mu); + std::vector> xds_clients; + for (const auto& key_client : *g_xds_client_map) { + auto xds_client = + key_client.second->RefIfNonZero(DEBUG_LOCATION, "DumpAllClientConfigs"); + if (xds_client != nullptr) { + xds_clients.emplace_back(xds_client.TakeAsSubclass()); + } + } + return xds_clients; +} + +} // namespace + +// ABSL_NO_THREAD_SAFETY_ANALYSIS because we have to manually manage locks for +// individual XdsClients and compiler struggles with checking the validity +grpc_slice GrpcXdsClient::DumpAllClientConfigs() + ABSL_NO_THREAD_SAFETY_ANALYSIS { + auto xds_clients = GetAllXdsClients(); + upb::Arena arena; + // Contains strings that should survive till serialization + std::set string_pool; + auto response = envoy_service_status_v3_ClientStatusResponse_new(arena.ptr()); + // We lock each XdsClient mutex till we are done with the serialization to + // ensure that all data referenced from the UPB proto message stays alive. + for (const auto& xds_client : xds_clients) { + auto client_config = + envoy_service_status_v3_ClientStatusResponse_add_config(response, + arena.ptr()); + xds_client->mu()->Lock(); + xds_client->DumpClientConfig(&string_pool, arena.ptr(), client_config); + envoy_service_status_v3_ClientConfig_set_client_scope( + client_config, StdStringToUpbString(xds_client->key())); + } + // Serialize the upb message to bytes + size_t output_length; + char* output = envoy_service_status_v3_ClientStatusResponse_serialize( + response, arena.ptr(), &output_length); + for (const auto& xds_client : xds_clients) { + xds_client->mu()->Unlock(); + } + return grpc_slice_from_cpp_string(std::string(output, output_length)); +} + +void GrpcXdsClient::ReportCallbackMetrics(CallbackMetricReporter& reporter) { + MutexLock lock(mu()); + ReportResourceCounts([&](const ResourceCountLabels& labels, uint64_t count) { + reporter.Report( + kMetricResources, count, + {key_, labels.xds_authority, labels.resource_type, labels.cache_state}, + {}); + }); + ReportServerConnections([&](absl::string_view xds_server, bool connected) { + reporter.Report(kMetricConnected, connected, {key_, xds_server}, {}); + }); +} + namespace internal { void SetXdsChannelArgsForTest(grpc_channel_args* args) { diff --git a/src/core/ext/xds/xds_client_grpc.h b/src/core/ext/xds/xds_client_grpc.h index 72df525ab6e..ba6377a5c2d 100644 --- a/src/core/ext/xds/xds_client_grpc.h +++ b/src/core/ext/xds/xds_client_grpc.h @@ -31,6 +31,7 @@ #include "src/core/ext/xds/xds_client.h" #include "src/core/ext/xds/xds_transport.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/metrics.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" @@ -41,13 +42,13 @@ namespace grpc_core { class GrpcXdsClient : public XdsClient { public: + // The key to pass to GetOrCreate() for gRPC servers. + static constexpr absl::string_view kServerKey = "#server"; + // Factory function to get or create the global XdsClient instance. static absl::StatusOr> GetOrCreate( absl::string_view key, const ChannelArgs& args, const char* reason); - // Builds ClientStatusResponse containing all resources from all XdsClients - static grpc_slice DumpAllClientConfigs(); - // Do not instantiate directly -- use GetOrCreate() instead. // TODO(roth): The transport factory is injectable here to support // tests that want to use a fake transport factory with code that @@ -83,9 +84,18 @@ class GrpcXdsClient : public XdsClient { absl::string_view key() const { return key_; } + // Builds ClientStatusResponse containing all resources from all XdsClients + static grpc_slice DumpAllClientConfigs(); + private: + class MetricsReporter; + + void ReportCallbackMetrics(CallbackMetricReporter& reporter); + std::string key_; OrphanablePtr certificate_provider_store_; + GlobalStatsPluginRegistry::StatsPluginGroup stats_plugin_group_; + std::unique_ptr registered_metric_callback_; }; namespace internal { diff --git a/src/core/ext/xds/xds_metrics.h b/src/core/ext/xds/xds_metrics.h new file mode 100644 index 00000000000..f30e9dbe962 --- /dev/null +++ b/src/core/ext/xds/xds_metrics.h @@ -0,0 +1,39 @@ +// +// Copyright 2024 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. +// + +#ifndef GRPC_SRC_CORE_EXT_XDS_XDS_METRICS_H +#define GRPC_SRC_CORE_EXT_XDS_XDS_METRICS_H + +#include + +#include "absl/strings/string_view.h" + +namespace grpc_core { + +// An interface for XdsClient to report metrics. +class XdsMetricsReporter { + public: + virtual ~XdsMetricsReporter() = default; + + virtual void ReportResourceUpdates(absl::string_view xds_server, + absl::string_view resource_type, + uint64_t num_valid, + uint64_t num_invalid) = 0; +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_XDS_XDS_METRICS_H diff --git a/src/core/ext/xds/xds_server_config_fetcher.cc b/src/core/ext/xds/xds_server_config_fetcher.cc index 6e406843a64..07747f54d50 100644 --- a/src/core/ext/xds/xds_server_config_fetcher.cc +++ b/src/core/ext/xds/xds_server_config_fetcher.cc @@ -94,8 +94,6 @@ namespace { using ReadDelayHandle = XdsClient::ReadDelayHandle; -constexpr absl::string_view kServerXdsClientKey = "#server"; - TraceFlag grpc_xds_server_config_fetcher_trace(false, "xds_server_config_fetcher"); @@ -1374,7 +1372,8 @@ grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create( "update=%p, user_data=%p}, args=%p)", 3, (notifier.on_serving_status_update, notifier.user_data, args)); auto xds_client = grpc_core::GrpcXdsClient::GetOrCreate( - grpc_core::kServerXdsClientKey, channel_args, "XdsServerConfigFetcher"); + grpc_core::GrpcXdsClient::kServerKey, channel_args, + "XdsServerConfigFetcher"); if (!xds_client.ok()) { gpr_log(GPR_ERROR, "Failed to create xds client: %s", xds_client.status().ToString().c_str()); diff --git a/src/core/lib/channel/metrics.cc b/src/core/lib/channel/metrics.cc index 5a038db187b..813eeb02cd4 100644 --- a/src/core/lib/channel/metrics.cc +++ b/src/core/lib/channel/metrics.cc @@ -311,6 +311,16 @@ void GlobalStatsPluginRegistry::RegisterStatsPlugin( plugins_->push_back(std::move(plugin)); } +GlobalStatsPluginRegistry::StatsPluginGroup +GlobalStatsPluginRegistry::GetAllStatsPlugins() { + MutexLock lock(&*mutex_); + StatsPluginGroup group; + for (const auto& plugin : *plugins_) { + group.push_back(plugin); + } + return group; +} + GlobalStatsPluginRegistry::StatsPluginGroup GlobalStatsPluginRegistry::GetStatsPluginsForChannel( const StatsPlugin::ChannelScope& scope) { diff --git a/src/core/lib/channel/metrics.h b/src/core/lib/channel/metrics.h index a93f0037cb3..c4315e721ee 100644 --- a/src/core/lib/channel/metrics.h +++ b/src/core/lib/channel/metrics.h @@ -310,8 +310,10 @@ class GlobalStatsPluginRegistry { }; static void RegisterStatsPlugin(std::shared_ptr plugin); - // The following two functions can be invoked to get a StatsPluginGroup for + + // The following functions can be invoked to get a StatsPluginGroup for // a specified scope. + static StatsPluginGroup GetAllStatsPlugins(); static StatsPluginGroup GetStatsPluginsForChannel( const StatsPlugin::ChannelScope& scope); // TODO(yijiem): Implement this. diff --git a/test/core/xds/BUILD b/test/core/xds/BUILD index 26030f839f5..581db547721 100644 --- a/test/core/xds/BUILD +++ b/test/core/xds/BUILD @@ -162,6 +162,18 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "xds_client_test_peer", + hdrs = ["xds_client_test_peer.h"], + external_deps = [ + "absl/functional:function_ref", + ], + language = "C++", + deps = [ + "//:xds_client", + ], +) + grpc_cc_test( name = "xds_client_test", srcs = ["xds_client_test.cc"], @@ -171,6 +183,7 @@ grpc_cc_test( uses_event_engine = True, uses_polling = False, deps = [ + ":xds_client_test_peer", ":xds_transport_fake", "//:xds_client", "//src/proto/grpc/testing/xds/v3:discovery_proto", @@ -192,6 +205,7 @@ grpc_proto_fuzzer( uses_event_engine = False, uses_polling = False, deps = [ + ":xds_client_test_peer", ":xds_transport_fake", "//src/core:grpc_xds_client", "//test/core/util:grpc_test_util", diff --git a/test/core/xds/xds_client_fuzzer.cc b/test/core/xds/xds_client_fuzzer.cc index 4d6994a1381..5b9dc709969 100644 --- a/test/core/xds/xds_client_fuzzer.cc +++ b/test/core/xds/xds_client_fuzzer.cc @@ -43,30 +43,11 @@ #include "src/libfuzzer/libfuzzer_macro.h" #include "src/proto/grpc/testing/xds/v3/discovery.pb.h" #include "test/core/xds/xds_client_fuzzer.pb.h" +#include "test/core/xds/xds_client_test_peer.h" #include "test/core/xds/xds_transport_fake.h" namespace grpc_core { -namespace testing { - -class XdsClientTestPeer { - public: - explicit XdsClientTestPeer(XdsClient* xds_client) : xds_client_(xds_client) {} - - void TestDumpClientConfig() { - upb::Arena arena; - auto client_config = envoy_service_status_v3_ClientConfig_new(arena.ptr()); - std::set string_pool; - MutexLock lock(xds_client_->mu()); - xds_client_->DumpClientConfig(&string_pool, arena.ptr(), client_config); - } - - private: - XdsClient* xds_client_; -}; - -} // namespace testing - class Fuzzer { public: explicit Fuzzer(absl::string_view bootstrap_json) { @@ -84,8 +65,8 @@ class Fuzzer { transport_factory_ = transport_factory.get(); xds_client_ = MakeRefCounted( std::move(*bootstrap), std::move(transport_factory), - grpc_event_engine::experimental::GetDefaultEventEngine(), "foo agent", - "foo version"); + grpc_event_engine::experimental::GetDefaultEventEngine(), + /*metrics_reporter=*/nullptr, "foo agent", "foo version"); } void Act(const xds_client_fuzzer::Action& action) { @@ -135,6 +116,28 @@ class Fuzzer { case xds_client_fuzzer::Action::kDumpCsdsData: testing::XdsClientTestPeer(xds_client_.get()).TestDumpClientConfig(); break; + case xds_client_fuzzer::Action::kReportResourceCounts: + testing::XdsClientTestPeer(xds_client_.get()) + .TestReportResourceCounts( + [](const testing::XdsClientTestPeer::ResourceCountLabels& + labels, + uint64_t count) { + gpr_log(GPR_INFO, + "xds_authority=\"%s\", resource_type=\"%s\", " + "cache_state=\"%s\" count=%" PRIu64, + std::string(labels.xds_authority).c_str(), + std::string(labels.resource_type).c_str(), + std::string(labels.cache_state).c_str(), count); + }); + break; + case xds_client_fuzzer::Action::kReportServerConnections: + testing::XdsClientTestPeer(xds_client_.get()) + .TestReportServerConnections( + [](absl::string_view xds_server, bool connected) { + gpr_log(GPR_INFO, "xds_server=\"%s\" connected=%d", + std::string(xds_server).c_str(), connected); + }); + break; case xds_client_fuzzer::Action::kTriggerConnectionFailure: TriggerConnectionFailure( action.trigger_connection_failure().authority(), diff --git a/test/core/xds/xds_client_fuzzer.proto b/test/core/xds/xds_client_fuzzer.proto index 2738e76b3d4..6d1274eb9cc 100644 --- a/test/core/xds/xds_client_fuzzer.proto +++ b/test/core/xds/xds_client_fuzzer.proto @@ -59,6 +59,10 @@ message StopWatch { message DumpCsdsData {} +message ReportResourceCounts {} + +message ReportServerConnections {} + // // interactions with fake transport // @@ -96,12 +100,15 @@ message SendStatusToClient { Status status = 2; } +// Next free field: 10 message Action { oneof action_type { // interactions with XdsClient API StartWatch start_watch = 1; StopWatch stop_watch = 2; DumpCsdsData dump_csds_data = 3; + ReportResourceCounts report_resource_counts = 8; + ReportServerConnections report_server_connections = 9; // interactions with fake transport TriggerConnectionFailure trigger_connection_failure = 4; ReadMessageFromClient read_message_from_client = 5; diff --git a/test/core/xds/xds_client_test.cc b/test/core/xds/xds_client_test.cc index 741e2022362..b6036e35e96 100644 --- a/test/core/xds/xds_client_test.cc +++ b/test/core/xds/xds_client_test.cc @@ -59,6 +59,7 @@ #include "src/proto/grpc/testing/xds/v3/discovery.pb.h" #include "test/core/util/scoped_env_var.h" #include "test/core/util/test_config.h" +#include "test/core/xds/xds_client_test_peer.h" #include "test/core/xds/xds_transport_fake.h" // IWYU pragma: no_include @@ -594,6 +595,65 @@ class XdsClientTest : public ::testing::Test { DiscoveryResponse response_; }; + class MetricsReporter : public XdsMetricsReporter { + public: + using ResourceUpdateMap = std::map< + std::pair, + uint64_t>; + + const ResourceUpdateMap& resource_updates_valid() const { + return resource_updates_valid_; + } + const ResourceUpdateMap& resource_updates_invalid() const { + return resource_updates_invalid_; + } + + private: + void ReportResourceUpdates(absl::string_view xds_server, + absl::string_view resource_type, + uint64_t num_resources_valid, + uint64_t num_resources_invalid) override { + auto key = + std::make_pair(std::string(xds_server), std::string(resource_type)); + if (num_resources_valid > 0) { + resource_updates_valid_[key] += num_resources_valid; + } + if (num_resources_invalid > 0) { + resource_updates_invalid_[key] += num_resources_invalid; + } + } + + ResourceUpdateMap resource_updates_valid_; + ResourceUpdateMap resource_updates_invalid_; + }; + + using ResourceCounts = + std::vector>; + ResourceCounts GetResourceCounts() { + ResourceCounts resource_counts; + XdsClientTestPeer(xds_client_.get()) + .TestReportResourceCounts( + [&](const XdsClientTestPeer::ResourceCountLabels& labels, + uint64_t count) { + resource_counts.emplace_back(labels, count); + }); + return resource_counts; + } + + using ServerConnectionMap = std::map; + ServerConnectionMap GetServerConnections() { + ServerConnectionMap server_connection_map; + XdsClientTestPeer(xds_client_.get()) + .TestReportServerConnections( + [&](absl::string_view xds_server, bool connected) { + std::string server(xds_server); + EXPECT_EQ(server_connection_map.find(server), + server_connection_map.end()); + server_connection_map[std::move(server)] = connected; + }); + return server_connection_map; + } + // Sets transport_factory_ and initializes xds_client_ with the // specified bootstrap config. void InitXdsClient( @@ -603,10 +663,13 @@ class XdsClientTest : public ::testing::Test { []() { FAIL() << "Multiple concurrent reads"; }); transport_factory_ = transport_factory->Ref().TakeAsSubclass(); + auto metrics_reporter = std::make_unique(); + metrics_reporter_ = metrics_reporter.get(); xds_client_ = MakeRefCounted( bootstrap_builder.Build(), std::move(transport_factory), - grpc_event_engine::experimental::GetDefaultEventEngine(), "foo agent", - "foo version", resource_request_timeout * grpc_test_slowdown_factor()); + grpc_event_engine::experimental::GetDefaultEventEngine(), + std::move(metrics_reporter), "foo agent", "foo version", + resource_request_timeout * grpc_test_slowdown_factor()); } // Starts and cancels a watch for a Foo resource. @@ -764,12 +827,45 @@ class XdsClientTest : public ::testing::Test { RefCountedPtr transport_factory_; RefCountedPtr xds_client_; + MetricsReporter* metrics_reporter_ = nullptr; }; +MATCHER_P3(ResourceCountLabelsEq, xds_authority, resource_type, cache_state, + "equals ResourceCountLabels") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(xds_authority, arg.xds_authority, + result_listener); + ok &= ::testing::ExplainMatchResult(resource_type, arg.resource_type, + result_listener); + ok &= ::testing::ExplainMatchResult(cache_state, arg.cache_state, + result_listener); + return ok; +} + TEST_F(XdsClientTest, BasicWatch) { InitXdsClient(); + // Metrics should initially be empty. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), ::testing::ElementsAre()); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre()); // Start a watch for "foo1". auto watcher = StartFooWatch("foo1"); + // Check metrics. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); // XdsClient should have created an ADS stream. @@ -795,6 +891,22 @@ TEST_F(XdsClientTest, BasicWatch) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -805,6 +917,16 @@ TEST_F(XdsClientTest, BasicWatch) { // Cancel watch. CancelFooWatch(watcher.get(), "foo1"); EXPECT_TRUE(stream->Orphaned()); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), ::testing::ElementsAre()); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre()); } TEST_F(XdsClientTest, UpdateFromServer) { @@ -836,6 +958,20 @@ TEST_F(XdsClientTest, UpdateFromServer) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -855,6 +991,20 @@ TEST_F(XdsClientTest, UpdateFromServer) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 9); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -896,6 +1046,20 @@ TEST_F(XdsClientTest, MultipleWatchersForSameResource) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -929,6 +1093,20 @@ TEST_F(XdsClientTest, MultipleWatchersForSameResource) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 9); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -951,6 +1129,17 @@ TEST_F(XdsClientTest, SubscribeToMultipleResources) { auto watcher = StartFooWatch("foo1"); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); + // Check metrics. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // XdsClient should have created an ADS stream. auto stream = WaitForAdsStream(); ASSERT_TRUE(stream != nullptr); @@ -974,6 +1163,20 @@ TEST_F(XdsClientTest, SubscribeToMultipleResources) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -983,6 +1186,19 @@ TEST_F(XdsClientTest, SubscribeToMultipleResources) { /*resource_names=*/{"foo1"}); // Start a watch for "foo2". auto watcher2 = StartFooWatch("foo2"); + // Check metric data. + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre( + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1), + ::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // XdsClient should have sent a subscription request on the ADS stream. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1002,6 +1218,20 @@ TEST_F(XdsClientTest, SubscribeToMultipleResources) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo2"); EXPECT_EQ(resource->value, 7); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 2))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1011,6 +1241,13 @@ TEST_F(XdsClientTest, SubscribeToMultipleResources) { /*resource_names=*/{"foo1", "foo2"}); // Cancel watch for "foo1". CancelFooWatch(watcher.get(), "foo1"); + // Check metric data. + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should send an unsubscription request. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1079,6 +1316,20 @@ TEST_F(XdsClientTest, UpdateContainsOnlyChangedResource) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo2"); EXPECT_EQ(resource->value, 7); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 2))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1098,6 +1349,20 @@ TEST_F(XdsClientTest, UpdateContainsOnlyChangedResource) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 9); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 3))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 2))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1122,6 +1387,17 @@ TEST_F(XdsClientTest, ResourceValidationFailure) { InitXdsClient(); // Start a watch for "foo1". auto watcher = StartFooWatch("foo1"); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); // XdsClient should have created an ADS stream. @@ -1151,6 +1427,20 @@ TEST_F(XdsClientTest, ResourceValidationFailure) { "invalid resource: INVALID_ARGUMENT: errors validating JSON: " "[field:value error:is not a number] (node ID:xds_client_test)") << *error; + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "nacked"), + 1))); // XdsClient should NACK the update. // Note that version_info is not populated in the request. request = WaitForRequest(stream.get()); @@ -1190,6 +1480,23 @@ TEST_F(XdsClientTest, ResourceValidationFailure) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 9); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1209,6 +1516,17 @@ TEST_F(XdsClientTest, ResourceValidationFailureMultipleResources) { auto watcher = StartFooWatch("foo1"); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // XdsClient should have created an ADS stream. auto stream = WaitForAdsStream(); ASSERT_TRUE(stream != nullptr); @@ -1222,6 +1540,17 @@ TEST_F(XdsClientTest, ResourceValidationFailureMultipleResources) { CheckRequestNode(*request); // Should be present on the first request. // Before the server responds, add a watch for another resource. auto watcher2 = StartFooWatch("foo2"); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 2))); // Client should send another request. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1231,6 +1560,17 @@ TEST_F(XdsClientTest, ResourceValidationFailureMultipleResources) { /*resource_names=*/{"foo1", "foo2"}); // Add a watch for a third resource. auto watcher3 = StartFooWatch("foo3"); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 3))); // Client should send another request. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1240,6 +1580,17 @@ TEST_F(XdsClientTest, ResourceValidationFailureMultipleResources) { /*resource_names=*/{"foo1", "foo2", "foo3"}); // Add a watch for a fourth resource. auto watcher4 = StartFooWatch("foo4"); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 4))); // Client should send another request. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1298,6 +1649,36 @@ TEST_F(XdsClientTest, ResourceValidationFailureMultipleResources) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo4"); EXPECT_EQ(resource->value, 5); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 5))); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre( + // foo4 + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1), + // foo1 and foo3 + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "nacked"), + 2), + // did not recognize response for foo2 + ::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // XdsClient should NACK the update. // There was one good resource, so the version will be updated. request = WaitForRequest(stream.get()); @@ -1363,6 +1744,20 @@ TEST_F(XdsClientTest, ResourceValidationFailureForCachedResource) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1386,6 +1781,23 @@ TEST_F(XdsClientTest, ResourceValidationFailureForCachedResource) { "invalid resource: INVALID_ARGUMENT: errors validating JSON: " "[field:value error:is not a number] (node ID:xds_client_test)") << *error; + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "nacked_but_cached"), + 1))); // XdsClient should NACK the update. // Note that version_info is set to the previous version in this request, // because there were no valid resources in it. @@ -1450,6 +1862,26 @@ TEST_F(XdsClientTest, WildcardCapableResponseWithEmptyResource) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "wc1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT( + metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 1))); + EXPECT_THAT( + metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 1))); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsWildcardCapableResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should NACK the update. // There was one good resource, so the version will be updated. request = WaitForRequest(stream.get()); @@ -1500,6 +1932,22 @@ TEST_F(XdsClientTest, ResourceDeletion) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "wc1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT( + metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsWildcardCapableResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1516,6 +1964,22 @@ TEST_F(XdsClientTest, ResourceDeletion) { .Serialize()); // Watcher should see the does-not-exist event. EXPECT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(1))); + // Check metric data. + EXPECT_THAT( + metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsWildcardCapableResourceType::Get()->type_url(), + "does_not_exist"), + 1))); // Start a new watcher for the same resource. It should immediately // receive the same does-not-exist notification. auto watcher2 = StartWildcardCapableWatch("wc1"); @@ -1543,6 +2007,22 @@ TEST_F(XdsClientTest, ResourceDeletion) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "wc1"); EXPECT_EQ(resource->value, 7); + // Check metric data. + EXPECT_THAT( + metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsWildcardCapableResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1587,6 +2067,22 @@ TEST_F(XdsClientTest, ResourceDeletionIgnoredWhenConfigured) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "wc1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT( + metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsWildcardCapableResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1604,6 +2100,22 @@ TEST_F(XdsClientTest, ResourceDeletionIgnoredWhenConfigured) { // Watcher should not see any update, since we should have ignored the // deletion. EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(1))); + // Check metric data. + EXPECT_THAT( + metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsWildcardCapableResourceType::Get()->type_url(), "acked"), + 1))); // Start a new watcher for the same resource. It should immediately // receive the cached resource. auto watcher2 = StartWildcardCapableWatch("wc1"); @@ -1634,6 +2146,22 @@ TEST_F(XdsClientTest, ResourceDeletionIgnoredWhenConfigured) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "wc1"); EXPECT_EQ(resource->value, 7); + // Check metric data. + EXPECT_THAT( + metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsWildcardCapableResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsWildcardCapableResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1649,8 +2177,13 @@ TEST_F(XdsClientTest, ResourceDeletionIgnoredWhenConfigured) { TEST_F(XdsClientTest, StreamClosedByServer) { InitXdsClient(); + // Metrics should initially be empty. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre()); // Start a watch for "foo1". auto watcher = StartFooWatch("foo1"); + // Check metric data. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); // XdsClient should have created an ADS stream. @@ -1689,6 +2222,9 @@ TEST_F(XdsClientTest, StreamClosedByServer) { // response on the stream before it failed. // Stream should be orphaned. EXPECT_TRUE(stream->Orphaned()); + // Check metric data. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should create a new stream. stream = WaitForAdsStream(); ASSERT_TRUE(stream != nullptr); @@ -1734,8 +2270,13 @@ TEST_F(XdsClientTest, StreamClosedByServer) { TEST_F(XdsClientTest, StreamClosedByServerWithoutSeeingResponse) { InitXdsClient(); + // Metrics should initially be empty. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre()); // Start a watch for "foo1". auto watcher = StartFooWatch("foo1"); + // Check metric data. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); // XdsClient should have created an ADS stream. @@ -1751,6 +2292,9 @@ TEST_F(XdsClientTest, StreamClosedByServerWithoutSeeingResponse) { CheckRequestNode(*request); // Should be present on the first request. // Server closes the stream without sending a response. stream->MaybeSendStatusToClient(absl::UnavailableError("ugh")); + // Check metric data. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", false))); // XdsClient should report an error to the watcher. auto error = watcher->WaitForNextError(); ASSERT_TRUE(error.has_value()); @@ -1771,6 +2315,9 @@ TEST_F(XdsClientTest, StreamClosedByServerWithoutSeeingResponse) { /*error_detail=*/absl::OkStatus(), /*resource_names=*/{"foo1"}); CheckRequestNode(*request); // Should be present on the first request. + // Connection still reported as unhappy until we get a response. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", false))); // Server now sends the requested resource. stream->SendMessageToClient( ResponseBuilder(XdsFooResourceType::Get()->type_url()) @@ -1783,6 +2330,9 @@ TEST_F(XdsClientTest, StreamClosedByServerWithoutSeeingResponse) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Connection now reported as happy. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient sends an ACK. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1802,8 +2352,13 @@ TEST_F(XdsClientTest, ConnectionFails) { // Tell transport to let us manually trigger completion of the // send_message ops to XdsClient. transport_factory_->SetAutoCompleteMessagesFromClient(false); + // Metrics should initially be empty. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre()); // Start a watch for "foo1". auto watcher = StartFooWatch("foo1"); + // Check metric data. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); // XdsClient should have created an ADS stream. @@ -1828,6 +2383,9 @@ TEST_F(XdsClientTest, ConnectionFails) { "xDS channel for server default_xds_server: " "connection failed (node ID:xds_client_test)") << *error; + // Connection reported as unhappy. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", false))); // We should not see a resource-does-not-exist event, because the // timer should not be running while the channel is disconnected. EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(4))); @@ -1853,6 +2411,9 @@ TEST_F(XdsClientTest, ConnectionFails) { .set_nonce("A") .AddFooResource(XdsFooResource("foo1", 6)) .Serialize()); + // Connection now reported as happy. + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should have delivered the response to the watchers. auto resource = watcher->WaitForNextResource(); ASSERT_NE(resource, nullptr); @@ -1882,6 +2443,17 @@ TEST_F(XdsClientTest, ResourceDoesNotExistUponTimeout) { auto watcher = StartFooWatch("foo1"); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // XdsClient should have created an ADS stream. auto stream = WaitForAdsStream(); ASSERT_TRUE(stream != nullptr); @@ -1896,6 +2468,17 @@ TEST_F(XdsClientTest, ResourceDoesNotExistUponTimeout) { // Do not send a response, but wait for the resource to be reported as // not existing. EXPECT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(5))); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "does_not_exist"), + 1))); // Start a new watcher for the same resource. It should immediately // receive the same does-not-exist notification. auto watcher2 = StartFooWatch("foo1"); @@ -1916,6 +2499,20 @@ TEST_F(XdsClientTest, ResourceDoesNotExistUponTimeout) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -1932,8 +2529,25 @@ TEST_F(XdsClientTest, ResourceDoesNotExistUponTimeout) { TEST_F(XdsClientTest, ResourceDoesNotExistAfterStreamRestart) { // Lower resources-does-not-exist timeout so test finishes faster. InitXdsClient(FakeXdsBootstrap::Builder(), Duration::Seconds(3)); + // Metrics should initially be empty. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), ::testing::ElementsAre()); // Start a watch for "foo1". auto watcher = StartFooWatch("foo1"); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher->HasEvent()); // XdsClient should have created an ADS stream. @@ -1958,6 +2572,17 @@ TEST_F(XdsClientTest, ResourceDoesNotExistAfterStreamRestart) { "with no responses received; status: UNAVAILABLE: ugh " "(node ID:xds_client_test)") << *error; + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // XdsClient should create a new stream. stream = WaitForAdsStream(); ASSERT_TRUE(stream != nullptr); @@ -1972,6 +2597,17 @@ TEST_F(XdsClientTest, ResourceDoesNotExistAfterStreamRestart) { // Server does NOT send a response immediately. // Client should receive a resource does-not-exist. ASSERT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(4))); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "does_not_exist"), + 1))); // Server now sends the requested resource. stream->SendMessageToClient( ResponseBuilder(XdsFooResourceType::Get()->type_url()) @@ -1984,6 +2620,20 @@ TEST_F(XdsClientTest, ResourceDoesNotExistAfterStreamRestart) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient sends an ACK. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2022,12 +2672,26 @@ TEST_F(XdsClientTest, DoesNotExistTimerNotStartedUntilSendCompletes) { // We should not see a resource-does-not-exist event, because the // timer should not be running while the channel is disconnected. EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(4))); + // Check metric data. + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // The ADS stream uses wait_for_ready inside the XdsTransport interface, // so when the channel connects, the already-started stream will proceed. stream->CompleteSendMessageFromClient(); // Server does NOT send a response. // Watcher should see a does-not-exist event. EXPECT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(4))); + // Check metric data. + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "does_not_exist"), + 1))); // Now server sends a response. stream->SendMessageToClient( ResponseBuilder(XdsFooResourceType::Get()->type_url()) @@ -2040,6 +2704,13 @@ TEST_F(XdsClientTest, DoesNotExistTimerNotStartedUntilSendCompletes) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2093,6 +2764,20 @@ TEST_F(XdsClientTest, ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2105,6 +2790,19 @@ TEST_F(XdsClientTest, auto watcher2 = StartFooWatch("foo2"); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher2->HasEvent()); + // Check metric data. + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre( + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1), + ::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); // XdsClient sends a request to subscribe to the new resource. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2116,7 +2814,19 @@ TEST_F(XdsClientTest, // complete. // Unsubscribe from foo1 and then re-subscribe to it. CancelFooWatch(watcher.get(), "foo1"); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); watcher = StartFooWatch("foo1"); + EXPECT_THAT(GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), + "requested"), + 2))); // Now send a response from the server containing both foo1 and foo2. stream->SendMessageToClient( ResponseBuilder(XdsFooResourceType::Get()->type_url()) @@ -2137,6 +2847,20 @@ TEST_F(XdsClientTest, ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo2"); EXPECT_EQ(resource->value, 7); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 3))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 2))); // Now we finally tell XdsClient that its previous send_message op is // complete. stream->CompleteSendMessageFromClient(); @@ -2189,6 +2913,20 @@ TEST_F(XdsClientTest, DoNotSendDoesNotExistForCachedResource) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2216,6 +2954,20 @@ TEST_F(XdsClientTest, DoNotSendDoesNotExistForCachedResource) { // resource was already cached, so the server can optimize by not // resending it. EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(4))); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // Now server sends a response. stream->SendMessageToClient( ResponseBuilder(XdsFooResourceType::Get()->type_url()) @@ -2225,6 +2977,22 @@ TEST_F(XdsClientTest, DoNotSendDoesNotExistForCachedResource) { .Serialize()); // Watcher will not see any update, since the resource is unchanged. EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(1))); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2267,6 +3035,20 @@ TEST_F(XdsClientTest, ResourceWrappedInResourceMessage) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2308,6 +3090,20 @@ TEST_F(XdsClientTest, MultipleResourceTypes) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2338,6 +3134,30 @@ TEST_F(XdsClientTest, MultipleResourceTypes) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource2->name, "bar1"); EXPECT_EQ(resource2->value, "whee"); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre( + ::testing::Pair( + ::testing::Pair("default_xds_server", + XdsBarResourceType::Get()->type_url()), + 1), + ::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::UnorderedElementsAre( + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsBarResourceType::Get()->type_url(), "acked"), + 1), + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2368,6 +3188,13 @@ TEST_F(XdsClientTest, Federation) { authority.set_server(authority_server); InitXdsClient( FakeXdsBootstrap::Builder().AddAuthority(kAuthority, authority)); + // Metrics should initially be empty. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre()); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT(GetResourceCounts(), ::testing::ElementsAre()); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre()); // Start a watch for "foo1". auto watcher = StartFooWatch("foo1"); // Watcher should initially not see any resource reported. @@ -2395,6 +3222,22 @@ TEST_F(XdsClientTest, Federation) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2406,6 +3249,22 @@ TEST_F(XdsClientTest, Federation) { auto watcher2 = StartFooWatch(kXdstpResourceName); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher2->HasEvent()); + // Check metric data. + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre( + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1), + ::testing::Pair(ResourceCountLabelsEq( + kAuthority, XdsFooResourceType::Get()->type_url(), + "requested"), + 1))); + EXPECT_THAT(GetServerConnections(), + ::testing::ElementsAre( + ::testing::Pair("default_xds_server", true), + ::testing::Pair(authority_server.server_uri(), true))); // XdsClient will create a new stream to the server for this authority. auto stream2 = WaitForAdsStream(authority_server); ASSERT_TRUE(stream2 != nullptr); @@ -2431,6 +3290,34 @@ TEST_F(XdsClientTest, Federation) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, kXdstpResourceName); EXPECT_EQ(resource->value, 3); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre( + ::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1), + ::testing::Pair( + ::testing::Pair(authority_server.server_uri(), + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre( + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1), + ::testing::Pair( + ResourceCountLabelsEq( + kAuthority, XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), + ::testing::ElementsAre( + ::testing::Pair("default_xds_server", true), + ::testing::Pair(authority_server.server_uri(), true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream2.get()); ASSERT_TRUE(request.has_value()); @@ -2481,6 +3368,22 @@ TEST_F(XdsClientTest, FederationAuthorityDefaultsToTopLevelXdsServer) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2513,6 +3416,27 @@ TEST_F(XdsClientTest, FederationAuthorityDefaultsToTopLevelXdsServer) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, kXdstpResourceName); EXPECT_EQ(resource->value, 3); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 2))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre( + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1), + ::testing::Pair( + ResourceCountLabelsEq( + kAuthority, XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2651,6 +3575,22 @@ TEST_F(XdsClientTest, FederationChannelFailureReportedToWatchers) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, "foo1"); EXPECT_EQ(resource->value, 6); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre(::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre(::testing::Pair( + ResourceCountLabelsEq(XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), ::testing::ElementsAre(::testing::Pair( + "default_xds_server", true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream.get()); ASSERT_TRUE(request.has_value()); @@ -2660,6 +3600,11 @@ TEST_F(XdsClientTest, FederationChannelFailureReportedToWatchers) { /*resource_names=*/{"foo1"}); // Start a watch for the xdstp resource name. auto watcher2 = StartFooWatch(kXdstpResourceName); + // Check metric data. + EXPECT_THAT(GetServerConnections(), + ::testing::ElementsAre( + ::testing::Pair("default_xds_server", true), + ::testing::Pair(authority_server.server_uri(), true))); // Watcher should initially not see any resource reported. EXPECT_FALSE(watcher2->HasEvent()); // XdsClient will create a new stream to the server for this authority. @@ -2687,6 +3632,34 @@ TEST_F(XdsClientTest, FederationChannelFailureReportedToWatchers) { ASSERT_NE(resource, nullptr); EXPECT_EQ(resource->name, kXdstpResourceName); EXPECT_EQ(resource->value, 3); + // Check metric data. + EXPECT_THAT(metrics_reporter_->resource_updates_valid(), + ::testing::ElementsAre( + ::testing::Pair( + ::testing::Pair("default_xds_server", + XdsFooResourceType::Get()->type_url()), + 1), + ::testing::Pair( + ::testing::Pair(authority_server.server_uri(), + XdsFooResourceType::Get()->type_url()), + 1))); + EXPECT_THAT(metrics_reporter_->resource_updates_invalid(), + ::testing::ElementsAre()); + EXPECT_THAT( + GetResourceCounts(), + ::testing::ElementsAre( + ::testing::Pair(ResourceCountLabelsEq( + XdsClient::kOldStyleAuthority, + XdsFooResourceType::Get()->type_url(), "acked"), + 1), + ::testing::Pair( + ResourceCountLabelsEq( + kAuthority, XdsFooResourceType::Get()->type_url(), "acked"), + 1))); + EXPECT_THAT(GetServerConnections(), + ::testing::ElementsAre( + ::testing::Pair("default_xds_server", true), + ::testing::Pair(authority_server.server_uri(), true))); // XdsClient should have sent an ACK message to the xDS server. request = WaitForRequest(stream2.get()); ASSERT_TRUE(request.has_value()); @@ -2707,6 +3680,11 @@ TEST_F(XdsClientTest, FederationChannelFailureReportedToWatchers) { << *error; // The watcher for "foo1" should not see any error. EXPECT_FALSE(watcher->HasEvent()); + // Check metric data. + EXPECT_THAT(GetServerConnections(), + ::testing::ElementsAre( + ::testing::Pair("default_xds_server", true), + ::testing::Pair(authority_server.server_uri(), false))); // Cancel watch for "foo1". CancelFooWatch(watcher.get(), "foo1"); EXPECT_TRUE(stream->Orphaned()); diff --git a/test/core/xds/xds_client_test_peer.h b/test/core/xds/xds_client_test_peer.h new file mode 100644 index 00000000000..64cbd841499 --- /dev/null +++ b/test/core/xds/xds_client_test_peer.h @@ -0,0 +1,80 @@ +// +// Copyright 2022 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. +// + +#ifndef GRPC_TEST_CORE_XDS_XDS_CLIENT_TEST_PEER_H +#define GRPC_TEST_CORE_XDS_XDS_CLIENT_TEST_PEER_H + +#include + +#include + +#include "absl/functional/function_ref.h" +#include "absl/strings/str_cat.h" + +#include "src/core/ext/xds/xds_client.h" + +namespace grpc_core { +namespace testing { + +class XdsClientTestPeer { + public: + explicit XdsClientTestPeer(XdsClient* xds_client) : xds_client_(xds_client) {} + + void TestDumpClientConfig() { + upb::Arena arena; + auto client_config = envoy_service_status_v3_ClientConfig_new(arena.ptr()); + std::set string_pool; + MutexLock lock(xds_client_->mu()); + xds_client_->DumpClientConfig(&string_pool, arena.ptr(), client_config); + } + + struct ResourceCountLabels { + std::string xds_authority; + std::string resource_type; + std::string cache_state; + + std::string ToString() const { + return absl::StrCat("xds_authority=\"", xds_authority, + "\" resource_type=\"", resource_type, + "\" cache_state=\"", cache_state, "\""); + } + }; + void TestReportResourceCounts( + absl::FunctionRef func) { + MutexLock lock(xds_client_->mu()); + xds_client_->ReportResourceCounts( + [&](const XdsClient::ResourceCountLabels& labels, uint64_t count) { + ResourceCountLabels labels_copy = {std::string(labels.xds_authority), + std::string(labels.resource_type), + std::string(labels.cache_state)}; + func(labels_copy, count); + }); + } + + void TestReportServerConnections( + absl::FunctionRef func) { + MutexLock lock(xds_client_->mu()); + xds_client_->ReportServerConnections(func); + } + + private: + XdsClient* xds_client_; +}; + +} // namespace testing +} // namespace grpc_core + +#endif // GRPC_TEST_CORE_XDS_XDS_CLIENT_TEST_PEER_H diff --git a/test/core/xds/xds_cluster_resource_type_test.cc b/test/core/xds/xds_cluster_resource_type_test.cc index a30dd8bc253..2cb04833eec 100644 --- a/test/core/xds/xds_cluster_resource_type_test.cc +++ b/test/core/xds/xds_cluster_resource_type_test.cc @@ -118,7 +118,8 @@ class XdsClusterTest : public ::testing::Test { } return MakeRefCounted(std::move(*bootstrap), /*transport_factory=*/nullptr, - /*event_engine=*/nullptr, "foo agent", + /*event_engine=*/nullptr, + /*metrics_reporter=*/nullptr, "foo agent", "foo version"); } diff --git a/test/core/xds/xds_common_types_test.cc b/test/core/xds/xds_common_types_test.cc index ab049d954d6..4a5be5da3d7 100644 --- a/test/core/xds/xds_common_types_test.cc +++ b/test/core/xds/xds_common_types_test.cc @@ -104,7 +104,8 @@ class XdsCommonTypesTest : public ::testing::Test { } return MakeRefCounted(std::move(*bootstrap), /*transport_factory=*/nullptr, - /*event_engine=*/nullptr, "foo agent", + /*event_engine=*/nullptr, + /*metrics_reporter=*/nullptr, "foo agent", "foo version"); } diff --git a/test/core/xds/xds_endpoint_resource_type_test.cc b/test/core/xds/xds_endpoint_resource_type_test.cc index 8538dcd15c0..9371d50a780 100644 --- a/test/core/xds/xds_endpoint_resource_type_test.cc +++ b/test/core/xds/xds_endpoint_resource_type_test.cc @@ -95,7 +95,8 @@ class XdsEndpointTest : public ::testing::Test { } return MakeRefCounted(std::move(*bootstrap), /*transport_factory=*/nullptr, - /*event_engine=*/nullptr, "foo agent", + /*event_engine=*/nullptr, + /*metrics_reporter=*/nullptr, "foo agent", "foo version"); } diff --git a/test/core/xds/xds_http_filters_test.cc b/test/core/xds/xds_http_filters_test.cc index b8585d319d6..bdbabc45283 100644 --- a/test/core/xds/xds_http_filters_test.cc +++ b/test/core/xds/xds_http_filters_test.cc @@ -117,7 +117,8 @@ class XdsHttpFilterTest : public ::testing::Test { } return MakeRefCounted(std::move(*bootstrap), /*transport_factory=*/nullptr, - /*event_engine=*/nullptr, "foo agent", + /*event_engine=*/nullptr, + /*metrics_reporter=*/nullptr, "foo agent", "foo version"); } diff --git a/test/core/xds/xds_listener_resource_type_test.cc b/test/core/xds/xds_listener_resource_type_test.cc index eac9cb55df7..86a1b299b0a 100644 --- a/test/core/xds/xds_listener_resource_type_test.cc +++ b/test/core/xds/xds_listener_resource_type_test.cc @@ -118,7 +118,8 @@ class XdsListenerTest : public ::testing::Test { } return MakeRefCounted(std::move(*bootstrap), /*transport_factory=*/nullptr, - /*event_engine=*/nullptr, "foo agent", + /*event_engine=*/nullptr, + /*metrics_reporter=*/nullptr, "foo agent", "foo version"); } diff --git a/test/core/xds/xds_route_config_resource_type_test.cc b/test/core/xds/xds_route_config_resource_type_test.cc index 8703efdfcb2..e6df7684377 100644 --- a/test/core/xds/xds_route_config_resource_type_test.cc +++ b/test/core/xds/xds_route_config_resource_type_test.cc @@ -107,7 +107,8 @@ class XdsRouteConfigTest : public ::testing::Test { } return MakeRefCounted(std::move(*bootstrap), /*transport_factory=*/nullptr, - /*event_engine=*/nullptr, "foo agent", + /*event_engine=*/nullptr, + /*metrics_reporter=*/nullptr, "foo agent", "foo version"); } diff --git a/test/cpp/end2end/xds/BUILD b/test/cpp/end2end/xds/BUILD index 30f165067c4..cc36de6519d 100644 --- a/test/cpp/end2end/xds/BUILD +++ b/test/cpp/end2end/xds/BUILD @@ -223,6 +223,7 @@ grpc_cc_test( "//:gpr", "//:grpc", "//:grpc++", + "//test/core/util:fake_stats_plugin", "//test/core/util:grpc_test_util", "//test/core/util:scoped_env_var", ], diff --git a/test/cpp/end2end/xds/xds_core_end2end_test.cc b/test/cpp/end2end/xds/xds_core_end2end_test.cc index 752ed01fe55..df5c480b091 100644 --- a/test/cpp/end2end/xds/xds_core_end2end_test.cc +++ b/test/cpp/end2end/xds/xds_core_end2end_test.cc @@ -27,6 +27,7 @@ #include "src/core/client_channel/backup_poller.h" #include "src/core/lib/config/config_vars.h" #include "src/proto/grpc/testing/xds/v3/listener.pb.h" +#include "test/core/util/fake_stats_plugin.h" #include "test/core/util/resolve_localhost_ip46.h" #include "test/core/util/scoped_env_var.h" #include "test/cpp/end2end/xds/xds_end2end_test_lib.h" @@ -1071,6 +1072,172 @@ TEST_P(XdsFederationTest, FederationServer) { WaitForAllBackends(DEBUG_LOCATION); } +// +// XdsMetricsTest - tests xDS metrics +// + +class XdsMetricsTest : public XdsEnd2endTest { + protected: + void SetUp() override { + stats_plugin_ = grpc_core::FakeStatsPluginBuilder() + .UseDisabledByDefaultMetrics(true) + .BuildAndRegister(); + InitClient(); + } + + std::shared_ptr stats_plugin_; +}; + +// Runs with RDS so that we know all resource types work properly. +INSTANTIATE_TEST_SUITE_P( + XdsTest, XdsMetricsTest, + ::testing::Values(XdsTestType().set_enable_rds_testing()), + &XdsTestType::Name); + +TEST_P(XdsMetricsTest, MetricDefinitionResourceUpdatesValid) { + const auto* descriptor = + grpc_core::GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName( + "grpc.xds_client.resource_updates_valid"); + ASSERT_NE(descriptor, nullptr); + EXPECT_EQ(descriptor->value_type, + grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64); + EXPECT_EQ(descriptor->instrument_type, + grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCounter); + EXPECT_EQ(descriptor->enable_by_default, false); + EXPECT_EQ(descriptor->name, "grpc.xds_client.resource_updates_valid"); + EXPECT_EQ(descriptor->unit, "{resource}"); + EXPECT_THAT(descriptor->label_keys, + ::testing::ElementsAre("grpc.target", "grpc.xds.server", + "grpc.xds.resource_type")); + EXPECT_THAT(descriptor->optional_label_keys, ::testing::ElementsAre()); +} + +TEST_P(XdsMetricsTest, MetricDefinitionResourceUpdatesInvalid) { + const auto* descriptor = + grpc_core::GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName( + "grpc.xds_client.resource_updates_invalid"); + ASSERT_NE(descriptor, nullptr); + EXPECT_EQ(descriptor->value_type, + grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64); + EXPECT_EQ(descriptor->instrument_type, + grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCounter); + EXPECT_EQ(descriptor->enable_by_default, false); + EXPECT_EQ(descriptor->name, "grpc.xds_client.resource_updates_invalid"); + EXPECT_EQ(descriptor->unit, "{resource}"); + EXPECT_THAT(descriptor->label_keys, + ::testing::ElementsAre("grpc.target", "grpc.xds.server", + "grpc.xds.resource_type")); + EXPECT_THAT(descriptor->optional_label_keys, ::testing::ElementsAre()); +} + +TEST_P(XdsMetricsTest, MetricDefinitionConnected) { + const auto* descriptor = + grpc_core::GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName( + "grpc.xds_client.connected"); + ASSERT_NE(descriptor, nullptr); + EXPECT_EQ(descriptor->value_type, + grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64); + EXPECT_EQ( + descriptor->instrument_type, + grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge); + EXPECT_EQ(descriptor->enable_by_default, false); + EXPECT_EQ(descriptor->name, "grpc.xds_client.connected"); + EXPECT_EQ(descriptor->unit, "{bool}"); + EXPECT_THAT(descriptor->label_keys, + ::testing::ElementsAre("grpc.target", "grpc.xds.server")); + EXPECT_THAT(descriptor->optional_label_keys, ::testing::ElementsAre()); +} + +TEST_P(XdsMetricsTest, MetricDefinitionResources) { + const auto* descriptor = + grpc_core::GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName( + "grpc.xds_client.resources"); + ASSERT_NE(descriptor, nullptr); + EXPECT_EQ(descriptor->value_type, + grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64); + EXPECT_EQ( + descriptor->instrument_type, + grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge); + EXPECT_EQ(descriptor->enable_by_default, false); + EXPECT_EQ(descriptor->name, "grpc.xds_client.resources"); + EXPECT_EQ(descriptor->unit, "{resource}"); + EXPECT_THAT( + descriptor->label_keys, + ::testing::ElementsAre("grpc.target", "grpc.xds.authority", + "grpc.xds.resource_type", "grpc.xds.cache_state")); + EXPECT_THAT(descriptor->optional_label_keys, ::testing::ElementsAre()); +} + +TEST_P(XdsMetricsTest, MetricValues) { + const auto kMetricResourceUpdatesValid = + grpc_core::GlobalInstrumentsRegistryTestPeer:: + FindUInt64CounterHandleByName( + "grpc.xds_client.resource_updates_valid") + .value(); + const auto kMetricResourceUpdatesInvalid = + grpc_core::GlobalInstrumentsRegistryTestPeer:: + FindUInt64CounterHandleByName( + "grpc.xds_client.resource_updates_invalid") + .value(); + const auto kMetricConnected = + grpc_core::GlobalInstrumentsRegistryTestPeer:: + FindCallbackInt64GaugeHandleByName("grpc.xds_client.connected") + .value(); + const auto kMetricResources = + grpc_core::GlobalInstrumentsRegistryTestPeer:: + FindCallbackInt64GaugeHandleByName("grpc.xds_client.resources") + .value(); + const std::string kTarget = absl::StrCat("xds:", kServerName); + const std::string kXdsServer = absl::StrCat("localhost:", balancer_->port()); + CreateAndStartBackends(1, /*xds_enabled=*/true); + EdsResourceArgs args = + EdsResourceArgs({{"locality0", CreateEndpointsForBackends()}}); + balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); + CheckRpcSendOk(DEBUG_LOCATION); + stats_plugin_->TriggerCallbacks(); + // Check client metrics. + EXPECT_THAT(stats_plugin_->GetCallbackGaugeValue(kMetricConnected, + {kTarget, kXdsServer}, {}), + ::testing::Optional(1)); + for (absl::string_view type_url : + {"envoy.config.listener.v3.Listener", + "envoy.config.route.v3.RouteConfiguration", + "envoy.config.cluster.v3.Cluster", + "envoy.config.endpoint.v3.ClusterLoadAssignment"}) { + EXPECT_THAT( + stats_plugin_->GetCounterValue(kMetricResourceUpdatesValid, + {kTarget, kXdsServer, type_url}, {}), + ::testing::Optional(1)); + EXPECT_THAT( + stats_plugin_->GetCounterValue(kMetricResourceUpdatesInvalid, + {kTarget, kXdsServer, type_url}, {}), + ::testing::Optional(0)); + EXPECT_THAT(stats_plugin_->GetCallbackGaugeValue( + kMetricResources, {kTarget, "#old", type_url, "acked"}, {}), + ::testing::Optional(1)); + } + // Check server metrics. + EXPECT_THAT(stats_plugin_->GetCallbackGaugeValue(kMetricConnected, + {"#server", kXdsServer}, {}), + ::testing::Optional(1)); + for (absl::string_view type_url : + {"envoy.config.listener.v3.Listener", + "envoy.config.route.v3.RouteConfiguration"}) { + EXPECT_THAT( + stats_plugin_->GetCounterValue(kMetricResourceUpdatesValid, + {"#server", kXdsServer, type_url}, {}), + ::testing::Optional(1)); + EXPECT_THAT( + stats_plugin_->GetCounterValue(kMetricResourceUpdatesInvalid, + {"#server", kXdsServer, type_url}, {}), + ::testing::Optional(0)); + EXPECT_THAT( + stats_plugin_->GetCallbackGaugeValue( + kMetricResources, {"#server", "#old", type_url, "acked"}, {}), + ::testing::Optional(1)); + } +} + // // XdsFederationDisabledTest // diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index ba4cbaec282..f855fd03361 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -2115,6 +2115,7 @@ src/core/ext/xds/xds_lb_policy_registry.cc \ src/core/ext/xds/xds_lb_policy_registry.h \ src/core/ext/xds/xds_listener.cc \ src/core/ext/xds/xds_listener.h \ +src/core/ext/xds/xds_metrics.h \ src/core/ext/xds/xds_resource_type.h \ src/core/ext/xds/xds_resource_type_impl.h \ src/core/ext/xds/xds_route_config.cc \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 8796adfd4c6..a61ab574132 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1885,6 +1885,7 @@ src/core/ext/xds/xds_lb_policy_registry.cc \ src/core/ext/xds/xds_lb_policy_registry.h \ src/core/ext/xds/xds_listener.cc \ src/core/ext/xds/xds_listener.h \ +src/core/ext/xds/xds_metrics.h \ src/core/ext/xds/xds_resource_type.h \ src/core/ext/xds/xds_resource_type_impl.h \ src/core/ext/xds/xds_route_config.cc \ From 065aa63d1754a0271a88b762d02d7b049a39c4e8 Mon Sep 17 00:00:00 2001 From: Ming-Chuan Lin Date: Tue, 19 Mar 2024 16:51:39 -0700 Subject: [PATCH 02/15] Internal change PiperOrigin-RevId: 617335127 --- src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD index cfdd74e4050..5e63c32bc51 100644 --- a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD +++ b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@build_bazel_rules_android//android:rules.bzl", "android_library") +# copybara: Import internal android_library rule here licenses(["notice"]) From 125492ea7046e3dc631613cc2b9273103b9a6b51 Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Wed, 20 Mar 2024 11:39:51 -0700 Subject: [PATCH 03/15] [xds] Add env protection for multiple xDS servers in bootstrap (#36154) As per [gRFC A71](https://github.com/grpc/proposal/blob/master/A71-xds-fallback.md). Closes #36154 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36154 from eugeneo:xds-bootstrap-servers-env-var aada3e7e4ab4e4134fa22a97e1d3de7cd5a8b709 PiperOrigin-RevId: 617579604 --- build_autogenerated.yaml | 3 +- src/core/ext/xds/xds_bootstrap_grpc.cc | 28 ++++++++ src/core/ext/xds/xds_bootstrap_grpc.h | 2 + test/core/xds/BUILD | 1 + test/core/xds/xds_bootstrap_test.cc | 96 ++++++++++++++++++++++++-- 5 files changed, 123 insertions(+), 7 deletions(-) diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index 973ec51a9ce..a28fd37bcc2 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -20188,7 +20188,8 @@ targets: gtest: true build: test language: c++ - headers: [] + headers: + - test/core/util/scoped_env_var.h src: - test/core/xds/xds_bootstrap_test.cc deps: diff --git a/src/core/ext/xds/xds_bootstrap_grpc.cc b/src/core/ext/xds/xds_bootstrap_grpc.cc index 41749e510cd..dcd5c918091 100644 --- a/src/core/ext/xds/xds_bootstrap_grpc.cc +++ b/src/core/ext/xds/xds_bootstrap_grpc.cc @@ -38,6 +38,8 @@ #include #include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/env.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/json/json.h" #include "src/core/lib/json/json_object_loader.h" @@ -47,6 +49,17 @@ namespace grpc_core { +namespace { +bool IsFallbackExperimentEnabled() { + auto fallback_enabled = GetEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK"); + bool enabled = false; + return gpr_parse_bool_value(fallback_enabled.value_or("0").c_str(), + &enabled) && + enabled; +} + +} // namespace + // // GrpcXdsBootstrap::GrpcNode::Locality // @@ -219,6 +232,16 @@ const JsonLoaderInterface* GrpcXdsBootstrap::GrpcAuthority::JsonLoader( return loader; } +void GrpcXdsBootstrap::GrpcAuthority::JsonPostLoad( + const Json& /*json*/, const JsonArgs& /*args*/, + ValidationErrors* /*errors*/) { + if (!IsFallbackExperimentEnabled()) { + if (servers_.size() > 1) { + servers_.resize(1); + } + } +} + // // GrpcXdsBootstrap // @@ -293,6 +316,11 @@ void GrpcXdsBootstrap::JsonPostLoad(const Json& /*json*/, } } } + if (!IsFallbackExperimentEnabled()) { + if (servers_.size() > 1) { + servers_.resize(1); + } + } } std::string GrpcXdsBootstrap::ToString() const { diff --git a/src/core/ext/xds/xds_bootstrap_grpc.h b/src/core/ext/xds/xds_bootstrap_grpc.h index 13c6c8ac083..89fb7fe15e4 100644 --- a/src/core/ext/xds/xds_bootstrap_grpc.h +++ b/src/core/ext/xds/xds_bootstrap_grpc.h @@ -118,6 +118,8 @@ class GrpcXdsBootstrap : public XdsBootstrap { } static const JsonLoaderInterface* JsonLoader(const JsonArgs&); + void JsonPostLoad(const Json& json, const JsonArgs& args, + ValidationErrors* errors); private: std::vector servers_; diff --git a/test/core/xds/BUILD b/test/core/xds/BUILD index 581db547721..0ca4fe1ac5a 100644 --- a/test/core/xds/BUILD +++ b/test/core/xds/BUILD @@ -37,6 +37,7 @@ grpc_cc_test( "//:gpr", "//src/core:grpc_xds_client", "//test/core/util:grpc_test_util", + "//test/core/util:scoped_env_var", ], ) diff --git a/test/core/xds/xds_bootstrap_test.cc b/test/core/xds/xds_bootstrap_test.cc index 0749a9006e3..f5feb114d51 100644 --- a/test/core/xds/xds_bootstrap_test.cc +++ b/test/core/xds/xds_bootstrap_test.cc @@ -49,6 +49,7 @@ #include "src/core/lib/security/certificate_provider/certificate_provider_factory.h" #include "src/core/lib/security/credentials/channel_creds_registry.h" #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" +#include "test/core/util/scoped_env_var.h" #include "test/core/util/test_config.h" namespace grpc_core { @@ -163,8 +164,7 @@ TEST(XdsBootstrapTest, Basic) { ASSERT_TRUE(bootstrap_or.ok()) << bootstrap_or.status(); auto bootstrap = std::move(*bootstrap_or); EXPECT_THAT(bootstrap->servers(), - ::testing::ElementsAre(EqXdsServer("fake:///lb1", "fake"), - EqXdsServer("fake:///lb2", "fake"))); + ::testing::ElementsAre(EqXdsServer("fake:///lb1", "fake"))); EXPECT_EQ(bootstrap->authorities().size(), 2); auto* authority = static_cast( bootstrap->LookupAuthority("xds.example.com")); @@ -172,10 +172,8 @@ TEST(XdsBootstrapTest, Basic) { EXPECT_EQ(authority->client_listener_resource_name_template(), "xdstp://xds.example.com/envoy.config.listener.v3.Listener/grpc/" "server/%s"); - EXPECT_THAT( - authority->servers(), - ::testing::ElementsAre(EqXdsServer("fake:///xds_server", "fake"), - EqXdsServer("fake:///xds_server2", "fake"))); + EXPECT_THAT(authority->servers(), ::testing::ElementsAre(EqXdsServer( + "fake:///xds_server", "fake"))); authority = static_cast( bootstrap->LookupAuthority("xds.example2.com")); ASSERT_NE(authority, nullptr); @@ -726,6 +724,92 @@ TEST(XdsBootstrapTest, XdsServerToJsonAndParse) { EXPECT_EQ(*xds_server, *output_xds_server); } +TEST(XdsBootstrapTest, NoXdsServersEnvVar) { + ScopedEnvVar fallback_enabled("GRPC_EXPERIMENTAL_XDS_FALLBACK", "1"); + const char* json_str = + "{" + " \"xds_servers\": [" + " {" + " \"server_uri\": \"fake:///lb1\"," + " \"channel_creds\": [" + " {" + " \"type\": \"fake\"," + " \"ignore\": 0" + " }" + " ]," + " \"ignore\": 0" + " }," + " {" + " \"server_uri\": \"fake:///lb2\"," + " \"channel_creds\": [" + " {" + " \"type\": \"fake\"," + " \"ignore\": 0" + " }" + " ]," + " \"ignore\": 0" + " }" + " ]," + " \"authorities\": {" + " \"xds.example.com\": {" + " \"client_listener_resource_name_template\": " + "\"xdstp://xds.example.com/envoy.config.listener.v3.Listener/grpc/server/" + "%s\"," + " \"xds_servers\": [" + " {" + " \"server_uri\": \"fake:///xds_server\"," + " \"channel_creds\": [" + " {" + " \"type\": \"fake\"" + " }" + " ]," + " \"server_features\": [\"xds_v3\"]" + " }," + " {" + " \"server_uri\": \"fake:///xds_server2\"," + " \"channel_creds\": [" + " {" + " \"type\": \"fake\"" + " }" + " ]," + " \"server_features\": [\"xds_v3\"]" + " }" + " ]" + " }" + " }," + " \"node\": {" + " \"id\": \"foo\"," + " \"cluster\": \"bar\"," + " \"locality\": {" + " \"region\": \"milky_way\"," + " \"zone\": \"sol_system\"," + " \"sub_zone\": \"earth\"," + " \"ignore\": {}" + " }," + " \"metadata\": {" + " \"foo\": 1," + " \"bar\": 2" + " }," + " \"ignore\": \"whee\"" + " }," + " \"server_listener_resource_name_template\": \"example/resource\"," + " \"ignore\": {}" + "}"; + auto bootstrap_or = GrpcXdsBootstrap::Create(json_str); + ASSERT_TRUE(bootstrap_or.ok()) << bootstrap_or.status(); + auto bootstrap = std::move(*bootstrap_or); + EXPECT_THAT(bootstrap->servers(), + ::testing::ElementsAre(EqXdsServer("fake:///lb1", "fake"), + EqXdsServer("fake:///lb2", "fake"))); + auto* authority = static_cast( + bootstrap->LookupAuthority("xds.example.com")); + ASSERT_NE(authority, nullptr); + EXPECT_THAT( + authority->servers(), + ::testing::ElementsAre(EqXdsServer("fake:///xds_server", "fake"), + EqXdsServer("fake:///xds_server2", "fake"))); +} + } // namespace } // namespace testing } // namespace grpc_core From 2d88de979e4581a5f8de3c5c73a524773fc77e2f Mon Sep 17 00:00:00 2001 From: Yijie Ma Date: Wed, 20 Mar 2024 14:44:42 -0700 Subject: [PATCH 04/15] [test] Use std::regex_search in no_logging test (#36131) Closes #36131 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36131 from yijiem:no-logging f3f638176f0b45fff416b21cf1b959c9a936badb PiperOrigin-RevId: 617630514 --- test/core/end2end/tests/no_logging.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/end2end/tests/no_logging.cc b/test/core/end2end/tests/no_logging.cc index d83537529ae..c9f0b99af9d 100644 --- a/test/core/end2end/tests/no_logging.cc +++ b/test/core/end2end/tests/no_logging.cc @@ -87,7 +87,7 @@ class Verifier { } auto it = allowed_logs_by_module->find(filename); if (it != allowed_logs_by_module->end() && - std::regex_match(args->message, it->second)) { + std::regex_search(args->message, it->second)) { gpr_default_log(args); return; } From bd335033e29c321669c14a128526a3f727300c59 Mon Sep 17 00:00:00 2001 From: Akshay Shah Date: Wed, 20 Mar 2024 15:04:00 -0700 Subject: [PATCH 05/15] [docs] Clarify expected semantics of deflate compression (#36113) I was surprised to see that the C++ core interprets "grpc-accept-encoding: deflate" like HTTP: it compresses messages using zlib with deflate compression, rather than using raw deflate. Matching HTTP semantics makes sense, of course, but this misnomer has historically confused HTTP implementations too. This detail didn't seem important enough to warrant inclusion in the main protocol specification, so I've proposed an addition to `docs/compression.md` to document the expected behavior. I'm happy to move the addition around if you'd prefer it elsewhere. Closes #36113 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36113 from akshayjshah:deflate 9177d39d6340269452c492c7ed2934036cdb6206 PiperOrigin-RevId: 617635558 --- doc/compression.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/compression.md b/doc/compression.md index 7f0c3823e77..9df67777e37 100644 --- a/doc/compression.md +++ b/doc/compression.md @@ -90,6 +90,15 @@ The inheritance of the compression configuration by child RPCs is left up to the implementation. Note that in the absence of changes to the parent channel, its configuration will be used. +### Deflate Compression + +Like HTTP implementations, gRPC implementations MUST use the "deflate" +compression to mean the zlib structure (defined in +[RFC 1950](https://datatracker.ietf.org/doc/html/rfc1950)) +with the deflate compression algorithm (defined in +[RFC 1951](https://datatracker.ietf.org/doc/html/rfc1951)). +Servers and clients MUST NOT send raw deflate data. + ### Test cases 1. When a compression level is not specified for either the channel or the From 1ce1159a7513a667df844bd23042cc1ce2bc1a2a Mon Sep 17 00:00:00 2001 From: Esun Kim Date: Wed, 20 Mar 2024 16:14:00 -0700 Subject: [PATCH 06/15] [CI] Moved to Bazel 7 (#36105) Let's use Bazel 7 by default. Closes #36105 PiperOrigin-RevId: 617653203 --- .bazelversion | 2 +- bazel/supported_versions.txt | 2 +- doc/bazel_support.md | 2 +- tools/bazelify_tests/dockerimage_current_versions.bzl | 8 ++++---- tools/bazelify_tests/test/supported_bazel_versions.bzl | 2 +- tools/dockerfile/test/bazel.current_version | 2 +- tools/dockerfile/test/bazel/Dockerfile | 2 +- tools/dockerfile/test/bazel_arm64.current_version | 2 +- tools/dockerfile/test/bazel_arm64/Dockerfile | 2 +- .../dockerfile/test/binder_transport_apk.current_version | 2 +- tools/dockerfile/test/binder_transport_apk/Dockerfile | 2 +- tools/dockerfile/test/sanity.current_version | 2 +- tools/dockerfile/test/sanity/Dockerfile | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.bazelversion b/.bazelversion index f22d756da39..a3fcc7121bb 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -6.5.0 +7.1.0 diff --git a/bazel/supported_versions.txt b/bazel/supported_versions.txt index 73d8dc3a64c..c8f25c10a24 100644 --- a/bazel/supported_versions.txt +++ b/bazel/supported_versions.txt @@ -1,2 +1,2 @@ -6.5.0 7.1.0 +6.5.0 diff --git a/doc/bazel_support.md b/doc/bazel_support.md index 08cb014f106..da84c49abc5 100644 --- a/doc/bazel_support.md +++ b/doc/bazel_support.md @@ -43,7 +43,7 @@ However individual releases may have a broader compatibility range. The currently supported versions are captured by the following list: -- [`6.5.0`](https://github.com/bazelbuild/bazel/releases/tag/6.5.0) - [`7.1.0`](https://github.com/bazelbuild/bazel/releases/tag/7.1.0) +- [`6.5.0`](https://github.com/bazelbuild/bazel/releases/tag/6.5.0) NOTE: gRPC doesn't support bzlmod yet. \ No newline at end of file diff --git a/tools/bazelify_tests/dockerimage_current_versions.bzl b/tools/bazelify_tests/dockerimage_current_versions.bzl index e83a0d9a88b..323ce5b6694 100644 --- a/tools/bazelify_tests/dockerimage_current_versions.bzl +++ b/tools/bazelify_tests/dockerimage_current_versions.bzl @@ -88,9 +88,9 @@ DOCKERIMAGE_CURRENT_VERSIONS = { "tools/dockerfile/interoptest/grpc_interop_ruby.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/grpc_interop_ruby@sha256:efd7f41a736dd4b8f73b32f5215b86f6bfe9013c422dfcd77978de0253aaee45", "tools/dockerfile/interoptest/lb_interop_fake_servers.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/lb_interop_fake_servers@sha256:b89a51dd9147e1293f50ee64dd719fce5929ca7894d3770a3d80dbdecb99fd52", "tools/dockerfile/test/android_ndk.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/android_ndk@sha256:ab154ecb062af2111d2d3550c4d3da3384201d9893bbd37d49e8160fc34bc137", - "tools/dockerfile/test/bazel.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/bazel@sha256:eb327f8e44f2712f557de1d8918c41c3cba1112c4b39b13104c29211ed8f827a", - "tools/dockerfile/test/bazel_arm64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/bazel_arm64@sha256:6cddc0ecdb42a7db7105b73fc3192edb911702102d1bac671e26d44a17d7aa95", - "tools/dockerfile/test/binder_transport_apk.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk@sha256:ff64e263dfa5491ee6fddd7f0d7c1a20ba756636655849a3b923c665d78c8ef2", + "tools/dockerfile/test/bazel.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/bazel@sha256:13ac6e425df68bcbee5898bb349171781597416bb93a84c4b923390e078602be", + "tools/dockerfile/test/bazel_arm64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/bazel_arm64@sha256:112e4f5085b43df2c02852f23c665aa5310e5a44ea3f4ae553a21b882a9b56aa", + "tools/dockerfile/test/binder_transport_apk.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk@sha256:498798c02e414c19c85781c245ca641f94f1494a47edec7861316d91b2d635e5", "tools/dockerfile/test/csharp_debian11_arm64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/csharp_debian11_arm64@sha256:4d4bc5f15e03f3d3d8fd889670ecde2c66a2e4d2dd9db80733c05c1d90c8a248", "tools/dockerfile/test/csharp_debian11_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/csharp_debian11_x64@sha256:b2e5c47d986312ea0850e2f2e696b45d23ee0aabceea161d31e28559e19ec4a5", "tools/dockerfile/test/cxx_alpine_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/cxx_alpine_x64@sha256:f2019edf9f2afd5042567f11afb1aa78a789fc9acdcce5ee0c14cc11f6830ed7", @@ -112,5 +112,5 @@ DOCKERIMAGE_CURRENT_VERSIONS = { "tools/dockerfile/test/rbe_ubuntu2004.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/rbe_ubuntu2004@sha256:d3951aeadf43e3bee6adc5b86d26cdaf0b9d1b5baf790d7b2530d1c197adc9f8", "tools/dockerfile/test/ruby_debian11_arm64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_debian11_arm64@sha256:d2e79919b2e2d4cc36a29682ecb5170641df4fb506cfb453978ffdeb8a841bd9", "tools/dockerfile/test/ruby_debian11_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_debian11_x64@sha256:f8fc0ec22065278e5bc02ad7f9a68191e46d083035b3a90ed587561dba9c58c5", - "tools/dockerfile/test/sanity.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/sanity@sha256:a83cf1344c166834d76f49e08448f4253b535cdbc47efffb195cfa710f5114d6", + "tools/dockerfile/test/sanity.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/sanity@sha256:f9f5bdecfb8ea805b697e55b64a64827c683b507b3cbcc683e2f0101c9bc1643", } diff --git a/tools/bazelify_tests/test/supported_bazel_versions.bzl b/tools/bazelify_tests/test/supported_bazel_versions.bzl index e53bf51d06b..77d1cde5887 100644 --- a/tools/bazelify_tests/test/supported_bazel_versions.bzl +++ b/tools/bazelify_tests/test/supported_bazel_versions.bzl @@ -17,6 +17,6 @@ This file is generated from the supported_bazel_versions.bzl.template """ SUPPORTED_BAZEL_VERSIONS = [ - "6.5.0", "7.1.0", + "6.5.0", ] diff --git a/tools/dockerfile/test/bazel.current_version b/tools/dockerfile/test/bazel.current_version index 39fe083900c..895c31c5916 100644 --- a/tools/dockerfile/test/bazel.current_version +++ b/tools/dockerfile/test/bazel.current_version @@ -1 +1 @@ -us-docker.pkg.dev/grpc-testing/testing-images-public/bazel:71afcbd2698751336bd9890d00eb37ed790b3ac6@sha256:eb327f8e44f2712f557de1d8918c41c3cba1112c4b39b13104c29211ed8f827a \ No newline at end of file +us-docker.pkg.dev/grpc-testing/testing-images-public/bazel:f49cc7eb69c326a62a936c5b4cdadc5f651df857@sha256:13ac6e425df68bcbee5898bb349171781597416bb93a84c4b923390e078602be \ No newline at end of file diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index b85b8a207d6..aecc460d1d5 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -38,7 +38,7 @@ RUN apt-get update && apt-get -y install \ # Bazel installation # Must be in sync with tools/bazel -ENV BAZEL_VERSION 6.5.0 +ENV BAZEL_VERSION 7.1.0 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper. ENV DISABLE_BAZEL_WRAPPER 1 diff --git a/tools/dockerfile/test/bazel_arm64.current_version b/tools/dockerfile/test/bazel_arm64.current_version index eccc25d1444..8c5a4ea3300 100644 --- a/tools/dockerfile/test/bazel_arm64.current_version +++ b/tools/dockerfile/test/bazel_arm64.current_version @@ -1 +1 @@ -us-docker.pkg.dev/grpc-testing/testing-images-public/bazel_arm64:415b428a3108de92d1d819cd053181a110a8078b@sha256:6cddc0ecdb42a7db7105b73fc3192edb911702102d1bac671e26d44a17d7aa95 \ No newline at end of file +us-docker.pkg.dev/grpc-testing/testing-images-public/bazel_arm64:359ba8a4ea06e806f244b9488794fa23d0ae339f@sha256:112e4f5085b43df2c02852f23c665aa5310e5a44ea3f4ae553a21b882a9b56aa \ No newline at end of file diff --git a/tools/dockerfile/test/bazel_arm64/Dockerfile b/tools/dockerfile/test/bazel_arm64/Dockerfile index 8efb0ef1b22..5d357ee5541 100644 --- a/tools/dockerfile/test/bazel_arm64/Dockerfile +++ b/tools/dockerfile/test/bazel_arm64/Dockerfile @@ -97,7 +97,7 @@ RUN apt-get update && apt-get -y install libc++-dev clang && apt-get clean # Bazel installation # Must be in sync with tools/bazel -ENV BAZEL_VERSION 6.5.0 +ENV BAZEL_VERSION 7.1.0 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper. ENV DISABLE_BAZEL_WRAPPER 1 diff --git a/tools/dockerfile/test/binder_transport_apk.current_version b/tools/dockerfile/test/binder_transport_apk.current_version index bbb66248e57..d4c2d767fcb 100644 --- a/tools/dockerfile/test/binder_transport_apk.current_version +++ b/tools/dockerfile/test/binder_transport_apk.current_version @@ -1 +1 @@ -us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk:611a0d410d3032bc41175599a5f1495a07759c1f@sha256:ff64e263dfa5491ee6fddd7f0d7c1a20ba756636655849a3b923c665d78c8ef2 +us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk:d67135c8089a0721c8918828145d949127c34e7f@sha256:498798c02e414c19c85781c245ca641f94f1494a47edec7861316d91b2d635e5 \ No newline at end of file diff --git a/tools/dockerfile/test/binder_transport_apk/Dockerfile b/tools/dockerfile/test/binder_transport_apk/Dockerfile index 1e053dc599a..79260545bfa 100644 --- a/tools/dockerfile/test/binder_transport_apk/Dockerfile +++ b/tools/dockerfile/test/binder_transport_apk/Dockerfile @@ -38,7 +38,7 @@ RUN apt-get update && apt-get -y install \ # Bazel installation # Must be in sync with tools/bazel -ENV BAZEL_VERSION 6.5.0 +ENV BAZEL_VERSION 7.1.0 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper. ENV DISABLE_BAZEL_WRAPPER 1 diff --git a/tools/dockerfile/test/sanity.current_version b/tools/dockerfile/test/sanity.current_version index f05e8d51456..14d1a67e690 100644 --- a/tools/dockerfile/test/sanity.current_version +++ b/tools/dockerfile/test/sanity.current_version @@ -1 +1 @@ -us-docker.pkg.dev/grpc-testing/testing-images-public/sanity:38e0bdb9e26335d2d947263d33efa0f688dcd2fc@sha256:a83cf1344c166834d76f49e08448f4253b535cdbc47efffb195cfa710f5114d6 \ No newline at end of file +us-docker.pkg.dev/grpc-testing/testing-images-public/sanity:ed5f64033b5ac0038b25be49f8e53439e000461f@sha256:f9f5bdecfb8ea805b697e55b64a64827c683b507b3cbcc683e2f0101c9bc1643 \ No newline at end of file diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index c75124fa18a..c094d4dfbb5 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -108,7 +108,7 @@ RUN apt-get update && apt-get install -y jq git && apt-get clean # Bazel installation # Must be in sync with tools/bazel -ENV BAZEL_VERSION 6.5.0 +ENV BAZEL_VERSION 7.1.0 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper. ENV DISABLE_BAZEL_WRAPPER 1 From 277c82dc8c29d98564e5b846646fb5301adc88c4 Mon Sep 17 00:00:00 2001 From: AJ Heller Date: Wed, 20 Mar 2024 21:47:37 -0700 Subject: [PATCH 07/15] [build] Fix fix_build_deps.py (#36152) Broken in https://github.com/grpc/grpc/pull/36116 Closes #36152 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36152 from drfloob:fix/fix_build_deps/36116 e74054a3f30632863364d15d778eae48b24d2d15 PiperOrigin-RevId: 617721871 --- tools/distrib/fix_build_deps.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/distrib/fix_build_deps.py b/tools/distrib/fix_build_deps.py index 9dc0445ddd9..f0d4f3f9a67 100755 --- a/tools/distrib/fix_build_deps.py +++ b/tools/distrib/fix_build_deps.py @@ -439,6 +439,7 @@ for dirname in [ "grpc_package": lambda **kwargs: None, "filegroup": lambda name, **kwargs: None, "sh_library": lambda name, **kwargs: None, + "platform": lambda name, **kwargs: None, }, {}, ) From a1535ae615dc8edf18f71b6ff6f1510c521e371d Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 21 Mar 2024 11:03:21 -0700 Subject: [PATCH 08/15] [CSM] Cleanup and test Size() on MeshLabelsIterable (#35769) Adding testing for `Size()` on `MeshLabelsIterable` as promised on https://github.com/grpc/grpc/pull/35371 This method doesn't get used the OTel C++ library at present so it was untested earlier, and bugs in its implementation were noticed later. To avoid that issue in the future, adding manual testing of this method. Changes - * Moved `MeshLabelsIterable` to the header to be able to test its Size method directly. Also had to move around some internals to be able to do so. * Replaced `absl::variant metadata_` from decoding the metadata lazily to just decoding it in the constructor. I don't remember the original thinking behind this. Maybe I wanted the decoding to happen lazily, but there doesn't seem to be much gain from doing it lazily, we instead have to deal with the overhead of `variant`. Closes #35769 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35769 from yashykt:CsmMeshLabelsIterableSizeTesting ec9033b74275df3c81041e357f0bc271de191904 PiperOrigin-RevId: 617901839 --- src/cpp/ext/csm/metadata_exchange.cc | 243 +++++++++------------ src/cpp/ext/csm/metadata_exchange.h | 41 ++++ test/cpp/ext/csm/metadata_exchange_test.cc | 187 +++++++++++++--- 3 files changed, 306 insertions(+), 165 deletions(-) diff --git a/src/cpp/ext/csm/metadata_exchange.cc b/src/cpp/ext/csm/metadata_exchange.cc index 340fbf36fda..c4908efe85e 100644 --- a/src/cpp/ext/csm/metadata_exchange.cc +++ b/src/cpp/ext/csm/metadata_exchange.cc @@ -34,10 +34,8 @@ #include "absl/strings/strip.h" #include "absl/types/optional.h" #include "absl/types/variant.h" -#include "google/protobuf/struct.upb.h" #include "opentelemetry/sdk/resource/semantic_conventions.h" #include "upb/base/string_view.h" -#include "upb/mem/arena.hpp" #include @@ -91,7 +89,24 @@ constexpr absl::string_view kPeerCanonicalServiceAttribute = constexpr absl::string_view kGkeType = "gcp_kubernetes_engine"; constexpr absl::string_view kGceType = "gcp_compute_engine"; -enum class GcpResourceType : std::uint8_t { kGke, kGce, kUnknown }; +// A helper method that decodes the remote metadata \a slice as a protobuf +// Struct allocated on \a arena. +google_protobuf_Struct* DecodeMetadata(grpc_core::Slice slice, + upb_Arena* arena) { + // Treat an empty slice as an invalid metadata value. + if (slice.empty()) { + return nullptr; + } + // Decode the slice. + std::string decoded_metadata; + bool metadata_decoded = + absl::Base64Unescape(slice.as_string_view(), &decoded_metadata); + if (metadata_decoded) { + return google_protobuf_Struct_parse(decoded_metadata.c_str(), + decoded_metadata.size(), arena); + } + return nullptr; +} // A minimal class for helping with the information we need from the xDS // bootstrap file for GSM Observability reasons. @@ -145,13 +160,14 @@ std::string GetXdsBootstrapContents() { return ""; } -GcpResourceType StringToGcpResourceType(absl::string_view type) { +MeshLabelsIterable::GcpResourceType StringToGcpResourceType( + absl::string_view type) { if (type == kGkeType) { - return GcpResourceType::kGke; + return MeshLabelsIterable::GcpResourceType::kGke; } else if (type == kGceType) { - return GcpResourceType::kGce; + return MeshLabelsIterable::GcpResourceType::kGce; } - return GcpResourceType::kUnknown; + return MeshLabelsIterable::GcpResourceType::kUnknown; } upb_StringView AbslStrToUpbStr(absl::string_view str) { @@ -203,147 +219,96 @@ absl::string_view GetStringValueFromUpbStruct(google_protobuf_Struct* struct_pb, return "unknown"; } -class MeshLabelsIterable : public LabelsIterable { - public: - explicit MeshLabelsIterable( - const std::vector>& - local_labels, - grpc_core::Slice remote_metadata) - : local_labels_(local_labels), metadata_(std::move(remote_metadata)) {} - - absl::optional> Next() - override { - auto& struct_pb = GetDecodedMetadata(); - size_t local_labels_size = local_labels_.size(); - if (pos_ < local_labels_size) { - return local_labels_[pos_++]; - } - const size_t fixed_attribute_end = - local_labels_size + kFixedAttributes.size(); - if (pos_ < fixed_attribute_end) { - return NextFromAttributeList(struct_pb, kFixedAttributes, - local_labels_size); - } - return NextFromAttributeList(struct_pb, GetAttributesForType(remote_type_), - fixed_attribute_end); - } - - size_t Size() const override { - return local_labels_.size() + kFixedAttributes.size() + - GetAttributesForType(remote_type_).size(); - } +struct RemoteAttribute { + absl::string_view otel_attribute; + absl::string_view metadata_attribute; +}; - void ResetIteratorPosition() override { pos_ = 0; } +constexpr std::array kFixedAttributes = { + RemoteAttribute{kPeerTypeAttribute, kMetadataExchangeTypeKey}, + RemoteAttribute{kPeerCanonicalServiceAttribute, + kMetadataExchangeCanonicalServiceKey}, +}; - // Returns true if the peer sent a non-empty base64 encoded - // "x-envoy-peer-metadata" metadata. - bool GotRemoteLabels() const { - return GetDecodedMetadata().struct_pb != nullptr; - } +constexpr std::array kGkeAttributeList = { + RemoteAttribute{kPeerWorkloadNameAttribute, + kMetadataExchangeWorkloadNameKey}, + RemoteAttribute{kPeerNamespaceNameAttribute, + kMetadataExchangeNamespaceNameKey}, + RemoteAttribute{kPeerClusterNameAttribute, kMetadataExchangeClusterNameKey}, + RemoteAttribute{kPeerLocationAttribute, kMetadataExchangeLocationKey}, + RemoteAttribute{kPeerProjectIdAttribute, kMetadataExchangeProjectIdKey}, +}; - private: - struct RemoteAttribute { - absl::string_view otel_attribute; - absl::string_view metadata_attribute; - }; +constexpr std::array kGceAttributeList = { + RemoteAttribute{kPeerWorkloadNameAttribute, + kMetadataExchangeWorkloadNameKey}, + RemoteAttribute{kPeerLocationAttribute, kMetadataExchangeLocationKey}, + RemoteAttribute{kPeerProjectIdAttribute, kMetadataExchangeProjectIdKey}, +}; - struct StructPb { - upb::Arena arena; - google_protobuf_Struct* struct_pb = nullptr; - }; +absl::Span GetAttributesForType( + MeshLabelsIterable::GcpResourceType remote_type) { + switch (remote_type) { + case MeshLabelsIterable::GcpResourceType::kGke: + return kGkeAttributeList; + case MeshLabelsIterable::GcpResourceType::kGce: + return kGceAttributeList; + default: + return {}; + } +} - static constexpr std::array kFixedAttributes = { - RemoteAttribute{kPeerTypeAttribute, kMetadataExchangeTypeKey}, - RemoteAttribute{kPeerCanonicalServiceAttribute, - kMetadataExchangeCanonicalServiceKey}, - }; +absl::optional> +NextFromAttributeList(absl::Span attributes, + size_t start_index, size_t curr, + google_protobuf_Struct* decoded_metadata, + upb_Arena* arena) { + GPR_DEBUG_ASSERT(curr >= start_index); + const size_t index = curr - start_index; + if (index >= attributes.size()) return absl::nullopt; + const auto& attribute = attributes[index]; + return std::make_pair( + attribute.otel_attribute, + GetStringValueFromUpbStruct(decoded_metadata, + attribute.metadata_attribute, arena)); +} - static constexpr std::array kGkeAttributeList = { - RemoteAttribute{kPeerWorkloadNameAttribute, - kMetadataExchangeWorkloadNameKey}, - RemoteAttribute{kPeerNamespaceNameAttribute, - kMetadataExchangeNamespaceNameKey}, - RemoteAttribute{kPeerClusterNameAttribute, - kMetadataExchangeClusterNameKey}, - RemoteAttribute{kPeerLocationAttribute, kMetadataExchangeLocationKey}, - RemoteAttribute{kPeerProjectIdAttribute, kMetadataExchangeProjectIdKey}, - }; - static constexpr std::array kGceAttributeList = { - RemoteAttribute{kPeerWorkloadNameAttribute, - kMetadataExchangeWorkloadNameKey}, - RemoteAttribute{kPeerLocationAttribute, kMetadataExchangeLocationKey}, - RemoteAttribute{kPeerProjectIdAttribute, kMetadataExchangeProjectIdKey}, - }; +} // namespace - static absl::Span GetAttributesForType( - GcpResourceType remote_type) { - switch (remote_type) { - case GcpResourceType::kGke: - return kGkeAttributeList; - case GcpResourceType::kGce: - return kGceAttributeList; - default: - return {}; - } - } +// +// MeshLabelsIterable +// - absl::optional> - NextFromAttributeList(const StructPb& struct_pb, - absl::Span attributes, - size_t start_index) { - GPR_DEBUG_ASSERT(pos_ >= start_index); - const size_t index = pos_ - start_index; - if (index >= attributes.size()) return absl::nullopt; - ++pos_; - const auto& attribute = attributes[index]; - return std::make_pair(attribute.otel_attribute, - GetStringValueFromUpbStruct( - struct_pb.struct_pb, attribute.metadata_attribute, - struct_pb.arena.ptr())); +MeshLabelsIterable::MeshLabelsIterable( + const std::vector>& local_labels, + grpc_core::Slice remote_metadata) + : struct_pb_(DecodeMetadata(std::move(remote_metadata), arena_.ptr())), + local_labels_(local_labels), + remote_type_(StringToGcpResourceType(GetStringValueFromUpbStruct( + struct_pb_, kMetadataExchangeTypeKey, arena_.ptr()))) {} + +absl::optional> +MeshLabelsIterable::Next() { + size_t local_labels_size = local_labels_.size(); + if (pos_ < local_labels_size) { + return local_labels_[pos_++]; } - - StructPb& GetDecodedMetadata() const { - auto* slice = absl::get_if(&metadata_); - if (slice == nullptr) { - return absl::get(metadata_); - } - // Treat an empty slice as an invalid metadata value. - if (slice->empty()) { - metadata_ = StructPb{}; - auto& struct_pb = absl::get(metadata_); - return struct_pb; - } - std::string decoded_metadata; - bool metadata_decoded = - absl::Base64Unescape(slice->as_string_view(), &decoded_metadata); - metadata_ = StructPb{}; - auto& struct_pb = absl::get(metadata_); - if (metadata_decoded) { - struct_pb.struct_pb = google_protobuf_Struct_parse( - decoded_metadata.c_str(), decoded_metadata.size(), - struct_pb.arena.ptr()); - remote_type_ = StringToGcpResourceType(GetStringValueFromUpbStruct( - struct_pb.struct_pb, kMetadataExchangeTypeKey, - struct_pb.arena.ptr())); - } - return struct_pb; + const size_t fixed_attribute_end = + local_labels_size + kFixedAttributes.size(); + if (pos_ < fixed_attribute_end) { + return NextFromAttributeList(kFixedAttributes, local_labels_size, pos_++, + struct_pb_, arena_.ptr()); } + return NextFromAttributeList(GetAttributesForType(remote_type_), + fixed_attribute_end, pos_++, struct_pb_, + arena_.ptr()); +} - const std::vector>& local_labels_; - // Holds either the metadata slice or the decoded proto struct. - mutable absl::variant metadata_; - mutable GcpResourceType remote_type_ = GcpResourceType::kUnknown; - uint32_t pos_ = 0; -}; - -constexpr std::array - MeshLabelsIterable::kFixedAttributes; -constexpr std::array - MeshLabelsIterable::kGkeAttributeList; -constexpr std::array - MeshLabelsIterable::kGceAttributeList; - -} // namespace +size_t MeshLabelsIterable::Size() const { + return local_labels_.size() + kFixedAttributes.size() + + GetAttributesForType(remote_type_).size(); +} // Returns the mesh ID by reading and parsing the bootstrap file. Returns // "unknown" if for some reason, mesh ID could not be figured out. @@ -370,6 +335,10 @@ std::string GetMeshId() { return std::string(mesh_id); } +// +// ServiceMeshLabelsInjector +// + ServiceMeshLabelsInjector::ServiceMeshLabelsInjector( const opentelemetry::sdk::common::AttributeMap& map) { upb::Arena arena; diff --git a/src/cpp/ext/csm/metadata_exchange.h b/src/cpp/ext/csm/metadata_exchange.h index ab74b1916fa..560a07f1e97 100644 --- a/src/cpp/ext/csm/metadata_exchange.h +++ b/src/cpp/ext/csm/metadata_exchange.h @@ -27,7 +27,9 @@ #include #include "absl/strings/string_view.h" +#include "google/protobuf/struct.upb.h" #include "opentelemetry/sdk/common/attribute_utils.h" +#include "upb/mem/arena.hpp" #include "src/core/lib/slice/slice.h" #include "src/core/lib/transport/metadata_batch.h" @@ -66,11 +68,50 @@ class ServiceMeshLabelsInjector : public LabelsInjector { absl::Span>> optional_labels_span) const override; + const std::vector>& + TestOnlyLocalLabels() const { + return local_labels_; + } + + const grpc_core::Slice& TestOnlySerializedLabels() const { + return serialized_labels_to_send_; + } + private: std::vector> local_labels_; grpc_core::Slice serialized_labels_to_send_; }; +// A LabelsIterable class provided by ServiceMeshLabelsInjector. EXPOSED FOR +// TESTING PURPOSES ONLY. +class MeshLabelsIterable : public LabelsIterable { + public: + enum class GcpResourceType : std::uint8_t { kGke, kGce, kUnknown }; + + MeshLabelsIterable( + const std::vector>& + local_labels, + grpc_core::Slice remote_metadata); + + absl::optional> Next() + override; + + size_t Size() const override; + + void ResetIteratorPosition() override { pos_ = 0; } + + // Returns true if the peer sent a non-empty base64 encoded + // "x-envoy-peer-metadata" metadata. + bool GotRemoteLabels() const { return struct_pb_ != nullptr; } + + private: + upb::Arena arena_; + google_protobuf_Struct* struct_pb_ = nullptr; + const std::vector>& local_labels_; + GcpResourceType remote_type_ = GcpResourceType::kUnknown; + uint32_t pos_ = 0; +}; + // Returns the mesh ID by reading and parsing the bootstrap file. Returns // "unknown" if for some reason, mesh ID could not be figured out. // EXPOSED FOR TESTING PURPOSES ONLY. diff --git a/test/cpp/ext/csm/metadata_exchange_test.cc b/test/cpp/ext/csm/metadata_exchange_test.cc index 19667491da3..67299f73e40 100644 --- a/test/cpp/ext/csm/metadata_exchange_test.cc +++ b/test/cpp/ext/csm/metadata_exchange_test.cc @@ -43,6 +43,35 @@ namespace grpc { namespace testing { namespace { +using ::testing::ElementsAre; +using ::testing::Pair; + +opentelemetry::sdk::resource::Resource TestGkeResource() { + opentelemetry::sdk::common::AttributeMap attributes; + attributes.SetAttribute("cloud.platform", "gcp_kubernetes_engine"); + attributes.SetAttribute("k8s.pod.name", "pod"); + attributes.SetAttribute("k8s.container.name", "container"); + attributes.SetAttribute("k8s.namespace.name", "namespace"); + attributes.SetAttribute("k8s.cluster.name", "cluster"); + attributes.SetAttribute("cloud.region", "region"); + attributes.SetAttribute("cloud.account.id", "id"); + return opentelemetry::sdk::resource::Resource::Create(attributes); +} + +opentelemetry::sdk::resource::Resource TestGceResource() { + opentelemetry::sdk::common::AttributeMap attributes; + attributes.SetAttribute("cloud.platform", "gcp_compute_engine"); + attributes.SetAttribute("cloud.availability_zone", "zone"); + attributes.SetAttribute("cloud.account.id", "id"); + return opentelemetry::sdk::resource::Resource::Create(attributes); +} + +opentelemetry::sdk::resource::Resource TestUnknownResource() { + opentelemetry::sdk::common::AttributeMap attributes; + attributes.SetAttribute("cloud.platform", "random"); + return opentelemetry::sdk::resource::Resource::Create(attributes); +} + class TestScenario { public: enum class ResourceType : std::uint8_t { kGke, kGce, kUnknown }; @@ -91,32 +120,6 @@ class TestScenario { XdsBootstrapSource bootstrap_source() const { return bootstrap_source_; } private: - static opentelemetry::sdk::resource::Resource TestGkeResource() { - opentelemetry::sdk::common::AttributeMap attributes; - attributes.SetAttribute("cloud.platform", "gcp_kubernetes_engine"); - attributes.SetAttribute("k8s.pod.name", "pod"); - attributes.SetAttribute("k8s.container.name", "container"); - attributes.SetAttribute("k8s.namespace.name", "namespace"); - attributes.SetAttribute("k8s.cluster.name", "cluster"); - attributes.SetAttribute("cloud.region", "region"); - attributes.SetAttribute("cloud.account.id", "id"); - return opentelemetry::sdk::resource::Resource::Create(attributes); - } - - static opentelemetry::sdk::resource::Resource TestGceResource() { - opentelemetry::sdk::common::AttributeMap attributes; - attributes.SetAttribute("cloud.platform", "gcp_compute_engine"); - attributes.SetAttribute("cloud.availability_zone", "zone"); - attributes.SetAttribute("cloud.account.id", "id"); - return opentelemetry::sdk::resource::Resource::Create(attributes); - } - - static opentelemetry::sdk::resource::Resource TestUnknownResource() { - opentelemetry::sdk::common::AttributeMap attributes; - attributes.SetAttribute("cloud.platform", "random"); - return opentelemetry::sdk::resource::Resource::Create(attributes); - } - ResourceType type_; XdsBootstrapSource bootstrap_source_; }; @@ -163,7 +166,7 @@ class MetadataExchangeTest case TestScenario::XdsBootstrapSource::kFromFile: { ASSERT_EQ(bootstrap_file_name_, nullptr); FILE* bootstrap_file = - gpr_tmpfile("gcp_observability_config", &bootstrap_file_name_); + gpr_tmpfile("xds_bootstrap", &bootstrap_file_name_); fputs(kBootstrap, bootstrap_file); fclose(bootstrap_file); grpc_core::SetEnv("GRPC_XDS_BOOTSTRAP", bootstrap_file_name_); @@ -186,7 +189,7 @@ class MetadataExchangeTest } ~MetadataExchangeTest() override { - grpc_core::UnsetEnv("GRPC_GCP_OBSERVABILITY_CONFIG"); + grpc_core::UnsetEnv("GRPC_XDS_BOOTSTRAP_CONFIG"); grpc_core::UnsetEnv("GRPC_XDS_BOOTSTRAP"); if (bootstrap_file_name_ != nullptr) { remove(bootstrap_file_name_); @@ -418,6 +421,134 @@ TEST_P(MetadataExchangeTest, VerifyCsmServiceLabels) { "mynamespace"); } +// Creates a serialized slice with labels for metadata exchange based on \a +// resource. +grpc_core::Slice RemoteMetadataSliceFromResource( + const opentelemetry::sdk::resource::Resource& resource) { + return grpc::internal::ServiceMeshLabelsInjector(resource.GetAttributes()) + .TestOnlySerializedLabels() + .Ref(); +} + +std::vector> LabelsFromIterable( + grpc::internal::MeshLabelsIterable* iterable) { + std::vector> labels; + while (true) { + auto label = iterable->Next(); + if (!label.has_value()) break; + labels.push_back(*std::move(label)); + } + EXPECT_EQ(labels.size(), iterable->Size()); + return labels; +} + +std::string PrettyPrintLabels( + const std::vector>& + labels) { + std::vector strings; + strings.reserve(labels.size()); + for (const auto& pair : labels) { + strings.push_back( + absl::StrFormat("{\"%s\" : \"%s\"}", pair.first, pair.second)); + } + return absl::StrJoin(strings, ", "); +} + +TEST(MeshLabelsIterableTest, NoRemoteMetadata) { + std::vector> local_labels = { + {"csm.workload_canonical_service", "canonical_service"}, + {"csm.mesh_id", "mesh"}}; + grpc::internal::MeshLabelsIterable iterable(local_labels, grpc_core::Slice()); + auto labels = LabelsFromIterable(&iterable); + EXPECT_FALSE(iterable.GotRemoteLabels()); + EXPECT_THAT( + labels, + ElementsAre(Pair("csm.workload_canonical_service", "canonical_service"), + Pair("csm.mesh_id", "mesh"), + Pair("csm.remote_workload_type", "unknown"), + Pair("csm.remote_workload_canonical_service", "unknown"))) + << PrettyPrintLabels(labels); +} + +TEST(MeshLabelsIterableTest, RemoteGceTypeMetadata) { + std::vector> local_labels = { + {"csm.workload_canonical_service", "canonical_service"}, + {"csm.mesh_id", "mesh"}}; + grpc::internal::MeshLabelsIterable iterable( + local_labels, RemoteMetadataSliceFromResource(TestGceResource())); + auto labels = LabelsFromIterable(&iterable); + EXPECT_TRUE(iterable.GotRemoteLabels()); + EXPECT_THAT( + labels, + ElementsAre( + Pair("csm.workload_canonical_service", "canonical_service"), + Pair("csm.mesh_id", "mesh"), + Pair("csm.remote_workload_type", "gcp_compute_engine"), + Pair("csm.remote_workload_canonical_service", "canonical_service"), + Pair("csm.remote_workload_name", "workload"), + Pair("csm.remote_workload_location", "zone"), + Pair("csm.remote_workload_project_id", "id"))) + << PrettyPrintLabels(labels); +} + +TEST(MeshLabelsIterableTest, RemoteGkeTypeMetadata) { + std::vector> local_labels = { + {"csm.workload_canonical_service", "canonical_service"}, + {"csm.mesh_id", "mesh"}}; + grpc::internal::MeshLabelsIterable iterable( + local_labels, RemoteMetadataSliceFromResource(TestGkeResource())); + auto labels = LabelsFromIterable(&iterable); + EXPECT_TRUE(iterable.GotRemoteLabels()); + EXPECT_THAT( + labels, + ElementsAre( + Pair("csm.workload_canonical_service", "canonical_service"), + Pair("csm.mesh_id", "mesh"), + Pair("csm.remote_workload_type", "gcp_kubernetes_engine"), + Pair("csm.remote_workload_canonical_service", "canonical_service"), + Pair("csm.remote_workload_name", "workload"), + Pair("csm.remote_workload_namespace_name", "namespace"), + Pair("csm.remote_workload_cluster_name", "cluster"), + Pair("csm.remote_workload_location", "region"), + Pair("csm.remote_workload_project_id", "id"))) + << PrettyPrintLabels(labels); +} + +TEST(MeshLabelsIterableTest, RemoteUnknownTypeMetadata) { + std::vector> local_labels = { + {"csm.workload_canonical_service", "canonical_service"}, + {"csm.mesh_id", "mesh"}}; + grpc::internal::MeshLabelsIterable iterable( + local_labels, RemoteMetadataSliceFromResource(TestUnknownResource())); + auto labels = LabelsFromIterable(&iterable); + EXPECT_TRUE(iterable.GotRemoteLabels()); + EXPECT_THAT( + labels, + ElementsAre( + Pair("csm.workload_canonical_service", "canonical_service"), + Pair("csm.mesh_id", "mesh"), + Pair("csm.remote_workload_type", "random"), + Pair("csm.remote_workload_canonical_service", "canonical_service"))) + << PrettyPrintLabels(labels); +} + +TEST(MeshLabelsIterableTest, TestResetIteratorPosition) { + std::vector> local_labels = { + {"csm.workload_canonical_service", "canonical_service"}, + {"csm.mesh_id", "mesh"}}; + grpc::internal::MeshLabelsIterable iterable(local_labels, grpc_core::Slice()); + auto labels = LabelsFromIterable(&iterable); + auto expected_labels_matcher = ElementsAre( + Pair("csm.workload_canonical_service", "canonical_service"), + Pair("csm.mesh_id", "mesh"), Pair("csm.remote_workload_type", "unknown"), + Pair("csm.remote_workload_canonical_service", "unknown")); + EXPECT_THAT(labels, expected_labels_matcher) << PrettyPrintLabels(labels); + // Resetting the iterable should return the entire list again. + iterable.ResetIteratorPosition(); + labels = LabelsFromIterable(&iterable); + EXPECT_THAT(labels, expected_labels_matcher) << PrettyPrintLabels(labels); +} + INSTANTIATE_TEST_SUITE_P( MetadataExchange, MetadataExchangeTest, ::testing::Values( From 4cf87d4c91b5d81fc93ba996a2b6081043145384 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 21 Mar 2024 14:08:39 -0700 Subject: [PATCH 09/15] [logging] Reduce line count for gRPC experiment output (#36150) Closes #36150 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36150 from ctiller:drop-the-vowels 04d04225fbf4d0f69ae2ef9bcdebcaf34a1fb958 PiperOrigin-RevId: 617958770 --- src/core/lib/experiments/config.cc | 81 +++++++++++++++++------------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/src/core/lib/experiments/config.cc b/src/core/lib/experiments/config.cc index 6a480c22db1..4210ccc3055 100644 --- a/src/core/lib/experiments/config.cc +++ b/src/core/lib/experiments/config.cc @@ -25,7 +25,7 @@ #include #include "absl/functional/any_invocable.h" -#include "absl/strings/str_cat.h" +#include "absl/strings/str_join.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" @@ -187,42 +187,53 @@ bool IsTestExperimentEnabled(size_t experiment_id) { } void PrintExperimentsList() { - size_t max_experiment_length = 0; - // Populate visitation order into a std::map so that iteration results in a - // lexical ordering of experiment names. - // The lexical ordering makes it nice and easy to find the experiment you're - // looking for in the output spam that we generate. - std::map visitation_order; + std::map experiment_status; + std::set defaulted_on_experiments; for (size_t i = 0; i < kNumExperiments; i++) { - max_experiment_length = - std::max(max_experiment_length, strlen(g_experiment_metadata[i].name)); - visitation_order[g_experiment_metadata[i].name] = i; + const char* name = g_experiment_metadata[i].name; + const bool enabled = IsExperimentEnabled(i); + const bool default_enabled = g_experiment_metadata[i].default_value; + const bool forced = g_forced_experiments[i].forced; + if (!default_enabled && !enabled) continue; + if (default_enabled && enabled) { + defaulted_on_experiments.insert(name); + continue; + } + if (enabled) { + if (g_check_constraints_cb != nullptr && + (*g_check_constraints_cb)(g_experiment_metadata[i])) { + experiment_status[name] = "on:constraints"; + continue; + } + if (forced && g_forced_experiments[i].value) { + experiment_status[name] = "on:forced"; + continue; + } + experiment_status[name] = "on"; + } else { + if (forced && !g_forced_experiments[i].value) { + experiment_status[name] = "off:forced"; + continue; + } + experiment_status[name] = "off"; + } } - for (auto name_index : visitation_order) { - const size_t i = name_index.second; - gpr_log( - GPR_INFO, "%s", - absl::StrCat( - "gRPC EXPERIMENT ", g_experiment_metadata[i].name, - std::string(max_experiment_length - - strlen(g_experiment_metadata[i].name) + 1, - ' '), - IsExperimentEnabled(i) ? "ON " : "OFF", - " (default:", g_experiment_metadata[i].default_value ? "ON" : "OFF", - (g_check_constraints_cb != nullptr - ? absl::StrCat( - " + ", g_experiment_metadata[i].additional_constaints, - " => ", - (*g_check_constraints_cb)(g_experiment_metadata[i]) - ? "ON " - : "OFF") - : std::string()), - g_forced_experiments[i].forced - ? absl::StrCat(" force:", - g_forced_experiments[i].value ? "ON" : "OFF") - : std::string(), - ")") - .c_str()); + if (experiment_status.empty()) { + if (!defaulted_on_experiments.empty()) { + gpr_log(GPR_INFO, "gRPC experiments enabled: %s", + absl::StrJoin(defaulted_on_experiments, ", ").c_str()); + } + } else { + if (defaulted_on_experiments.empty()) { + gpr_log(GPR_INFO, "gRPC experiments: %s", + absl::StrJoin(experiment_status, ", ", absl::PairFormatter(":")) + .c_str()); + } else { + gpr_log(GPR_INFO, "gRPC experiments: %s; default-enabled: %s", + absl::StrJoin(experiment_status, ", ", absl::PairFormatter(":")) + .c_str(), + absl::StrJoin(defaulted_on_experiments, ", ").c_str()); + } } } From 21b5410a4c060261c327b8db0c19e168488a55bd Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 21 Mar 2024 14:16:12 -0700 Subject: [PATCH 10/15] [event-engine] Separate promise context from default event engine headers (#36148) These two things are different (event engine being a context has nothing to do with the ability to get a default event engine). Lumping them into the same header means that things that want the context also need to want the default event engine declarations, which in turn pull in CoreConfiguration -- which ultimately means that nothing that is depended on by CoreConfiguration can consume the event engine context, which is undesirable (and causing dependency loops in current work). Also includes an impressive number of cleanups to `grpc_base` because I ran `fix_build_deps` on that target as part of this. Closes #36148 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36148 from ctiller:context-isnt-default--default-isnt-context a4fdad9621e6a102d8aa184772dc78bcfd1aad45 PiperOrigin-RevId: 617961015 --- BUILD | 48 +------------------ CMakeLists.txt | 5 -- Package.swift | 1 + build_autogenerated.yaml | 27 +++++++---- gRPC-C++.podspec | 2 + gRPC-Core.podspec | 2 + grpc.gemspec | 1 + package.xml | 1 + src/core/BUILD | 22 +++++++-- .../server_config_selector_filter.cc | 1 + .../client/chaotic_good_connector.cc | 1 - .../server/chaotic_good_server.cc | 2 +- src/core/lib/channel/promise_based_filter.h | 4 +- .../lib/event_engine/default_event_engine.h | 6 --- .../lib/event_engine/event_engine_context.h | 31 ++++++++++++ src/core/lib/promise/activity.h | 1 + src/core/lib/promise/sleep.cc | 2 +- tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core.internal | 1 + 19 files changed, 83 insertions(+), 76 deletions(-) create mode 100644 src/core/lib/event_engine/event_engine_context.h diff --git a/BUILD b/BUILD index bf8daacde4b..f847e1bcf57 100644 --- a/BUILD +++ b/BUILD @@ -1962,20 +1962,15 @@ grpc_cc_library( }), external_deps = [ "absl/base:core_headers", - "absl/cleanup", "absl/container:flat_hash_map", - "absl/container:flat_hash_set", "absl/container:inlined_vector", "absl/functional:any_invocable", "absl/functional:function_ref", - "absl/hash", "absl/meta:type_traits", - "absl/random", "absl/status", "absl/status:statusor", "absl/strings", "absl/strings:str_format", - "absl/time", "absl/types:optional", "absl/utility", "madler_zlib", @@ -1989,7 +1984,6 @@ grpc_cc_library( visibility = ["@grpc:alt_grpc_base_legacy"], deps = [ "api_trace", - "byte_buffer", "call_combiner", "call_trace", "call_tracer", @@ -1998,28 +1992,19 @@ grpc_cc_library( "channel_stack_builder", "channelz", "config", - "config_vars", "cpp_impl_of", "debug_location", - "dynamic_annotations", "exec_ctx", "gpr", "grpc_public_hdrs", "grpc_trace", "iomgr", - "iomgr_buffer_list", - "iomgr_internal_errqueue", "iomgr_timer", "legacy_context", "orphanable", - "parse_address", "promise", "ref_counted_ptr", - "resource_quota_api", - "sockaddr_utils", "stats", - "tcp_tracer", - "uri_parser", "//src/core:1999", "//src/core:activity", "//src/core:all_ok", @@ -2027,14 +2012,11 @@ grpc_cc_library( "//src/core:arena_promise", "//src/core:atomic_utils", "//src/core:bitset", - "//src/core:call_factory", "//src/core:call_filters", "//src/core:call_final_info", "//src/core:call_finalization", "//src/core:call_spine", - "//src/core:cancel_callback", "//src/core:channel_args", - "//src/core:channel_args_endpoint_config", "//src/core:channel_args_preconditioning", "//src/core:channel_fwd", "//src/core:channel_init", @@ -2043,75 +2025,47 @@ grpc_cc_library( "//src/core:closure", "//src/core:compression", "//src/core:connectivity_state", - "//src/core:construct_destruct", "//src/core:context", "//src/core:default_event_engine", - "//src/core:dual_ref_counted", "//src/core:error", "//src/core:error_utils", "//src/core:event_engine_common", - "//src/core:event_engine_extensions", - "//src/core:event_engine_memory_allocator_factory", - "//src/core:event_engine_query_extensions", - "//src/core:event_engine_shim", - "//src/core:event_engine_tcp_socket_utils", - "//src/core:event_engine_trace", - "//src/core:event_log", + "//src/core:event_engine_context", "//src/core:experiments", "//src/core:for_each", "//src/core:gpr_atm", "//src/core:gpr_manual_constructor", "//src/core:gpr_spinlock", - "//src/core:grpc_sockaddr", "//src/core:if", - "//src/core:init_internally", "//src/core:iomgr_fwd", - "//src/core:iomgr_port", - "//src/core:json", - "//src/core:json_writer", "//src/core:latch", "//src/core:loop", "//src/core:map", "//src/core:match", - "//src/core:memory_quota", "//src/core:message", "//src/core:metadata", "//src/core:metadata_batch", "//src/core:metrics", "//src/core:no_destruct", - "//src/core:per_cpu", "//src/core:pipe", "//src/core:poll", - "//src/core:pollset_set", - "//src/core:posix_event_engine_base_hdrs", - "//src/core:posix_event_engine_endpoint", "//src/core:promise_status", "//src/core:promise_trace", "//src/core:race", - "//src/core:random_early_detection", "//src/core:ref_counted", - "//src/core:resolved_address", - "//src/core:resource_quota", - "//src/core:resource_quota_trace", "//src/core:seq", "//src/core:server_interface", "//src/core:slice", "//src/core:slice_buffer", "//src/core:slice_cast", "//src/core:slice_refcount", - "//src/core:socket_mutator", "//src/core:stats_data", "//src/core:status_flag", "//src/core:status_helper", - "//src/core:strerror", - "//src/core:thread_quota", "//src/core:time", "//src/core:transport_fwd", - "//src/core:try_join", "//src/core:try_seq", "//src/core:useful", - "//src/core:windows_event_engine", - "//src/core:windows_event_engine_listener", ], ) diff --git a/CMakeLists.txt b/CMakeLists.txt index e022789d29a..27dc333c460 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5116,7 +5116,6 @@ add_library(grpc_authorization_provider src/core/lib/address_utils/parse_address.cc src/core/lib/address_utils/sockaddr_utils.cc src/core/lib/backoff/backoff.cc - src/core/lib/backoff/random_early_detection.cc src/core/lib/channel/call_tracer.cc src/core/lib/channel/channel_args.cc src/core/lib/channel/channel_args_preconditioning.cc @@ -5349,10 +5348,8 @@ add_library(grpc_authorization_provider src/core/lib/surface/version.cc src/core/lib/surface/wait_for_cq_end_op.cc src/core/lib/transport/batch_builder.cc - src/core/lib/transport/call_factory.cc src/core/lib/transport/call_filters.cc src/core/lib/transport/call_final_info.cc - src/core/lib/transport/call_size_estimator.cc src/core/lib/transport/call_spine.cc src/core/lib/transport/connectivity_state.cc src/core/lib/transport/error_utils.cc @@ -5442,8 +5439,6 @@ target_link_libraries(grpc_authorization_provider absl::function_ref absl::hash absl::type_traits - absl::random_bit_gen_ref - absl::random_distributions absl::statusor absl::span absl::utility diff --git a/Package.swift b/Package.swift index f7b1930f099..a2eee8f6ca6 100644 --- a/Package.swift +++ b/Package.swift @@ -1202,6 +1202,7 @@ let package = Package( "src/core/lib/event_engine/default_event_engine_factory.cc", "src/core/lib/event_engine/default_event_engine_factory.h", "src/core/lib/event_engine/event_engine.cc", + "src/core/lib/event_engine/event_engine_context.h", "src/core/lib/event_engine/extensions/can_track_errors.h", "src/core/lib/event_engine/extensions/chaotic_good_extension.h", "src/core/lib/event_engine/extensions/supports_fd.h", diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index a28fd37bcc2..5d9b6c355b5 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -847,6 +847,7 @@ libs: - src/core/lib/event_engine/common_closures.h - src/core/lib/event_engine/default_event_engine.h - src/core/lib/event_engine/default_event_engine_factory.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/event_engine/extensions/can_track_errors.h - src/core/lib/event_engine/extensions/chaotic_good_extension.h - src/core/lib/event_engine/extensions/supports_fd.h @@ -2355,6 +2356,7 @@ libs: - src/core/lib/event_engine/common_closures.h - src/core/lib/event_engine/default_event_engine.h - src/core/lib/event_engine/default_event_engine_factory.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/event_engine/extensions/can_track_errors.h - src/core/lib/event_engine/extensions/chaotic_good_extension.h - src/core/lib/event_engine/extensions/supports_fd.h @@ -4405,7 +4407,6 @@ libs: - src/core/lib/address_utils/sockaddr_utils.h - src/core/lib/avl/avl.h - src/core/lib/backoff/backoff.h - - src/core/lib/backoff/random_early_detection.h - src/core/lib/channel/call_finalization.h - src/core/lib/channel/call_tracer.h - src/core/lib/channel/channel_args.h @@ -4441,6 +4442,7 @@ libs: - src/core/lib/event_engine/common_closures.h - src/core/lib/event_engine/default_event_engine.h - src/core/lib/event_engine/default_event_engine_factory.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/event_engine/extensions/can_track_errors.h - src/core/lib/event_engine/extensions/chaotic_good_extension.h - src/core/lib/event_engine/extensions/supports_fd.h @@ -4599,7 +4601,6 @@ libs: - src/core/lib/promise/activity.h - src/core/lib/promise/all_ok.h - src/core/lib/promise/arena_promise.h - - src/core/lib/promise/cancel_callback.h - src/core/lib/promise/context.h - src/core/lib/promise/detail/basic_seq.h - src/core/lib/promise/detail/join_state.h @@ -4623,7 +4624,6 @@ libs: - src/core/lib/promise/seq.h - src/core/lib/promise/status_flag.h - src/core/lib/promise/trace.h - - src/core/lib/promise/try_join.h - src/core/lib/promise/try_seq.h - src/core/lib/resource_quota/api.h - src/core/lib/resource_quota/arena.h @@ -4687,10 +4687,8 @@ libs: - src/core/lib/surface/validate_metadata.h - src/core/lib/surface/wait_for_cq_end_op.h - src/core/lib/transport/batch_builder.h - - src/core/lib/transport/call_factory.h - src/core/lib/transport/call_filters.h - src/core/lib/transport/call_final_info.h - - src/core/lib/transport/call_size_estimator.h - src/core/lib/transport/call_spine.h - src/core/lib/transport/connectivity_state.h - src/core/lib/transport/custom_metadata.h @@ -4758,7 +4756,6 @@ libs: - src/core/lib/address_utils/parse_address.cc - src/core/lib/address_utils/sockaddr_utils.cc - src/core/lib/backoff/backoff.cc - - src/core/lib/backoff/random_early_detection.cc - src/core/lib/channel/call_tracer.cc - src/core/lib/channel/channel_args.cc - src/core/lib/channel/channel_args_preconditioning.cc @@ -4991,10 +4988,8 @@ libs: - src/core/lib/surface/version.cc - src/core/lib/surface/wait_for_cq_end_op.cc - src/core/lib/transport/batch_builder.cc - - src/core/lib/transport/call_factory.cc - src/core/lib/transport/call_filters.cc - src/core/lib/transport/call_final_info.cc - - src/core/lib/transport/call_size_estimator.cc - src/core/lib/transport/call_spine.cc - src/core/lib/transport/connectivity_state.cc - src/core/lib/transport/error_utils.cc @@ -5043,8 +5038,6 @@ libs: - absl/functional:function_ref - absl/hash:hash - absl/meta:type_traits - - absl/random:bit_gen_ref - - absl/random:distributions - absl/status:statusor - absl/types:span - absl/utility:utility @@ -5233,6 +5226,7 @@ targets: language: c++ headers: - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/gprpp/atomic_utils.h - src/core/lib/gprpp/bitset.h - src/core/lib/gprpp/down_cast.h @@ -6386,6 +6380,7 @@ targets: - src/core/lib/channel/channel_args.h - src/core/lib/compression/compression_internal.h - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/experiments/config.h - src/core/lib/experiments/experiments.h - src/core/lib/gpr/spinlock.h @@ -7664,6 +7659,7 @@ targets: - src/core/ext/upb-gen/google/rpc/status.upb.h - src/core/ext/upb-gen/google/rpc/status.upb_minitable.h - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/experiments/config.h - src/core/lib/experiments/experiments.h - src/core/lib/gpr/spinlock.h @@ -9158,6 +9154,7 @@ targets: - src/core/ext/upb-gen/google/rpc/status.upb.h - src/core/ext/upb-gen/google/rpc/status.upb_minitable.h - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/experiments/config.h - src/core/lib/experiments/experiments.h - src/core/lib/gpr/spinlock.h @@ -9764,6 +9761,7 @@ targets: - src/core/ext/upb-gen/google/rpc/status.upb.h - src/core/ext/upb-gen/google/rpc/status.upb_minitable.h - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/experiments/config.h - src/core/lib/experiments/experiments.h - src/core/lib/gpr/spinlock.h @@ -9899,6 +9897,7 @@ targets: - src/core/ext/upb-gen/google/rpc/status.upb.h - src/core/ext/upb-gen/google/rpc/status.upb_minitable.h - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/experiments/config.h - src/core/lib/experiments/experiments.h - src/core/lib/gpr/spinlock.h @@ -11518,6 +11517,7 @@ targets: language: c++ headers: - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/gprpp/atomic_utils.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/orphanable.h @@ -11559,6 +11559,7 @@ targets: - src/core/ext/upb-gen/google/rpc/status.upb.h - src/core/ext/upb-gen/google/rpc/status.upb_minitable.h - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/experiments/config.h - src/core/lib/experiments/experiments.h - src/core/lib/gpr/spinlock.h @@ -12068,6 +12069,7 @@ targets: language: c++ headers: - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/gprpp/atomic_utils.h - src/core/lib/gprpp/bitset.h - src/core/lib/gprpp/down_cast.h @@ -12231,6 +12233,7 @@ targets: - src/core/ext/upb-gen/google/rpc/status.upb.h - src/core/ext/upb-gen/google/rpc/status.upb_minitable.h - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/experiments/config.h - src/core/lib/experiments/experiments.h - src/core/lib/gpr/spinlock.h @@ -12837,6 +12840,7 @@ targets: build: test language: c++ headers: + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/gprpp/atomic_utils.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/orphanable.h @@ -13125,6 +13129,7 @@ targets: build: test language: c++ headers: + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/gprpp/atomic_utils.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/notification.h @@ -14042,6 +14047,7 @@ targets: language: c++ headers: - src/core/lib/debug/trace.h + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/gprpp/atomic_utils.h - src/core/lib/gprpp/bitset.h - src/core/lib/gprpp/down_cast.h @@ -19611,6 +19617,7 @@ targets: build: test language: c++ headers: + - src/core/lib/event_engine/event_engine_context.h - src/core/lib/gprpp/atomic_utils.h - src/core/lib/gprpp/down_cast.h - src/core/lib/gprpp/notification.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index e4e0db337dc..77e9a3af608 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -930,6 +930,7 @@ Pod::Spec.new do |s| 'src/core/lib/event_engine/common_closures.h', 'src/core/lib/event_engine/default_event_engine.h', 'src/core/lib/event_engine/default_event_engine_factory.h', + 'src/core/lib/event_engine/event_engine_context.h', 'src/core/lib/event_engine/extensions/can_track_errors.h', 'src/core/lib/event_engine/extensions/chaotic_good_extension.h', 'src/core/lib/event_engine/extensions/supports_fd.h', @@ -2195,6 +2196,7 @@ Pod::Spec.new do |s| 'src/core/lib/event_engine/common_closures.h', 'src/core/lib/event_engine/default_event_engine.h', 'src/core/lib/event_engine/default_event_engine_factory.h', + 'src/core/lib/event_engine/event_engine_context.h', 'src/core/lib/event_engine/extensions/can_track_errors.h', 'src/core/lib/event_engine/extensions/chaotic_good_extension.h', 'src/core/lib/event_engine/extensions/supports_fd.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 73c31d9c6ed..859ffe4776a 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1318,6 +1318,7 @@ Pod::Spec.new do |s| 'src/core/lib/event_engine/default_event_engine_factory.cc', 'src/core/lib/event_engine/default_event_engine_factory.h', 'src/core/lib/event_engine/event_engine.cc', + 'src/core/lib/event_engine/event_engine_context.h', 'src/core/lib/event_engine/extensions/can_track_errors.h', 'src/core/lib/event_engine/extensions/chaotic_good_extension.h', 'src/core/lib/event_engine/extensions/supports_fd.h', @@ -2977,6 +2978,7 @@ Pod::Spec.new do |s| 'src/core/lib/event_engine/common_closures.h', 'src/core/lib/event_engine/default_event_engine.h', 'src/core/lib/event_engine/default_event_engine_factory.h', + 'src/core/lib/event_engine/event_engine_context.h', 'src/core/lib/event_engine/extensions/can_track_errors.h', 'src/core/lib/event_engine/extensions/chaotic_good_extension.h', 'src/core/lib/event_engine/extensions/supports_fd.h', diff --git a/grpc.gemspec b/grpc.gemspec index 4c7b75d8e43..74880a4e33c 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -1208,6 +1208,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/event_engine/default_event_engine_factory.cc ) s.files += %w( src/core/lib/event_engine/default_event_engine_factory.h ) s.files += %w( src/core/lib/event_engine/event_engine.cc ) + s.files += %w( src/core/lib/event_engine/event_engine_context.h ) s.files += %w( src/core/lib/event_engine/extensions/can_track_errors.h ) s.files += %w( src/core/lib/event_engine/extensions/chaotic_good_extension.h ) s.files += %w( src/core/lib/event_engine/extensions/supports_fd.h ) diff --git a/package.xml b/package.xml index 834f8b1aa74..9b4c2ff2849 100644 --- a/package.xml +++ b/package.xml @@ -1190,6 +1190,7 @@ + diff --git a/src/core/BUILD b/src/core/BUILD index bbc92c0bb8e..0a333928eb5 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -592,7 +592,7 @@ grpc_cc_library( deps = [ "activity", "context", - "default_event_engine", + "event_engine_context", "poll", "time", "//:event_engine_base_hdrs", @@ -906,6 +906,7 @@ grpc_cc_library( "atomic_utils", "construct_destruct", "context", + "event_engine_context", "no_destruct", "poll", "promise_factory", @@ -2608,6 +2609,21 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "event_engine_context", + hdrs = [ + "lib/event_engine/event_engine_context.h", + ], + visibility = [ + "@grpc:alt_grpc_base_legacy", + ], + deps = [ + "context", + "//:event_engine_base_hdrs", + "//:gpr", + ], +) + grpc_cc_library( name = "default_event_engine", srcs = [ @@ -2622,7 +2638,6 @@ grpc_cc_library( ], deps = [ "channel_args", - "context", "default_event_engine_factory", "event_engine_trace", "no_destruct", @@ -3549,6 +3564,7 @@ grpc_cc_library( "channel_args", "channel_fwd", "context", + "event_engine_context", "grpc_server_config_selector", "grpc_service_config", "metadata_batch", @@ -7443,10 +7459,10 @@ grpc_cc_library( "chaotic_good_settings_metadata", "closure", "context", - "default_event_engine", "error", "error_utils", "event_engine_common", + "event_engine_context", "event_engine_extensions", "event_engine_query_extensions", "event_engine_tcp_socket_utils", diff --git a/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc b/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc index fc78beba190..0be80a238a0 100644 --- a/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc +++ b/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc @@ -31,6 +31,7 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/context.h" #include "src/core/lib/channel/promise_based_filter.h" +#include "src/core/lib/event_engine/event_engine_context.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/status_helper.h" #include "src/core/lib/gprpp/sync.h" diff --git a/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc b/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc index 47f8af13760..2ef11595b04 100644 --- a/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc +++ b/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc @@ -34,7 +34,6 @@ #include "src/core/ext/transport/chaotic_good/settings_metadata.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/event_engine/channel_args_endpoint_config.h" -#include "src/core/lib/event_engine/default_event_engine.h" #include "src/core/lib/event_engine/extensions/chaotic_good_extension.h" #include "src/core/lib/event_engine/query_extensions.h" #include "src/core/lib/event_engine/tcp_socket_utils.h" diff --git a/src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc b/src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc index ec0bcac7358..70bf644c2a9 100644 --- a/src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc +++ b/src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc @@ -38,7 +38,7 @@ #include "src/core/ext/transport/chaotic_good/settings_metadata.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/event_engine/channel_args_endpoint_config.h" -#include "src/core/lib/event_engine/default_event_engine.h" +#include "src/core/lib/event_engine/event_engine_context.h" #include "src/core/lib/event_engine/extensions/chaotic_good_extension.h" #include "src/core/lib/event_engine/query_extensions.h" #include "src/core/lib/event_engine/resolved_address_internal.h" diff --git a/src/core/lib/channel/promise_based_filter.h b/src/core/lib/channel/promise_based_filter.h index 971e98895b1..852965c5686 100644 --- a/src/core/lib/channel/promise_based_filter.h +++ b/src/core/lib/channel/promise_based_filter.h @@ -47,8 +47,8 @@ #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/context.h" -#include "src/core/lib/event_engine/default_event_engine.h" // IWYU pragma: keep -#include "src/core/lib/gprpp/crash.h" +#include "src/core/lib/event_engine/default_event_engine.h" +#include "src/core/lib/event_engine/event_engine_context.h" // IWYU pragma: keep #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/call_combiner.h" diff --git a/src/core/lib/event_engine/default_event_engine.h b/src/core/lib/event_engine/default_event_engine.h index 0601915e1c0..1725447ffdf 100644 --- a/src/core/lib/event_engine/default_event_engine.h +++ b/src/core/lib/event_engine/default_event_engine.h @@ -23,12 +23,6 @@ #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gprpp/debug_location.h" -#include "src/core/lib/promise/context.h" - -namespace grpc_core { -template <> -struct ContextType {}; -} // namespace grpc_core namespace grpc_event_engine { namespace experimental { diff --git a/src/core/lib/event_engine/event_engine_context.h b/src/core/lib/event_engine/event_engine_context.h new file mode 100644 index 00000000000..c256f696117 --- /dev/null +++ b/src/core/lib/event_engine/event_engine_context.h @@ -0,0 +1,31 @@ +// Copyright 2024 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. + +#ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_EVENT_ENGINE_CONTEXT_H +#define GRPC_SRC_CORE_LIB_EVENT_ENGINE_EVENT_ENGINE_CONTEXT_H + +#include + +#include + +#include "src/core/lib/promise/context.h" + +namespace grpc_core { + +template <> +struct ContextType {}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_EVENT_ENGINE_CONTEXT_H diff --git a/src/core/lib/promise/activity.h b/src/core/lib/promise/activity.h index 65b644902c7..17a2b70516c 100644 --- a/src/core/lib/promise/activity.h +++ b/src/core/lib/promise/activity.h @@ -31,6 +31,7 @@ #include +#include "src/core/lib/event_engine/event_engine_context.h" #include "src/core/lib/gprpp/construct_destruct.h" #include "src/core/lib/gprpp/no_destruct.h" #include "src/core/lib/gprpp/orphanable.h" diff --git a/src/core/lib/promise/sleep.cc b/src/core/lib/promise/sleep.cc index 4ddae17e0fd..d6da73cfe60 100644 --- a/src/core/lib/promise/sleep.cc +++ b/src/core/lib/promise/sleep.cc @@ -20,7 +20,7 @@ #include -#include "src/core/lib/event_engine/default_event_engine.h" // IWYU pragma: keep +#include "src/core/lib/event_engine/event_engine_context.h" // IWYU pragma: keep #include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/promise/activity.h" diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index f855fd03361..4d50f2cd55c 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -2207,6 +2207,7 @@ src/core/lib/event_engine/default_event_engine.h \ src/core/lib/event_engine/default_event_engine_factory.cc \ src/core/lib/event_engine/default_event_engine_factory.h \ src/core/lib/event_engine/event_engine.cc \ +src/core/lib/event_engine/event_engine_context.h \ src/core/lib/event_engine/extensions/can_track_errors.h \ src/core/lib/event_engine/extensions/chaotic_good_extension.h \ src/core/lib/event_engine/extensions/supports_fd.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index a61ab574132..5f2f1f4e642 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1979,6 +1979,7 @@ src/core/lib/event_engine/default_event_engine.h \ src/core/lib/event_engine/default_event_engine_factory.cc \ src/core/lib/event_engine/default_event_engine_factory.h \ src/core/lib/event_engine/event_engine.cc \ +src/core/lib/event_engine/event_engine_context.h \ src/core/lib/event_engine/extensions/can_track_errors.h \ src/core/lib/event_engine/extensions/chaotic_good_extension.h \ src/core/lib/event_engine/extensions/supports_fd.h \ From 564930c8b39e8ee03fcc1a4b0cde782463a4135b Mon Sep 17 00:00:00 2001 From: Hannah Shi Date: Thu, 21 Mar 2024 16:24:09 -0700 Subject: [PATCH 11/15] [ObjC] remove NSPrivacyAccessedAPICategorySystemBootTime from privacy manifest (#36080) #35923 removed the use of mach_absolute_time in gpr. There is still one usage in protobuf, which they have removed the usage in https://github.com/protocolbuffers/protobuf/pull/15554 but we haven't update yet. However gRPC library does not depends on protobuf but upb, so we should no longer need NSPrivacyAccessedAPICategorySystemBootTime any more. Closes #36080 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36080 from HannahShiSFB:remove-privacy-for-mach_absolute_time dacccafeecd510ba031dfc694578f5a6146990ab PiperOrigin-RevId: 617995787 --- src/objective-c/BoringSSL-GRPC.podspec | 12 ++++++------ src/objective-c/PrivacyInfo.xcprivacy | 8 -------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec index 4103011d3bc..db662806f33 100644 --- a/src/objective-c/BoringSSL-GRPC.podspec +++ b/src/objective-c/BoringSSL-GRPC.podspec @@ -696,12 +696,12 @@ Pod::Spec.new do |s| # PrivacyInfo.xcprivacy is not part of BoringSSL repo, inject it during pod installation base64 --decode $opts < src/PrivacyInfo.xcprivacy - H4sICAAAAAAC/1ByaXZhY3lJbmZvLnhjcHJpdmFjeQC1kl9PwjAUxZ/Hp6h9Z1di/JsxAhskJAQXGQ8+ - Nt0VG7a1aRuw395OHUhE8UHflrNzzj2/pNHgpSrJBrURsu7TXnhOCdZcFqJe9ekyn3Rv6CDuRGfpfZI/ - ZmOiSmEsyZaj2TQhtAswVKpEgDRPSTabLnLiOwDGc0ros7XqDmC73YascYVcVo3RQKalQm3dzJd1fSAs - bEH9mff2gzleLQS3cSeI1uji+SLTYsO4yzXja78ygkb2f59YaRC++BJZlsgtFimzLHcKzS7BtGYOvm1O - ZcVEfdI+5ByNwWKYTY/U+4+gBQh+TrZBbzNW+wFHnQmzuJLaTUSJuajQWFapCD4SJ488IDNyDxV8mrm/ - m1z1rsPeYSnscaDl+RewhTMWq5GUtsH7Y7KLy8ntL8h2WqtE8PY0484rAb5xoDEDAAA= + H4sICAAAAAAC/1ByaXZhY3lJbmZvLnhjcHJpdmFjeQCFUU1PwjAYPo9fUXtnr7uoMWMEN0iWEFykHDw2 + 3Ss2dGvTNuD+vUWdk4hya54+n3nT6VujyB6tk7qd0CS+pgRboWvZbid0wxbjOzrNRulV8Ziz52pOjJLO + k2rzsCxzQscAM2MUAhSsINWyXDMSPADmK0roq/fmHuBwOMT8yIqFbo5EB5XVBq3vlsFsHARx7WsaYj7d + T+oEtJbCZ6Mo3WGXrdaVlXsuOma52IWWKRzh8PvClUP4xcu1Uig81gX3nHUG3beCW8s7+NO50A2X7UX6 + TAh0DutZVZ6xD4+oHxD9r+yFgea8DQXOMnPucattt5AKmWzQed6YFL4UF0OekDs9jIp+1Bxy85vkNk5O + TWGYA/1BeqxHUvg4YDZ6B1ry6jZXAgAA EOF # We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists diff --git a/src/objective-c/PrivacyInfo.xcprivacy b/src/objective-c/PrivacyInfo.xcprivacy index 04aa8ca5607..276f7610da6 100644 --- a/src/objective-c/PrivacyInfo.xcprivacy +++ b/src/objective-c/PrivacyInfo.xcprivacy @@ -18,14 +18,6 @@ C617.1 - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime - NSPrivacyAccessedAPITypeReasons - - 35F9.1 - - From c2758e87fcc8146ea9b7ed5999f863f2f2106df6 Mon Sep 17 00:00:00 2001 From: AJ Heller Date: Fri, 22 Mar 2024 00:40:40 -0700 Subject: [PATCH 12/15] [experiments] Bump EventEngine experiment expiration dates (#36164) Closes #36164 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36164 from drfloob:again 8ab709d7238d7067a6f0a7beb6c617b530ed7efb PiperOrigin-RevId: 618088552 --- src/core/lib/experiments/experiments.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/lib/experiments/experiments.yaml b/src/core/lib/experiments/experiments.yaml index f1c1f4a11fc..1a9610018f0 100644 --- a/src/core/lib/experiments/experiments.yaml +++ b/src/core/lib/experiments/experiments.yaml @@ -80,21 +80,21 @@ allow_in_fuzzing_config: false - name: event_engine_client description: Use EventEngine clients instead of iomgr's grpc_tcp_client - expiry: 2024/04/01 + expiry: 2024/07/01 owner: hork@google.com test_tags: ["core_end2end_test", "event_engine_client_test"] uses_polling: true - name: event_engine_dns description: If set, use EventEngine DNSResolver for client channel resolution - expiry: 2024/04/01 + expiry: 2024/07/01 owner: yijiem@google.com test_tags: ["cancel_ares_query_test", "resolver_component_tests_runner_invoker"] allow_in_fuzzing_config: false uses_polling: true - name: event_engine_listener description: Use EventEngine listeners instead of iomgr's grpc_tcp_server - expiry: 2024/04/01 + expiry: 2024/07/01 owner: vigneshbabu@google.com test_tags: ["core_end2end_test", "event_engine_listener_test"] uses_polling: true From 604a8b9155aacb98d9206f2d493bac0cf7f2aa74 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 22 Mar 2024 13:27:33 -0700 Subject: [PATCH 13/15] [client channel] if picker is null, fail call instead of crashing (#36167) We've seen some recent crashes with the work_serializer_dispatch experiment where the picker is null when we try to do an LB pick. The only code-path we've found where the picker is set to null is the one triggered by the channel_idle filter, so we think we may be hitting a race condition where the call is started on the client_channel filter after the request to go idle has hit the WorkSerializer but before it has actually run. If that is the cause, then the right fix is to ensure that once we dispatch the request to go idle, we enqueue any subsequent RPC and dispatch a request to exit idle. However, that will require a bit of work, and it will be easier to do as part of the new call v3 channel stack, so we don't want to invest time in fixing this in the current implementation. For now, we add a work-around where we fail the RPC if the picker is null, which is better than crashing but not ideal. Closes #36167 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36167 from markdroth:client_channel_idle_race_workaround 0207dd3bdda9208774b7d2c64f088d39e3a48148 PiperOrigin-RevId: 618271781 --- src/core/client_channel/client_channel_filter.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/client_channel/client_channel_filter.cc b/src/core/client_channel/client_channel_filter.cc index c3820ed8846..b6123287474 100644 --- a/src/core/client_channel/client_channel_filter.cc +++ b/src/core/client_channel/client_channel_filter.cc @@ -2894,6 +2894,15 @@ ClientChannelFilter::LoadBalancedCall::PickSubchannel(bool was_queued) { set_picker(chand_->picker_); } while (true) { + // TODO(roth): Fix race condition in channel_idle filter and any + // other possible causes of this. + if (pickers.back() == nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { + gpr_log(GPR_ERROR, "chand=%p lb_call=%p: picker is null, failing call", + chand_, this); + } + return absl::InternalError("picker is null -- shouldn't happen"); + } // Do pick. if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: performing pick with picker=%p", From 041c283ccc70b634b9e66bc962701be9db3ea218 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 22 Mar 2024 17:28:13 -0700 Subject: [PATCH 14/15] [experiments] Fix initialization order fiasco (#36168) Internal ref : b/324720620 Closes #36168 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36168 from yashykt:FixStaticOrderInitFiasco 14f2a8950300911295fa4260629fc72bdb0af61e PiperOrigin-RevId: 618328195 --- src/core/lib/experiments/config.cc | 33 +++++++++++-------- ...ed-retry_streaming_fuzzer-6651400812036096 | 0 2 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 test/core/end2end/end2end_test_corpus/retry_streaming/clusterfuzz-testcase-minimized-retry_streaming_fuzzer-6651400812036096 diff --git a/src/core/lib/experiments/config.cc b/src/core/lib/experiments/config.cc index 4210ccc3055..ee5f7836693 100644 --- a/src/core/lib/experiments/config.cc +++ b/src/core/lib/experiments/config.cc @@ -49,9 +49,16 @@ struct ForcedExperiment { bool forced = false; bool value; }; -ForcedExperiment g_forced_experiments[kNumExperiments]; -std::atomic g_loaded(false); +ForcedExperiment* ForcedExperiments() { + static NoDestruct forced_experiments[kNumExperiments]; + return &**forced_experiments; +} + +std::atomic* Loaded() { + static NoDestruct> loaded(false); + return &*loaded; +} absl::AnyInvocable* g_check_constraints_cb = nullptr; @@ -98,7 +105,7 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariableInner() { // Set defaults from metadata. Experiments experiments; for (size_t i = 0; i < kNumExperiments; i++) { - if (!g_forced_experiments[i].forced) { + if (!ForcedExperiments()[i].forced) { if (g_check_constraints_cb != nullptr) { experiments.enabled[i] = (*g_check_constraints_cb)(g_experiment_metadata[i]); @@ -106,7 +113,7 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariableInner() { experiments.enabled[i] = g_experiment_metadata[i].default_value; } } else { - experiments.enabled[i] = g_forced_experiments[i].value; + experiments.enabled[i] = ForcedExperiments()[i].value; } } // For each comma-separated experiment in the global config: @@ -151,7 +158,7 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariableInner() { } Experiments LoadExperimentsFromConfigVariable() { - g_loaded.store(true, std::memory_order_relaxed); + Loaded()->store(true, std::memory_order_relaxed); return LoadExperimentsFromConfigVariableInner(); } @@ -193,7 +200,7 @@ void PrintExperimentsList() { const char* name = g_experiment_metadata[i].name; const bool enabled = IsExperimentEnabled(i); const bool default_enabled = g_experiment_metadata[i].default_value; - const bool forced = g_forced_experiments[i].forced; + const bool forced = ForcedExperiments()[i].forced; if (!default_enabled && !enabled) continue; if (default_enabled && enabled) { defaulted_on_experiments.insert(name); @@ -205,13 +212,13 @@ void PrintExperimentsList() { experiment_status[name] = "on:constraints"; continue; } - if (forced && g_forced_experiments[i].value) { + if (forced && ForcedExperiments()[i].value) { experiment_status[name] = "on:forced"; continue; } experiment_status[name] = "on"; } else { - if (forced && !g_forced_experiments[i].value) { + if (forced && !ForcedExperiments()[i].value) { experiment_status[name] = "off:forced"; continue; } @@ -238,14 +245,14 @@ void PrintExperimentsList() { } void ForceEnableExperiment(absl::string_view experiment, bool enable) { - GPR_ASSERT(g_loaded.load(std::memory_order_relaxed) == false); + GPR_ASSERT(Loaded()->load(std::memory_order_relaxed) == false); for (size_t i = 0; i < kNumExperiments; i++) { if (g_experiment_metadata[i].name != experiment) continue; - if (g_forced_experiments[i].forced) { - GPR_ASSERT(g_forced_experiments[i].value == enable); + if (ForcedExperiments()[i].forced) { + GPR_ASSERT(ForcedExperiments()[i].value == enable); } else { - g_forced_experiments[i].forced = true; - g_forced_experiments[i].value = enable; + ForcedExperiments()[i].forced = true; + ForcedExperiments()[i].value = enable; } return; } diff --git a/test/core/end2end/end2end_test_corpus/retry_streaming/clusterfuzz-testcase-minimized-retry_streaming_fuzzer-6651400812036096 b/test/core/end2end/end2end_test_corpus/retry_streaming/clusterfuzz-testcase-minimized-retry_streaming_fuzzer-6651400812036096 new file mode 100644 index 00000000000..e69de29bb2d From c54c69dcdd483eba78ed8dbc98c60a8c2d069758 Mon Sep 17 00:00:00 2001 From: Yijie Ma Date: Sat, 23 Mar 2024 19:34:26 -0700 Subject: [PATCH 15/15] [Metrics] New OpenTelemetry Plugin Implementation of Stats Plugin (#36070) Closes #36070 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36070 from yijiem:grpc-metrics 72653727b165e30e13810ae39db4252b358a8932 PiperOrigin-RevId: 618529035 --- BUILD | 1 - CMakeLists.txt | 96 +++- Package.swift | 1 + build_autogenerated.yaml | 196 +++++++- gRPC-C++.podspec | 2 + gRPC-Core.podspec | 2 + grpc.gemspec | 1 + include/grpcpp/ext/otel_plugin.h | 3 + package.xml | 1 + src/core/BUILD | 8 + .../client_channel/client_channel_filter.cc | 1 + .../client/chaotic_good_connector.cc | 1 + .../ext/transport/inproc/inproc_transport.cc | 1 + src/core/ext/xds/xds_client_grpc.cc | 2 +- src/core/lib/channel/call_tracer.h | 3 - src/core/lib/channel/metrics.cc | 139 ++++-- src/core/lib/channel/metrics.h | 201 ++++---- .../lib/channel/server_call_tracer_filter.cc | 2 + .../lib/channel/server_call_tracer_filter.h | 28 ++ src/core/lib/surface/call.cc | 25 +- src/core/lib/surface/legacy_channel.cc | 17 +- .../plugin_registry/grpc_plugin_registry.cc | 2 +- src/cpp/ext/otel/BUILD | 6 +- src/cpp/ext/otel/key_value_iterable.h | 23 +- src/cpp/ext/otel/otel_client_call_tracer.cc | 282 ++++++++++++ ...all_tracer.h => otel_client_call_tracer.h} | 35 +- src/cpp/ext/otel/otel_client_filter.cc | 328 -------------- src/cpp/ext/otel/otel_client_filter.h | 68 --- src/cpp/ext/otel/otel_plugin.cc | 428 +++++++++++++++--- src/cpp/ext/otel/otel_plugin.h | 288 +++++++++--- src/cpp/ext/otel/otel_server_call_tracer.cc | 198 ++------ src/cpp/ext/otel/otel_server_call_tracer.h | 109 ++++- .../lb_policy/pick_first_test.cc | 2 +- .../lb_policy/weighted_round_robin_test.cc | 2 +- test/core/end2end/grpc_core_end2end_test.bzl | 2 + test/core/end2end/tests/http2_stats.cc | 52 +-- .../client_transport_error_test.cc | 1 + .../chaotic_good/client_transport_test.cc | 1 + test/core/util/fake_stats_plugin.cc | 26 +- test/core/util/fake_stats_plugin.h | 27 +- test/cpp/ext/otel/BUILD | 1 + test/cpp/ext/otel/otel_plugin_test.cc | 420 +++++++++++++++++ test/cpp/ext/otel/otel_test_library.cc | 84 ++-- test/cpp/ext/otel/otel_test_library.h | 13 +- tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core.internal | 1 + 46 files changed, 2176 insertions(+), 955 deletions(-) create mode 100644 src/core/lib/channel/server_call_tracer_filter.h create mode 100644 src/cpp/ext/otel/otel_client_call_tracer.cc rename src/cpp/ext/otel/{otel_call_tracer.h => otel_client_call_tracer.h} (82%) delete mode 100644 src/cpp/ext/otel/otel_client_filter.cc delete mode 100644 src/cpp/ext/otel/otel_client_filter.h diff --git a/BUILD b/BUILD index f847e1bcf57..dcc62db0d28 100644 --- a/BUILD +++ b/BUILD @@ -1695,7 +1695,6 @@ grpc_cc_library( language = "c++", visibility = ["@grpc:alt_grpc_base_legacy"], deps = [ - "config", "gpr", "legacy_context", "tcp_tracer", diff --git a/CMakeLists.txt b/CMakeLists.txt index 27dc333c460..4885629ec34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5695,7 +5695,7 @@ endif() if(gRPC_BUILD_GRPCPP_OTEL_PLUGIN) add_library(grpcpp_otel_plugin - src/cpp/ext/otel/otel_client_filter.cc + src/cpp/ext/otel/otel_client_call_tracer.cc src/cpp/ext/otel/otel_plugin.cc src/cpp/ext/otel/otel_server_call_tracer.cc ) @@ -7560,6 +7560,7 @@ add_executable(bad_ping_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/bad_ping.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -8035,6 +8036,7 @@ add_executable(binary_metadata_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/binary_metadata.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -8474,6 +8476,7 @@ add_executable(call_creds_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/call_creds.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -8680,6 +8683,7 @@ add_executable(call_host_override_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/call_host_override.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -8785,6 +8789,7 @@ add_executable(cancel_after_accept_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/cancel_after_accept.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -8847,6 +8852,7 @@ add_executable(cancel_after_client_done_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/cancel_after_client_done.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -8909,6 +8915,7 @@ add_executable(cancel_after_invoke_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/cancel_after_invoke.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -8971,6 +8978,7 @@ add_executable(cancel_after_round_trip_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/cancel_after_round_trip.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -9080,6 +9088,7 @@ add_executable(cancel_before_invoke_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/cancel_before_invoke.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -9184,6 +9193,7 @@ add_executable(cancel_in_a_vacuum_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/cancel_in_a_vacuum.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -9246,6 +9256,7 @@ add_executable(cancel_with_status_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/cancel_with_status.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -10892,6 +10903,7 @@ add_executable(client_streaming_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/client_streaming.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -11230,6 +11242,7 @@ add_executable(compressed_payload_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/compressed_payload.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -11514,6 +11527,7 @@ add_executable(connectivity_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/connectivity.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -11942,6 +11956,7 @@ add_executable(default_host_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/default_host.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -12149,6 +12164,7 @@ add_executable(disappearing_server_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/disappearing_server.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -12468,6 +12484,7 @@ add_executable(empty_batch_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/empty_batch.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -13844,6 +13861,7 @@ add_executable(filter_causes_close_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/filter_causes_close.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -13906,6 +13924,7 @@ add_executable(filter_context_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/filter_context.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -13968,6 +13987,7 @@ add_executable(filter_init_fails_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/filter_init_fails.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -14080,6 +14100,7 @@ add_executable(filtered_metadata_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/filtered_metadata.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -14868,6 +14889,7 @@ add_executable(graceful_server_shutdown_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/graceful_server_shutdown.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -15233,6 +15255,7 @@ add_executable(grpc_authz_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/grpc_authz.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -16623,6 +16646,7 @@ add_executable(high_initial_seqno_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/high_initial_seqno.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -16931,6 +16955,7 @@ add_executable(hpack_size_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/hpack_size.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -17086,6 +17111,7 @@ add_executable(http2_stats_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/http2_stats.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -17978,6 +18004,7 @@ add_executable(invoke_large_request_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/invoke_large_request.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -18366,6 +18393,7 @@ add_executable(keepalive_timeout_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/keepalive_timeout.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -18471,6 +18499,7 @@ add_executable(large_metadata_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/large_metadata.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -19143,6 +19172,7 @@ add_executable(max_concurrent_streams_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/max_concurrent_streams.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -19205,6 +19235,7 @@ add_executable(max_connection_age_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/max_connection_age.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -19267,6 +19298,7 @@ add_executable(max_connection_idle_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/max_connection_idle.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -19329,6 +19361,7 @@ add_executable(max_message_length_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/max_message_length.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -20010,6 +20043,7 @@ add_executable(negative_deadline_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/negative_deadline.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -20104,6 +20138,7 @@ add_executable(no_logging_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/no_logging.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -20166,6 +20201,7 @@ add_executable(no_op_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/no_op.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -20633,9 +20669,10 @@ add_executable(otel_plugin_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.h - src/cpp/ext/otel/otel_client_filter.cc + src/cpp/ext/otel/otel_client_call_tracer.cc src/cpp/ext/otel/otel_plugin.cc src/cpp/ext/otel/otel_server_call_tracer.cc + test/core/util/fake_stats_plugin.cc test/cpp/end2end/test_service_impl.cc test/cpp/ext/otel/otel_plugin_test.cc test/cpp/ext/otel/otel_test_library.cc @@ -21093,6 +21130,7 @@ add_executable(payload_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/payload.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -21467,6 +21505,7 @@ add_executable(ping_pong_streaming_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/ping_pong_streaming.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -21580,6 +21619,7 @@ add_executable(ping_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/ping.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -22573,6 +22613,7 @@ add_executable(proxy_auth_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/proxy_auth.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23148,6 +23189,7 @@ add_executable(registered_call_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/registered_call.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23254,6 +23296,7 @@ add_executable(request_with_flags_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/request_with_flags.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23316,6 +23359,7 @@ add_executable(request_with_payload_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/request_with_payload.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23649,6 +23693,7 @@ add_executable(resource_quota_server_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/resource_quota_server.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23753,6 +23798,7 @@ add_executable(retry_cancel_after_first_attempt_starts_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23815,6 +23861,7 @@ add_executable(retry_cancel_during_delay_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_cancel_during_delay.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23877,6 +23924,7 @@ add_executable(retry_cancel_with_multiple_send_batches_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -23939,6 +23987,7 @@ add_executable(retry_cancellation_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_cancellation.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24001,6 +24050,7 @@ add_executable(retry_disabled_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_disabled.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24063,6 +24113,7 @@ add_executable(retry_exceeds_buffer_size_in_delay_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24125,6 +24176,7 @@ add_executable(retry_exceeds_buffer_size_in_initial_batch_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24187,6 +24239,7 @@ add_executable(retry_exceeds_buffer_size_in_subsequent_batch_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24249,6 +24302,7 @@ add_executable(retry_lb_drop_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_lb_drop.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24311,6 +24365,7 @@ add_executable(retry_lb_fail_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_lb_fail.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24373,6 +24428,7 @@ add_executable(retry_non_retriable_status_before_trailers_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_non_retriable_status_before_trailers.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24435,6 +24491,7 @@ add_executable(retry_non_retriable_status_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_non_retriable_status.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24497,6 +24554,7 @@ add_executable(retry_per_attempt_recv_timeout_on_last_attempt_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24559,6 +24617,7 @@ add_executable(retry_per_attempt_recv_timeout_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_per_attempt_recv_timeout.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24621,6 +24680,7 @@ add_executable(retry_recv_initial_metadata_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_recv_initial_metadata.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24683,6 +24743,7 @@ add_executable(retry_recv_message_replay_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_recv_message_replay.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24745,6 +24806,7 @@ add_executable(retry_recv_message_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_recv_message.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24807,6 +24869,7 @@ add_executable(retry_recv_trailing_metadata_error_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_recv_trailing_metadata_error.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24869,6 +24932,7 @@ add_executable(retry_send_initial_metadata_refs_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_send_initial_metadata_refs.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24931,6 +24995,7 @@ add_executable(retry_send_op_fails_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_send_op_fails.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -24993,6 +25058,7 @@ add_executable(retry_send_recv_batch_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_send_recv_batch.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25055,6 +25121,7 @@ add_executable(retry_server_pushback_delay_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_server_pushback_delay.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25117,6 +25184,7 @@ add_executable(retry_server_pushback_disabled_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_server_pushback_disabled.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25221,6 +25289,7 @@ add_executable(retry_streaming_after_commit_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_streaming_after_commit.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25283,6 +25352,7 @@ add_executable(retry_streaming_succeeds_before_replay_finished_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25345,6 +25415,7 @@ add_executable(retry_streaming_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_streaming.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25407,6 +25478,7 @@ add_executable(retry_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25511,6 +25583,7 @@ add_executable(retry_throttled_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_throttled.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25573,6 +25646,7 @@ add_executable(retry_too_many_attempts_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_too_many_attempts.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25635,6 +25709,7 @@ add_executable(retry_transparent_goaway_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_transparent_goaway.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25697,6 +25772,7 @@ add_executable(retry_transparent_max_concurrent_streams_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25759,6 +25835,7 @@ add_executable(retry_transparent_not_sent_on_wire_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25821,6 +25898,7 @@ add_executable(retry_unref_before_finish_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_unref_before_finish.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -25883,6 +25961,7 @@ add_executable(retry_unref_before_recv_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/retry_unref_before_recv.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -26866,6 +26945,7 @@ add_executable(server_finishes_request_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/server_finishes_request.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -27149,6 +27229,7 @@ add_executable(server_streaming_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/server_streaming.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -27410,6 +27491,7 @@ add_executable(shutdown_finishes_calls_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/shutdown_finishes_calls.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -27472,6 +27554,7 @@ add_executable(shutdown_finishes_tags_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/shutdown_finishes_tags.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -27597,6 +27680,7 @@ add_executable(simple_delayed_request_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/simple_delayed_request.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -27659,6 +27743,7 @@ add_executable(simple_metadata_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/simple_metadata.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -27765,6 +27850,7 @@ add_executable(simple_request_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/simple_request.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -28690,6 +28776,7 @@ add_executable(streaming_error_response_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/streaming_error_response.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -29421,6 +29508,7 @@ add_executable(test_core_end2end_channelz_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/channelz.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -30679,6 +30767,7 @@ add_executable(timeout_before_request_call_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/timeout_before_request_call.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -31182,6 +31271,7 @@ add_executable(trailing_metadata_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/trailing_metadata.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -32417,6 +32507,7 @@ add_executable(write_buffering_at_end_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/write_buffering_at_end.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) @@ -32479,6 +32570,7 @@ add_executable(write_buffering_test test/core/end2end/fixtures/proxy.cc test/core/end2end/tests/write_buffering.cc test/core/event_engine/event_engine_test_utils.cc + test/core/util/fake_stats_plugin.cc test/core/util/test_lb_policies.cc ) if(WIN32 AND MSVC) diff --git a/Package.swift b/Package.swift index a2eee8f6ca6..3b4e1e79352 100644 --- a/Package.swift +++ b/Package.swift @@ -1160,6 +1160,7 @@ let package = Package( "src/core/lib/channel/promise_based_filter.cc", "src/core/lib/channel/promise_based_filter.h", "src/core/lib/channel/server_call_tracer_filter.cc", + "src/core/lib/channel/server_call_tracer_filter.h", "src/core/lib/channel/status_util.cc", "src/core/lib/channel/status_util.h", "src/core/lib/channel/tcp_tracer.h", diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index 5d9b6c355b5..bf256ad9009 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -828,6 +828,7 @@ libs: - src/core/lib/channel/context.h - src/core/lib/channel/metrics.h - src/core/lib/channel/promise_based_filter.h + - src/core/lib/channel/server_call_tracer_filter.h - src/core/lib/channel/status_util.h - src/core/lib/channel/tcp_tracer.h - src/core/lib/compression/compression_internal.h @@ -2337,6 +2338,7 @@ libs: - src/core/lib/channel/context.h - src/core/lib/channel/metrics.h - src/core/lib/channel/promise_based_filter.h + - src/core/lib/channel/server_call_tracer_filter.h - src/core/lib/channel/status_util.h - src/core/lib/channel/tcp_tracer.h - src/core/lib/compression/compression_internal.h @@ -5107,12 +5109,11 @@ libs: - include/grpcpp/ext/otel_plugin.h headers: - src/cpp/ext/otel/key_value_iterable.h - - src/cpp/ext/otel/otel_call_tracer.h - - src/cpp/ext/otel/otel_client_filter.h + - src/cpp/ext/otel/otel_client_call_tracer.h - src/cpp/ext/otel/otel_plugin.h - src/cpp/ext/otel/otel_server_call_tracer.h src: - - src/cpp/ext/otel/otel_client_filter.cc + - src/cpp/ext/otel/otel_client_call_tracer.cc - src/cpp/ext/otel/otel_plugin.cc - src/cpp/ext/otel/otel_server_call_tracer.cc deps: @@ -5854,6 +5855,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -5874,6 +5876,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/bad_ping.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6080,6 +6083,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6100,6 +6104,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/binary_metadata.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6340,6 +6345,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6360,6 +6366,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/call_creds.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6582,6 +6589,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6602,6 +6610,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/call_host_override.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6656,6 +6665,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6676,6 +6686,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/cancel_after_accept.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6717,6 +6728,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6737,6 +6749,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/cancel_after_client_done.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6778,6 +6791,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6798,6 +6812,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/cancel_after_invoke.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6839,6 +6854,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6859,6 +6875,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/cancel_after_round_trip.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6917,6 +6934,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -6937,6 +6955,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/cancel_before_invoke.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -6993,6 +7012,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -7013,6 +7033,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/cancel_in_a_vacuum.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -7054,6 +7075,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -7074,6 +7096,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/cancel_with_status.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -8007,6 +8030,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -8027,6 +8051,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/client_streaming.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -8181,6 +8206,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -8201,6 +8227,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/compressed_payload.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -8319,6 +8346,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -8339,6 +8367,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/connectivity.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -8486,6 +8515,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -8506,6 +8536,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/default_host.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -8584,6 +8615,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -8604,6 +8636,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/disappearing_server.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -8718,6 +8751,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -8738,6 +8772,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/empty_batch.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -9503,6 +9538,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -9523,6 +9559,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/filter_causes_close.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -9564,6 +9601,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -9584,6 +9622,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/filter_context.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -9625,6 +9664,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -9645,6 +9685,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/filter_init_fails.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -9704,6 +9745,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -9724,6 +9766,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/filtered_metadata.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -10246,6 +10289,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -10266,6 +10310,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/graceful_server_shutdown.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -10442,6 +10487,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -10462,6 +10508,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/grpc_authz.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -11003,6 +11050,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -11023,6 +11071,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/high_initial_seqno.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -11199,6 +11248,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -11219,6 +11269,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/hpack_size.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -11284,6 +11335,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -11304,6 +11356,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/http2_stats.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -11764,6 +11817,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -11784,6 +11838,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/invoke_large_request.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -11964,6 +12019,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -11984,6 +12040,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/keepalive_timeout.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -12037,6 +12094,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -12057,6 +12115,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/large_metadata.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -12450,6 +12509,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -12470,6 +12530,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/max_concurrent_streams.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -12511,6 +12572,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -12531,6 +12593,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/max_connection_age.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -12572,6 +12635,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -12592,6 +12656,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/max_connection_idle.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -12633,6 +12698,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -12653,6 +12719,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/max_message_length.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -12916,6 +12983,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -12936,6 +13004,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/negative_deadline.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -12989,6 +13058,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -13009,6 +13079,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/no_logging.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -13050,6 +13121,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -13070,6 +13142,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/no_op.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -13221,10 +13294,10 @@ targets: plugin_option: gRPC_BUILD_GRPCPP_OTEL_PLUGIN headers: - src/cpp/ext/otel/key_value_iterable.h - - src/cpp/ext/otel/otel_call_tracer.h - - src/cpp/ext/otel/otel_client_filter.h + - src/cpp/ext/otel/otel_client_call_tracer.h - src/cpp/ext/otel/otel_plugin.h - src/cpp/ext/otel/otel_server_call_tracer.h + - test/core/util/fake_stats_plugin.h - test/cpp/end2end/test_service_impl.h - test/cpp/ext/otel/otel_test_library.h src: @@ -13232,9 +13305,10 @@ targets: - src/proto/grpc/testing/echo_messages.proto - src/proto/grpc/testing/simple_messages.proto - src/proto/grpc/testing/xds/v3/orca_load_report.proto - - src/cpp/ext/otel/otel_client_filter.cc + - src/cpp/ext/otel/otel_client_call_tracer.cc - src/cpp/ext/otel/otel_plugin.cc - src/cpp/ext/otel/otel_server_call_tracer.cc + - test/core/util/fake_stats_plugin.cc - test/cpp/end2end/test_service_impl.cc - test/cpp/ext/otel/otel_plugin_test.cc - test/cpp/ext/otel/otel_test_library.cc @@ -13417,6 +13491,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -13437,6 +13512,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/payload.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -13677,6 +13753,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -13697,6 +13774,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/ping_pong_streaming.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -13769,6 +13847,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -13789,6 +13868,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/ping.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14186,6 +14266,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -14206,6 +14287,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/proxy_auth.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14442,6 +14524,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -14462,6 +14545,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/registered_call.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14517,6 +14601,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -14537,6 +14622,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/request_with_flags.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14578,6 +14664,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -14598,6 +14685,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/request_with_payload.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14791,6 +14879,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -14811,6 +14900,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/resource_quota_server.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14863,6 +14953,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -14883,6 +14974,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14924,6 +15016,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -14944,6 +15037,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_cancel_during_delay.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -14985,6 +15079,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15005,6 +15100,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15046,6 +15142,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15066,6 +15163,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_cancellation.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15107,6 +15205,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15127,6 +15226,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_disabled.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15168,6 +15268,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15188,6 +15289,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15229,6 +15331,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15249,6 +15352,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15290,6 +15394,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15310,6 +15415,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15351,6 +15457,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15371,6 +15478,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_lb_drop.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15412,6 +15520,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15432,6 +15541,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_lb_fail.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15473,6 +15583,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15493,6 +15604,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_non_retriable_status_before_trailers.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15534,6 +15646,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15554,6 +15667,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_non_retriable_status.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15595,6 +15709,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15615,6 +15730,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15656,6 +15772,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15676,6 +15793,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_per_attempt_recv_timeout.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15717,6 +15835,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15737,6 +15856,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_recv_initial_metadata.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15778,6 +15898,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15798,6 +15919,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_recv_message_replay.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15839,6 +15961,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15859,6 +15982,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_recv_message.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15900,6 +16024,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15920,6 +16045,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_recv_trailing_metadata_error.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -15961,6 +16087,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -15981,6 +16108,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_send_initial_metadata_refs.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16022,6 +16150,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16042,6 +16171,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_send_op_fails.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16083,6 +16213,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16103,6 +16234,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_send_recv_batch.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16144,6 +16276,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16164,6 +16297,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_server_pushback_delay.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16205,6 +16339,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16225,6 +16360,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_server_pushback_disabled.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16277,6 +16413,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16297,6 +16434,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_streaming_after_commit.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16338,6 +16476,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16358,6 +16497,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16399,6 +16539,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16419,6 +16560,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_streaming.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16460,6 +16602,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16480,6 +16623,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16532,6 +16676,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16552,6 +16697,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_throttled.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16593,6 +16739,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16613,6 +16760,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_too_many_attempts.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16654,6 +16802,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16674,6 +16823,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_transparent_goaway.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16715,6 +16865,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16735,6 +16886,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16776,6 +16928,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16796,6 +16949,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16837,6 +16991,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16857,6 +17012,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_unref_before_finish.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -16898,6 +17054,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -16918,6 +17075,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/retry_unref_before_recv.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -17300,6 +17458,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -17320,6 +17479,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/server_finishes_request.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -17448,6 +17608,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -17468,6 +17629,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/server_streaming.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -17576,6 +17738,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -17596,6 +17759,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/shutdown_finishes_calls.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -17637,6 +17801,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -17657,6 +17822,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/shutdown_finishes_tags.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -17713,6 +17879,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -17733,6 +17900,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/simple_delayed_request.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -17774,6 +17942,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -17794,6 +17963,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/simple_metadata.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -17849,6 +18019,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -17869,6 +18040,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/simple_request.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -18204,6 +18376,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -18224,6 +18397,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/streaming_error_response.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -18558,6 +18732,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -18578,6 +18753,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/channelz.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -19102,6 +19278,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -19122,6 +19299,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/timeout_before_request_call.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -19319,6 +19497,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -19339,6 +19518,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/trailing_metadata.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -20005,6 +20185,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -20025,6 +20206,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/write_buffering_at_end.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest @@ -20066,6 +20248,7 @@ targets: - test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/tests/cancel_test_helpers.h - test/core/event_engine/event_engine_test_utils.h + - test/core/util/fake_stats_plugin.h - test/core/util/test_lb_policies.h src: - src/core/ext/transport/chaotic_good/chaotic_good_transport.cc @@ -20086,6 +20269,7 @@ targets: - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/write_buffering.cc - test/core/event_engine/event_engine_test_utils.cc + - test/core/util/fake_stats_plugin.cc - test/core/util/test_lb_policies.cc deps: - gtest diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 77e9a3af608..f34c7dfb704 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -909,6 +909,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/context.h', 'src/core/lib/channel/metrics.h', 'src/core/lib/channel/promise_based_filter.h', + 'src/core/lib/channel/server_call_tracer_filter.h', 'src/core/lib/channel/status_util.h', 'src/core/lib/channel/tcp_tracer.h', 'src/core/lib/compression/compression_internal.h', @@ -2175,6 +2176,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/context.h', 'src/core/lib/channel/metrics.h', 'src/core/lib/channel/promise_based_filter.h', + 'src/core/lib/channel/server_call_tracer_filter.h', 'src/core/lib/channel/status_util.h', 'src/core/lib/channel/tcp_tracer.h', 'src/core/lib/compression/compression_internal.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 859ffe4776a..cc5573b737d 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1276,6 +1276,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/promise_based_filter.cc', 'src/core/lib/channel/promise_based_filter.h', 'src/core/lib/channel/server_call_tracer_filter.cc', + 'src/core/lib/channel/server_call_tracer_filter.h', 'src/core/lib/channel/status_util.cc', 'src/core/lib/channel/status_util.h', 'src/core/lib/channel/tcp_tracer.h', @@ -2957,6 +2958,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/context.h', 'src/core/lib/channel/metrics.h', 'src/core/lib/channel/promise_based_filter.h', + 'src/core/lib/channel/server_call_tracer_filter.h', 'src/core/lib/channel/status_util.h', 'src/core/lib/channel/tcp_tracer.h', 'src/core/lib/compression/compression_internal.h', diff --git a/grpc.gemspec b/grpc.gemspec index 74880a4e33c..5a98949d12f 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -1166,6 +1166,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/promise_based_filter.cc ) s.files += %w( src/core/lib/channel/promise_based_filter.h ) s.files += %w( src/core/lib/channel/server_call_tracer_filter.cc ) + s.files += %w( src/core/lib/channel/server_call_tracer_filter.h ) s.files += %w( src/core/lib/channel/status_util.cc ) s.files += %w( src/core/lib/channel/status_util.h ) s.files += %w( src/core/lib/channel/tcp_tracer.h ) diff --git a/include/grpcpp/ext/otel_plugin.h b/include/grpcpp/ext/otel_plugin.h index 51afdaa83dd..56ac5fb17df 100644 --- a/include/grpcpp/ext/otel_plugin.h +++ b/include/grpcpp/ext/otel_plugin.h @@ -106,6 +106,9 @@ class OpenTelemetryPluginBuilder { /// options can be added. OpenTelemetryPluginBuilder& AddPluginOption( std::unique_ptr option); + // Records \a optional_label_key on all metrics that provide it. + OpenTelemetryPluginBuilder& AddOptionalLabel( + absl::string_view optional_label_key); /// Registers a global plugin that acts on all channels and servers running on /// the process. absl::Status BuildAndRegisterGlobal(); diff --git a/package.xml b/package.xml index 9b4c2ff2849..d1634f03f43 100644 --- a/package.xml +++ b/package.xml @@ -1148,6 +1148,7 @@ + diff --git a/src/core/BUILD b/src/core/BUILD index 0a333928eb5..a216c2c7b9d 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -119,6 +119,9 @@ grpc_cc_library( srcs = [ "lib/channel/server_call_tracer_filter.cc", ], + hdrs = [ + "lib/channel/server_call_tracer_filter.h", + ], external_deps = [ "absl/status", "absl/status:statusor", @@ -7548,6 +7551,7 @@ grpc_cc_library( "//:api_trace", "//:channel", "//:channel_create", + "//:config", "//:debug_location", "//:exec_ctx", "//:gpr", @@ -7579,10 +7583,14 @@ grpc_cc_library( ], language = "c++", deps = [ + "arena", "channel_args", "no_destruct", + "slice", "time", + "//:call_tracer", "//:gpr", + "//:legacy_context", ], ) diff --git a/src/core/client_channel/client_channel_filter.cc b/src/core/client_channel/client_channel_filter.cc index b6123287474..eb1ec52a343 100644 --- a/src/core/client_channel/client_channel_filter.cc +++ b/src/core/client_channel/client_channel_filter.cc @@ -1340,6 +1340,7 @@ ClientChannelFilter::CreateLoadBalancedCall( const grpc_call_element_args& args, grpc_polling_entity* pollent, grpc_closure* on_call_destruction_complete, absl::AnyInvocable on_commit, bool is_transparent_retry) { + promise_detail::Context arena_ctx(args.arena); return OrphanablePtr( args.arena->New( this, args, pollent, on_call_destruction_complete, diff --git a/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc b/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc index 2ef11595b04..9be72346484 100644 --- a/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc +++ b/src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc @@ -33,6 +33,7 @@ #include "src/core/ext/transport/chaotic_good/frame_header.h" #include "src/core/ext/transport/chaotic_good/settings_metadata.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/event_engine/channel_args_endpoint_config.h" #include "src/core/lib/event_engine/extensions/chaotic_good_extension.h" #include "src/core/lib/event_engine/query_extensions.h" diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc index 6a335cb0386..049735a4b08 100644 --- a/src/core/ext/transport/inproc/inproc_transport.cc +++ b/src/core/ext/transport/inproc/inproc_transport.cc @@ -22,6 +22,7 @@ #include #include "src/core/ext/transport/inproc/legacy_inproc_transport.h" +#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/experiments/experiments.h" #include "src/core/lib/gprpp/crash.h" #include "src/core/lib/promise/promise.h" diff --git a/src/core/ext/xds/xds_client_grpc.cc b/src/core/ext/xds/xds_client_grpc.cc index cbfee8e71fd..f0c5d7442cf 100644 --- a/src/core/ext/xds/xds_client_grpc.cc +++ b/src/core/ext/xds/xds_client_grpc.cc @@ -268,7 +268,7 @@ namespace { GlobalStatsPluginRegistry::StatsPluginGroup GetStatsPluginGroupForKey( absl::string_view key) { if (key == GrpcXdsClient::kServerKey) { - return GlobalStatsPluginRegistry::GetAllStatsPlugins(); + return GlobalStatsPluginRegistry::GetStatsPluginsForServer(ChannelArgs{}); } // TODO(roth): How do we set the authority here? StatsPlugin::ChannelScope scope(key, ""); diff --git a/src/core/lib/channel/call_tracer.h b/src/core/lib/channel/call_tracer.h index 54d5e2c8508..e2be3d1a448 100644 --- a/src/core/lib/channel/call_tracer.h +++ b/src/core/lib/channel/call_tracer.h @@ -32,7 +32,6 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/context.h" #include "src/core/lib/channel/tcp_tracer.h" -#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/slice/slice_buffer.h" @@ -207,8 +206,6 @@ class ServerCallTracerFactory { static absl::string_view ChannelArgName(); }; -void RegisterServerCallTracerFilter(CoreConfiguration::Builder* builder); - // Convenience functions to add call tracers to a call context. Allows setting // multiple call tracers to a single call. It is only valid to add client call // tracers before the client_channel filter sees the send_initial_metadata op. diff --git a/src/core/lib/channel/metrics.cc b/src/core/lib/channel/metrics.cc index 813eeb02cd4..5dcb5d4da01 100644 --- a/src/core/lib/channel/metrics.cc +++ b/src/core/lib/channel/metrics.cc @@ -16,7 +16,7 @@ #include "src/core/lib/channel/metrics.h" -#include "absl/container/flat_hash_map.h" +#include #include "src/core/lib/gprpp/crash.h" @@ -24,11 +24,10 @@ namespace grpc_core { // Uses the Construct-on-First-Use idiom to avoid the static initialization // order fiasco. -absl::flat_hash_map& +std::vector& GlobalInstrumentsRegistry::GetInstrumentList() { - static NoDestruct> + static NoDestruct< + std::vector> instruments; return *instruments; } @@ -40,8 +39,11 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -56,7 +58,7 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalUInt64CounterHandle handle; handle.index = index; return handle; @@ -69,8 +71,11 @@ GlobalInstrumentsRegistry::RegisterDoubleCounter( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -85,7 +90,7 @@ GlobalInstrumentsRegistry::RegisterDoubleCounter( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalDoubleCounterHandle handle; handle.index = index; return handle; @@ -98,8 +103,11 @@ GlobalInstrumentsRegistry::RegisterUInt64Histogram( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -114,7 +122,7 @@ GlobalInstrumentsRegistry::RegisterUInt64Histogram( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalUInt64HistogramHandle handle; handle.index = index; return handle; @@ -127,8 +135,11 @@ GlobalInstrumentsRegistry::RegisterDoubleHistogram( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -143,7 +154,7 @@ GlobalInstrumentsRegistry::RegisterDoubleHistogram( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalDoubleHistogramHandle handle; handle.index = index; return handle; @@ -156,8 +167,11 @@ GlobalInstrumentsRegistry::RegisterInt64Gauge( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -172,7 +186,7 @@ GlobalInstrumentsRegistry::RegisterInt64Gauge( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalInt64GaugeHandle handle; handle.index = index; return handle; @@ -185,8 +199,11 @@ GlobalInstrumentsRegistry::RegisterDoubleGauge( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -201,7 +218,7 @@ GlobalInstrumentsRegistry::RegisterDoubleGauge( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalDoubleGaugeHandle handle; handle.index = index; return handle; @@ -214,8 +231,11 @@ GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -230,7 +250,7 @@ GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalCallbackInt64GaugeHandle handle; handle.index = index; return handle; @@ -243,8 +263,11 @@ GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge( absl::Span optional_label_keys, bool enable_by_default) { auto& instruments = GetInstrumentList(); - if (instruments.find(name) != instruments.end()) { - Crash(absl::StrFormat("Metric name %s has already been registered.", name)); + for (const auto& descriptor : instruments) { + if (descriptor.name == name) { + Crash( + absl::StrFormat("Metric name %s has already been registered.", name)); + } } uint32_t index = instruments.size(); GPR_ASSERT(index < std::numeric_limits::max()); @@ -259,7 +282,7 @@ GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge( descriptor.label_keys = {label_keys.begin(), label_keys.end()}; descriptor.optional_label_keys = {optional_label_keys.begin(), optional_label_keys.end()}; - instruments.emplace(name, std::move(descriptor)); + instruments.push_back(std::move(descriptor)); GlobalCallbackDoubleGaugeHandle handle; handle.index = index; return handle; @@ -268,10 +291,16 @@ GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge( void GlobalInstrumentsRegistry::ForEach( absl::FunctionRef f) { for (const auto& instrument : GetInstrumentList()) { - f(instrument.second); + f(instrument); } } +const GlobalInstrumentsRegistry::GlobalInstrumentDescriptor& +GlobalInstrumentsRegistry::GetInstrumentDescriptor( + GlobalInstrumentHandle handle) { + return GetInstrumentList().at(handle.index); +} + RegisteredMetricCallback::RegisteredMetricCallback( GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group, absl::AnyInvocable callback, @@ -281,14 +310,14 @@ RegisteredMetricCallback::RegisteredMetricCallback( callback_(std::move(callback)), metrics_(std::move(metrics)), min_interval_(min_interval) { - for (auto& plugin : stats_plugin_group_.plugins_) { - plugin->AddCallback(this); + for (auto& state : stats_plugin_group_.plugins_state_) { + state.plugin->AddCallback(this); } } RegisteredMetricCallback::~RegisteredMetricCallback() { - for (auto& plugin : stats_plugin_group_.plugins_) { - plugin->RemoveCallback(this); + for (auto& state : stats_plugin_group_.plugins_state_) { + state.plugin->RemoveCallback(this); } } @@ -301,6 +330,28 @@ GlobalStatsPluginRegistry::StatsPluginGroup::RegisterCallback( *this, std::move(callback), std::move(metrics), min_interval); } +void GlobalStatsPluginRegistry::StatsPluginGroup::AddClientCallTracers( + const Slice& path, bool registered_method, + grpc_call_context_element* call_context) { + for (auto& state : plugins_state_) { + auto* call_tracer = state.plugin->GetClientCallTracer( + path, registered_method, state.scope_config); + if (call_tracer != nullptr) { + AddClientCallTracerToContext(call_context, call_tracer); + } + } +} + +void GlobalStatsPluginRegistry::StatsPluginGroup::AddServerCallTracers( + grpc_call_context_element* call_context) { + for (auto& state : plugins_state_) { + auto* call_tracer = state.plugin->GetServerCallTracer(state.scope_config); + if (call_tracer != nullptr) { + AddServerCallTracerToContext(call_context, call_tracer); + } + } +} + NoDestruct GlobalStatsPluginRegistry::mutex_; NoDestruct>> GlobalStatsPluginRegistry::plugins_; @@ -312,23 +363,31 @@ void GlobalStatsPluginRegistry::RegisterStatsPlugin( } GlobalStatsPluginRegistry::StatsPluginGroup -GlobalStatsPluginRegistry::GetAllStatsPlugins() { +GlobalStatsPluginRegistry::GetStatsPluginsForChannel( + const StatsPlugin::ChannelScope& scope) { MutexLock lock(&*mutex_); StatsPluginGroup group; for (const auto& plugin : *plugins_) { - group.push_back(plugin); + bool is_enabled = false; + std::shared_ptr config; + std::tie(is_enabled, config) = plugin->IsEnabledForChannel(scope); + if (is_enabled) { + group.AddStatsPlugin(plugin, std::move(config)); + } } return group; } GlobalStatsPluginRegistry::StatsPluginGroup -GlobalStatsPluginRegistry::GetStatsPluginsForChannel( - const StatsPlugin::ChannelScope& scope) { +GlobalStatsPluginRegistry::GetStatsPluginsForServer(const ChannelArgs& args) { MutexLock lock(&*mutex_); StatsPluginGroup group; for (const auto& plugin : *plugins_) { - if (plugin->IsEnabledForChannel(scope)) { - group.push_back(plugin); + bool is_enabled = false; + std::shared_ptr config; + std::tie(is_enabled, config) = plugin->IsEnabledForServer(args); + if (is_enabled) { + group.AddStatsPlugin(plugin, std::move(config)); } } return group; diff --git a/src/core/lib/channel/metrics.h b/src/core/lib/channel/metrics.h index c4315e721ee..2805ff0d083 100644 --- a/src/core/lib/channel/metrics.h +++ b/src/core/lib/channel/metrics.h @@ -29,10 +29,13 @@ #include +#include "src/core/lib/channel/call_tracer.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/context.h" #include "src/core/lib/gprpp/no_destruct.h" #include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/time.h" +#include "src/core/lib/slice/slice.h" namespace grpc_core { @@ -58,10 +61,11 @@ class GlobalInstrumentsRegistry { kGauge, kCallbackGauge, }; + using InstrumentID = uint32_t; struct GlobalInstrumentDescriptor { ValueType value_type; InstrumentType instrument_type; - uint32_t index; + InstrumentID index; bool enable_by_default; absl::string_view name; absl::string_view description; @@ -69,20 +73,20 @@ class GlobalInstrumentsRegistry { std::vector label_keys; std::vector optional_label_keys; }; - struct GlobalHandle { + struct GlobalInstrumentHandle { // This is the index for the corresponding registered instrument that // StatsPlugins can use to uniquely identify an instrument in the current // process. Though this is not guaranteed to be stable between different // runs or between different versions. - uint32_t index; + InstrumentID index; }; - struct GlobalUInt64CounterHandle : public GlobalHandle {}; - struct GlobalDoubleCounterHandle : public GlobalHandle {}; - struct GlobalUInt64HistogramHandle : public GlobalHandle {}; - struct GlobalDoubleHistogramHandle : public GlobalHandle {}; - struct GlobalInt64GaugeHandle : public GlobalHandle {}; - struct GlobalDoubleGaugeHandle : public GlobalHandle {}; - struct GlobalCallbackHandle : public GlobalHandle {}; + struct GlobalUInt64CounterHandle : public GlobalInstrumentHandle {}; + struct GlobalDoubleCounterHandle : public GlobalInstrumentHandle {}; + struct GlobalUInt64HistogramHandle : public GlobalInstrumentHandle {}; + struct GlobalDoubleHistogramHandle : public GlobalInstrumentHandle {}; + struct GlobalInt64GaugeHandle : public GlobalInstrumentHandle {}; + struct GlobalDoubleGaugeHandle : public GlobalInstrumentHandle {}; + struct GlobalCallbackHandle : public GlobalInstrumentHandle {}; struct GlobalCallbackInt64GaugeHandle : public GlobalCallbackHandle {}; struct GlobalCallbackDoubleGaugeHandle : public GlobalCallbackHandle {}; @@ -130,14 +134,15 @@ class GlobalInstrumentsRegistry { static void ForEach( absl::FunctionRef f); + static const GlobalInstrumentDescriptor& GetInstrumentDescriptor( + GlobalInstrumentHandle handle); private: friend class GlobalInstrumentsRegistryTestPeer; GlobalInstrumentsRegistry() = delete; - static absl::flat_hash_map< - absl::string_view, GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>& + static std::vector& GetInstrumentList(); }; @@ -162,6 +167,7 @@ class RegisteredMetricCallback; // The StatsPlugin interface. class StatsPlugin { public: + // Configuration (scope) for a specific client channel. class ChannelScope { public: ChannelScope(absl::string_view target, absl::string_view authority) @@ -174,37 +180,74 @@ class StatsPlugin { absl::string_view target_; absl::string_view authority_; }; + // A general-purpose way for stats plugin to store per-channel or per-server + // state. + class ScopeConfig { + public: + virtual ~ScopeConfig() = default; + }; virtual ~StatsPlugin() = default; - virtual bool IsEnabledForChannel(const ChannelScope& scope) const = 0; - virtual bool IsEnabledForServer(const ChannelArgs& args) const = 0; - + // Whether this stats plugin is enabled for the channel specified by \a scope. + // Returns true and a channel-specific ScopeConfig which may then be used to + // configure the ClientCallTracer in GetClientCallTracer(). + virtual std::pair> IsEnabledForChannel( + const ChannelScope& scope) const = 0; + // Whether this stats plugin is enabled for the server specified by \a args. + // Returns true and a server-specific ScopeConfig which may then be used to + // configure the ServerCallTracer in GetServerCallTracer(). + virtual std::pair> IsEnabledForServer( + const ChannelArgs& args) const = 0; + + // Adds \a value to the uint64 counter specified by \a handle. \a label_values + // and \a optional_label_values specify attributes that are associated with + // this measurement and must match with their corresponding keys in + // GlobalInstrumentsRegistry::RegisterUInt64Counter(). virtual void AddCounter( GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle, uint64_t value, absl::Span label_values, - absl::Span optional_values) = 0; + absl::Span optional_label_values) = 0; + // Adds \a value to the double counter specified by \a handle. \a label_values + // and \a optional_label_values specify attributes that are associated with + // this measurement and must match with their corresponding keys in + // GlobalInstrumentsRegistry::RegisterDoubleCounter(). virtual void AddCounter( GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle, double value, absl::Span label_values, - absl::Span optional_values) = 0; + absl::Span optional_label_values) = 0; + // Records a uint64 \a value to the histogram specified by \a handle. \a + // label_values and \a optional_label_values specify attributes that are + // associated with this measurement and must match with their corresponding + // keys in GlobalInstrumentsRegistry::RegisterUInt64Histogram(). virtual void RecordHistogram( GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle, uint64_t value, absl::Span label_values, - absl::Span optional_values) = 0; + absl::Span optional_label_values) = 0; + // Records a double \a value to the histogram specified by \a handle. \a + // label_values and \a optional_label_values specify attributes that are + // associated with this measurement and must match with their corresponding + // keys in GlobalInstrumentsRegistry::RegisterDoubleHistogram(). virtual void RecordHistogram( GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle, double value, absl::Span label_values, - absl::Span optional_values) = 0; + absl::Span optional_label_values) = 0; + // Sets an int64 \a value to the gauge specifed by \a handle. \a + // label_values and \a optional_label_values specify attributes that are + // associated with this measurement and must match with their corresponding + // keys in GlobalInstrumentsRegistry::RegisterInt64Gauge(). virtual void SetGauge( GlobalInstrumentsRegistry::GlobalInt64GaugeHandle handle, int64_t value, absl::Span label_values, - absl::Span optional_values) = 0; + absl::Span optional_label_values) = 0; + // Sets a double \a value to the gauge specifed by \a handle. \a + // label_values and \a optional_label_values specify attributes that are + // associated with this measurement and must match with their corresponding + // keys in GlobalInstrumentsRegistry::RegisterDoubleGauge(). virtual void SetGauge( GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle handle, double value, absl::Span label_values, - absl::Span optional_values) = 0; - + absl::Span optional_label_values) = 0; // Adds a callback to be invoked when the stats plugin wants to // populate the corresponding metrics (see callback->metrics() for list). virtual void AddCallback(RegisteredMetricCallback* callback) = 0; @@ -212,13 +255,15 @@ class StatsPlugin { // plugin may not use the callback after this method returns. virtual void RemoveCallback(RegisteredMetricCallback* callback) = 0; - // TODO(yijiem): Details pending. - // std::unique_ptr GetObservableGauge( - // absl::string_view name, absl::string_view description, - // absl::string_view unit); - // AsyncInstrument* GetObservableCounter( - // absl::string_view name, absl::string_view description, - // absl::string_view unit); + // Gets a ClientCallTracer associated with this stats plugin which can be used + // in a call. + virtual ClientCallTracer* GetClientCallTracer( + const Slice& path, bool registered_method, + std::shared_ptr scope_config) = 0; + // Gets a ServerCallTracer associated with this stats plugin which can be used + // in a call. + virtual ServerCallTracer* GetServerCallTracer( + std::shared_ptr scope_config) = 0; // TODO(yijiem): This is an optimization for the StatsPlugin to create its own // representation of the label_values and use it multiple times. We would @@ -230,63 +275,55 @@ class StatsPlugin { // absl::Span label_values) = 0; }; -// A global registry of StatsPlugins. It has shared ownership to the registered -// StatsPlugins. This API is supposed to be used during runtime after the main +// A global registry of stats plugins. It has shared ownership to the registered +// stats plugins. This API is supposed to be used during runtime after the main // function begins. This API is thread-safe. class GlobalStatsPluginRegistry { public: + // A stats plugin group object is how the code in gRPC normally interacts with + // stats plugins. They got a stats plugin group which contains all the stats + // plugins for a specific scope and all operations on the stats plugin group + // will be applied to all the stats plugins within the group. class StatsPluginGroup { public: - void push_back(std::shared_ptr plugin) { - plugins_.push_back(std::move(plugin)); + // Adds a stats plugin and a scope config (per-channel or per-server) to the + // group. + void AddStatsPlugin(std::shared_ptr plugin, + std::shared_ptr config) { + PluginState plugin_state; + plugin_state.plugin = std::move(plugin); + plugin_state.scope_config = std::move(config); + plugins_state_.push_back(std::move(plugin_state)); } - - void AddCounter(GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle, - uint64_t value, + // Adds a counter in all stats plugins within the group. See the StatsPlugin + // interface for more documentation and valid types. + template + void AddCounter(HandleType handle, ValueType value, absl::Span label_values, absl::Span optional_values) { - for (auto& plugin : plugins_) { - plugin->AddCounter(handle, value, label_values, optional_values); + for (auto& state : plugins_state_) { + state.plugin->AddCounter(handle, value, label_values, optional_values); } } - void AddCounter(GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle, - double value, - absl::Span label_values, - absl::Span optional_values) { - for (auto& plugin : plugins_) { - plugin->AddCounter(handle, value, label_values, optional_values); - } - } - void RecordHistogram( - GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle, - uint64_t value, absl::Span label_values, - absl::Span optional_values) { - for (auto& plugin : plugins_) { - plugin->RecordHistogram(handle, value, label_values, optional_values); + // Records a value to a histogram in all stats plugins within the group. See + // the StatsPlugin interface for more documentation and valid types. + template + void RecordHistogram(HandleType handle, ValueType value, + absl::Span label_values, + absl::Span optional_values) { + for (auto& state : plugins_state_) { + state.plugin->RecordHistogram(handle, value, label_values, + optional_values); } } - void RecordHistogram( - GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle, - double value, absl::Span label_values, - absl::Span optional_values) { - for (auto& plugin : plugins_) { - plugin->RecordHistogram(handle, value, label_values, optional_values); - } - } - void SetGauge(GlobalInstrumentsRegistry::GlobalInt64GaugeHandle handle, - int64_t value, + // Sets a value to a gauge in all stats plugins within the group. See the + // StatsPlugin interface for more documentation and valid types. + template + void SetGauge(HandleType handle, ValueType value, absl::Span label_values, absl::Span optional_values) { - for (auto& plugin : plugins_) { - plugin->SetGauge(handle, value, label_values, optional_values); - } - } - void SetGauge(GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle handle, - double value, - absl::Span label_values, - absl::Span optional_values) { - for (auto& plugin : plugins_) { - plugin->SetGauge(handle, value, label_values, optional_values); + for (auto& state : plugins_state_) { + state.plugin->SetGauge(handle, value, label_values, optional_values); } } @@ -303,21 +340,33 @@ class GlobalStatsPluginRegistry { std::vector metrics, Duration min_interval = Duration::Seconds(5)); + // Adds all available client call tracers associated with the stats plugins + // within the group to \a call_context. + void AddClientCallTracers(const Slice& path, bool registered_method, + grpc_call_context_element* call_context); + // Adds all available server call tracers associated with the stats plugins + // within the group to \a call_context. + void AddServerCallTracers(grpc_call_context_element* call_context); + private: friend class RegisteredMetricCallback; - std::vector> plugins_; + struct PluginState { + std::shared_ptr scope_config; + std::shared_ptr plugin; + }; + + std::vector plugins_state_; }; + // Registers a stats plugin with the global stats plugin registry. static void RegisterStatsPlugin(std::shared_ptr plugin); // The following functions can be invoked to get a StatsPluginGroup for // a specified scope. - static StatsPluginGroup GetAllStatsPlugins(); static StatsPluginGroup GetStatsPluginsForChannel( const StatsPlugin::ChannelScope& scope); - // TODO(yijiem): Implement this. - // StatsPluginsGroup GetStatsPluginsForServer(ChannelArgs& args); + static StatsPluginGroup GetStatsPluginsForServer(const ChannelArgs& args); private: friend class GlobalStatsPluginRegistryTestPeer; diff --git a/src/core/lib/channel/server_call_tracer_filter.cc b/src/core/lib/channel/server_call_tracer_filter.cc index 2858d4ca0ad..7a2ca01bb02 100644 --- a/src/core/lib/channel/server_call_tracer_filter.cc +++ b/src/core/lib/channel/server_call_tracer_filter.cc @@ -16,6 +16,8 @@ #include +#include "src/core/lib/channel/server_call_tracer_filter.h" + #include #include diff --git a/src/core/lib/channel/server_call_tracer_filter.h b/src/core/lib/channel/server_call_tracer_filter.h new file mode 100644 index 00000000000..e34fcb416d0 --- /dev/null +++ b/src/core/lib/channel/server_call_tracer_filter.h @@ -0,0 +1,28 @@ +// Copyright 2024 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. + +#ifndef GRPC_SRC_CORE_LIB_CHANNEL_SERVER_CALL_TRACER_FILTER_H +#define GRPC_SRC_CORE_LIB_CHANNEL_SERVER_CALL_TRACER_FILTER_H + +#include + +#include "src/core/lib/config/core_configuration.h" + +namespace grpc_core { + +void RegisterServerCallTracerFilter(CoreConfiguration::Builder* builder); + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_LIB_CHANNEL_SERVER_CALL_TRACER_FILTER_H diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 3f97df0f81f..e0dfe8e38b9 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -588,6 +588,12 @@ class FilterStackCall final : public Call { } private: + class ScopedContext : public promise_detail::Context { + public: + explicit ScopedContext(FilterStackCall* call) + : promise_detail::Context(call->arena()) {} + }; + static constexpr gpr_atm kRecvNone = 0; static constexpr gpr_atm kRecvInitialMetadataFirst = 1; @@ -807,6 +813,7 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args, GPR_DEBUG_ASSERT(FromCallStack(call->call_stack()) == call); *out_call = call->c_ptr(); grpc_slice path = grpc_empty_slice(); + ScopedContext ctx(call); if (call->is_client()) { call->final_op_.client.status_details = nullptr; call->final_op_.client.status = nullptr; @@ -822,6 +829,8 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args, call->send_initial_metadata_.Set( GrpcRegisteredMethod(), reinterpret_cast(static_cast( args->registered_method))); + channel_stack->stats_plugin_group->AddClientCallTracers( + Slice(CSliceRef(path)), args->registered_method, call->context_); } else { global_stats().IncrementServerCallsCreated(); call->final_op_.server.cancelled = nullptr; @@ -830,6 +839,9 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args, // collecting from when the call is created at the transport. The idea is // that the transport would create the call tracer and pass it in as part of // the metadata. + // TODO(yijiem): OpenCensus and internal Census is still using this way to + // set server call tracer. We need to refactor them to stats plugins + // (including removing the client channel filters). if (args->server != nullptr && args->server->server_call_tracer_factory() != nullptr) { auto* server_call_tracer = @@ -846,6 +858,7 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args, call->ContextSet(GRPC_CONTEXT_CALL_TRACER, server_call_tracer, nullptr); } } + channel_stack->stats_plugin_group->AddServerCallTracers(call->context_); } Call* parent = Call::FromC(args->parent); @@ -2725,6 +2738,8 @@ class ClientPromiseBasedCall final : public PromiseBasedCall { "non-nullptr."); } ScopedContext context(this); + args->channel->channel_stack()->stats_plugin_group->AddClientCallTracers( + *args->path, args->registered_method, this->context()); send_initial_metadata_ = GetContext()->MakePooled(GetContext()); send_initial_metadata_->Set(HttpPathMetadata(), std::move(*args->path)); @@ -3390,11 +3405,16 @@ ServerPromiseBasedCall::ServerPromiseBasedCall(Arena* arena, if (channelz_node != nullptr) { channelz_node->RecordCallStarted(); } + ScopedContext activity_context(this); // TODO(yashykt): In the future, we want to also enable stats and trace // collecting from when the call is created at the transport. The idea is that // the transport would create the call tracer and pass it in as part of the // metadata. - if (args->server->server_call_tracer_factory() != nullptr) { + // TODO(yijiem): OpenCensus and internal Census is still using this way to + // set server call tracer. We need to refactor them to stats plugins + // (including removing the client channel filters). + if (args->server != nullptr && + args->server->server_call_tracer_factory() != nullptr) { auto* server_call_tracer = args->server->server_call_tracer_factory()->CreateNewServerCallTracer( arena, args->server->channel_args()); @@ -3409,7 +3429,8 @@ ServerPromiseBasedCall::ServerPromiseBasedCall(Arena* arena, ContextSet(GRPC_CONTEXT_CALL_TRACER, server_call_tracer, nullptr); } } - ScopedContext activity_context(this); + args->channel->channel_stack()->stats_plugin_group->AddServerCallTracers( + context()); Spawn("server_promise", channel()->channel_stack()->MakeServerCallPromise( CallArgs{nullptr, ClientInitialMetadataOutstandingToken::Empty(), diff --git a/src/core/lib/surface/legacy_channel.cc b/src/core/lib/surface/legacy_channel.cc index 4a6bc9fcf9c..67d6c2f341b 100644 --- a/src/core/lib/surface/legacy_channel.cc +++ b/src/core/lib/surface/legacy_channel.cc @@ -89,12 +89,17 @@ absl::StatusOr> LegacyChannel::Create( status.ToString().c_str()); return status; } - // TODO(roth): Figure out how to populate authority here. - // Or maybe just don't worry about this if no one needs it until after - // the call v3 stack lands. - StatsPlugin::ChannelScope scope(builder.target(), ""); - *(*r)->stats_plugin_group = - GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope); + if (channel_stack_type == GRPC_SERVER_CHANNEL) { + *(*r)->stats_plugin_group = + GlobalStatsPluginRegistry::GetStatsPluginsForServer(args); + } else { + // TODO(roth): Figure out how to populate authority here. + // Or maybe just don't worry about this if no one needs it until after + // the call v3 stack lands. + StatsPlugin::ChannelScope scope(target, ""); + *(*r)->stats_plugin_group = + GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope); + } return MakeOrphanable( grpc_channel_stack_type_is_client(builder.channel_stack_type()), builder.IsPromising(), std::move(target), args, std::move(*r)); diff --git a/src/core/plugin_registry/grpc_plugin_registry.cc b/src/core/plugin_registry/grpc_plugin_registry.cc index 9f1c6cf9482..60fd3496d3c 100644 --- a/src/core/plugin_registry/grpc_plugin_registry.cc +++ b/src/core/plugin_registry/grpc_plugin_registry.cc @@ -20,6 +20,7 @@ #include +#include "src/core/lib/channel/server_call_tracer_filter.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/surface/lame_client.h" @@ -27,7 +28,6 @@ #include "src/core/lib/transport/http_connect_handshaker.h" #include "src/core/lib/transport/tcp_connect_handshaker.h" - namespace grpc_event_engine { namespace experimental { extern void RegisterEventEngineChannelArgPreconditioning( diff --git a/src/cpp/ext/otel/BUILD b/src/cpp/ext/otel/BUILD index d1e8d173d55..824ae9eea71 100644 --- a/src/cpp/ext/otel/BUILD +++ b/src/cpp/ext/otel/BUILD @@ -31,14 +31,13 @@ package( grpc_cc_library( name = "otel_plugin", srcs = [ - "otel_client_filter.cc", + "otel_client_call_tracer.cc", "otel_plugin.cc", "otel_server_call_tracer.cc", ], hdrs = [ "key_value_iterable.h", - "otel_call_tracer.h", - "otel_client_filter.h", + "otel_client_call_tracer.h", "otel_plugin.h", "otel_server_call_tracer.h", "//:include/grpcpp/ext/otel_plugin.h", @@ -77,6 +76,7 @@ grpc_cc_library( "//src/core:context", "//src/core:error", "//src/core:metadata_batch", + "//src/core:metrics", "//src/core:slice", "//src/core:slice_buffer", ], diff --git a/src/cpp/ext/otel/key_value_iterable.h b/src/cpp/ext/otel/key_value_iterable.h index 76a48d01448..89c158f2016 100644 --- a/src/cpp/ext/otel/key_value_iterable.h +++ b/src/cpp/ext/otel/key_value_iterable.h @@ -46,23 +46,26 @@ inline opentelemetry::nostd::string_view AbslStrViewToOpenTelemetryStrView( // An iterable class based on opentelemetry::common::KeyValueIterable that // allows gRPC to iterate on its various sources of attributes and avoid an // allocation in cases wherever possible. -class KeyValueIterable : public opentelemetry::common::KeyValueIterable { +class OpenTelemetryPlugin::KeyValueIterable + : public opentelemetry::common::KeyValueIterable { public: - explicit KeyValueIterable( + KeyValueIterable( const std::vector>& injected_labels_from_plugin_options, absl::Span> additional_labels, - const ActivePluginOptionsView* active_plugin_options_view, + const OpenTelemetryPlugin::ActivePluginOptionsView* + active_plugin_options_view, absl::Span>> optional_labels_span, - bool is_client) + bool is_client, const OpenTelemetryPlugin* otel_plugin) : injected_labels_from_plugin_options_( injected_labels_from_plugin_options), additional_labels_(additional_labels), active_plugin_options_view_(active_plugin_options_view), optional_labels_(optional_labels_span), - is_client_(is_client) {} + is_client_(is_client), + otel_plugin_(otel_plugin) {} bool ForEachKeyValue(opentelemetry::nostd::function_ref< bool(opentelemetry::nostd::string_view, @@ -75,7 +78,8 @@ class KeyValueIterable : public opentelemetry::common::KeyValueIterable { size_t /*index*/) { return plugin_option.labels_injector()->AddOptionalLabels( is_client_, optional_labels_, callback); - })) { + }, + otel_plugin_)) { return false; } for (const auto& plugin_option_injected_iterable : @@ -115,7 +119,8 @@ class KeyValueIterable : public opentelemetry::common::KeyValueIterable { size += plugin_option.labels_injector()->GetOptionalLabelsSize( is_client_, optional_labels_); return true; - }); + }, + otel_plugin_); } return size; } @@ -125,10 +130,12 @@ class KeyValueIterable : public opentelemetry::common::KeyValueIterable { injected_labels_from_plugin_options_; absl::Span> additional_labels_; - const ActivePluginOptionsView* active_plugin_options_view_; + const OpenTelemetryPlugin::ActivePluginOptionsView* + active_plugin_options_view_; absl::Span>> optional_labels_; bool is_client_; + const OpenTelemetryPlugin* otel_plugin_; }; } // namespace internal diff --git a/src/cpp/ext/otel/otel_client_call_tracer.cc b/src/cpp/ext/otel/otel_client_call_tracer.cc new file mode 100644 index 00000000000..8dafe16db62 --- /dev/null +++ b/src/cpp/ext/otel/otel_client_call_tracer.cc @@ -0,0 +1,282 @@ +// +// +// Copyright 2023 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. +// +// + +#include + +#include "src/cpp/ext/otel/otel_client_call_tracer.h" + +#include + +#include +#include +#include +#include +#include + +#include "absl/functional/any_invocable.h" +#include "absl/status/status.h" +#include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" +#include "absl/strings/strip.h" +#include "absl/time/clock.h" +#include "absl/time/time.h" +#include "absl/types/optional.h" +#include "absl/types/span.h" +#include "opentelemetry/context/context.h" +#include "opentelemetry/metrics/sync_instruments.h" + +#include +#include +#include + +#include "src/core/client_channel/client_channel_filter.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/context.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/channel/tcp_tracer.h" +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/promise/context.h" +#include "src/core/lib/resource_quota/arena.h" +#include "src/core/lib/slice/slice.h" +#include "src/core/lib/slice/slice_buffer.h" +#include "src/core/lib/transport/metadata_batch.h" +#include "src/cpp/ext/otel/key_value_iterable.h" +#include "src/cpp/ext/otel/otel_plugin.h" + +namespace grpc { +namespace internal { + +// +// OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer +// + +OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::CallAttemptTracer( + const OpenTelemetryPlugin::ClientCallTracer* parent, bool arena_allocated) + : parent_(parent), + arena_allocated_(arena_allocated), + start_time_(absl::Now()) { + if (parent_->otel_plugin_->client_.attempt.started != nullptr) { + std::array, 2> + additional_labels = { + {{OpenTelemetryMethodKey(), parent_->MethodForStats()}, + {OpenTelemetryTargetKey(), + parent_->scope_config_->filtered_target()}}}; + // We might not have all the injected labels that we want at this point, so + // avoid recording a subset of injected labels here. + parent_->otel_plugin_->client_.attempt.started->Add( + 1, KeyValueIterable( + /*injected_labels_from_plugin_options=*/{}, additional_labels, + /*active_plugin_options_view=*/nullptr, + /*optional_labels_span=*/{}, /*is_client=*/true, + parent_->otel_plugin_)); + } +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + RecordReceivedInitialMetadata(grpc_metadata_batch* recv_initial_metadata) { + parent_->scope_config_->active_plugin_options_view().ForEach( + [&](const InternalOpenTelemetryPluginOption& plugin_option, + size_t /*index*/) { + auto* labels_injector = plugin_option.labels_injector(); + if (labels_injector != nullptr) { + injected_labels_from_plugin_options_.push_back( + labels_injector->GetLabels(recv_initial_metadata)); + } + return true; + }, + parent_->otel_plugin_); +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + RecordSendInitialMetadata(grpc_metadata_batch* send_initial_metadata) { + parent_->scope_config_->active_plugin_options_view().ForEach( + [&](const InternalOpenTelemetryPluginOption& plugin_option, + size_t /*index*/) { + auto* labels_injector = plugin_option.labels_injector(); + if (labels_injector != nullptr) { + labels_injector->AddLabels(send_initial_metadata, nullptr); + } + return true; + }, + parent_->otel_plugin_); +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + RecordSendMessage(const grpc_core::SliceBuffer& send_message) { + RecordAnnotation( + absl::StrFormat("Send message: %ld bytes", send_message.Length())); +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + RecordSendCompressedMessage( + const grpc_core::SliceBuffer& send_compressed_message) { + RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes", + send_compressed_message.Length())); +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + RecordReceivedMessage(const grpc_core::SliceBuffer& recv_message) { + RecordAnnotation( + absl::StrFormat("Received message: %ld bytes", recv_message.Length())); +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + RecordReceivedDecompressedMessage( + const grpc_core::SliceBuffer& recv_decompressed_message) { + RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes", + recv_decompressed_message.Length())); +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + RecordReceivedTrailingMetadata( + absl::Status status, grpc_metadata_batch* /*recv_trailing_metadata*/, + const grpc_transport_stream_stats* transport_stream_stats) { + std::array, 3> + additional_labels = { + {{OpenTelemetryMethodKey(), parent_->MethodForStats()}, + {OpenTelemetryTargetKey(), + parent_->scope_config_->filtered_target()}, + {OpenTelemetryStatusKey(), + grpc_status_code_to_string( + static_cast(status.code()))}}}; + KeyValueIterable labels( + injected_labels_from_plugin_options_, additional_labels, + &parent_->scope_config_->active_plugin_options_view(), + optional_labels_array_, /*is_client=*/true, parent_->otel_plugin_); + if (parent_->otel_plugin_->client_.attempt.duration != nullptr) { + parent_->otel_plugin_->client_.attempt.duration->Record( + absl::ToDoubleSeconds(absl::Now() - start_time_), labels, + opentelemetry::context::Context{}); + } + if (parent_->otel_plugin_->client_.attempt + .sent_total_compressed_message_size != nullptr) { + parent_->otel_plugin_->client_.attempt.sent_total_compressed_message_size + ->Record(transport_stream_stats != nullptr + ? transport_stream_stats->outgoing.data_bytes + : 0, + labels, opentelemetry::context::Context{}); + } + if (parent_->otel_plugin_->client_.attempt + .rcvd_total_compressed_message_size != nullptr) { + parent_->otel_plugin_->client_.attempt.rcvd_total_compressed_message_size + ->Record(transport_stream_stats != nullptr + ? transport_stream_stats->incoming.data_bytes + : 0, + labels, opentelemetry::context::Context{}); + } +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordCancel( + absl::Status /*cancel_error*/) {} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordEnd( + const gpr_timespec& /*latency*/) { + if (arena_allocated_) { + this->~CallAttemptTracer(); + } else { + delete this; + } +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordAnnotation( + absl::string_view /*annotation*/) { + // Not implemented +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordAnnotation( + const Annotation& /*annotation*/) { + // Not implemented +} + +std::shared_ptr +OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::StartNewTcpTrace() { + // No TCP trace. + return nullptr; +} + +void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer:: + AddOptionalLabels( + OptionalLabelComponent component, + std::shared_ptr> optional_labels) { + optional_labels_array_[static_cast(component)] = + std::move(optional_labels); +} + +// +// OpenTelemetryPlugin::ClientCallTracer +// + +OpenTelemetryPlugin::ClientCallTracer::ClientCallTracer( + const grpc_core::Slice& path, grpc_core::Arena* arena, + bool registered_method, OpenTelemetryPlugin* otel_plugin, + std::shared_ptr scope_config) + : path_(path.Ref()), + arena_(arena), + registered_method_(registered_method), + otel_plugin_(otel_plugin), + scope_config_(std::move(scope_config)) {} + +OpenTelemetryPlugin::ClientCallTracer::~ClientCallTracer() {} + +OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer* +OpenTelemetryPlugin::ClientCallTracer::StartNewAttempt( + bool is_transparent_retry) { + // We allocate the first attempt on the arena and all subsequent attempts + // on the heap, so that in the common case we don't require a heap + // allocation, nor do we unnecessarily grow the arena. + bool is_first_attempt = true; + { + grpc_core::MutexLock lock(&mu_); + if (transparent_retries_ != 0 || retries_ != 0) { + is_first_attempt = false; + } + if (is_transparent_retry) { + ++transparent_retries_; + } else { + ++retries_; + } + } + if (is_first_attempt) { + return arena_->New(this, /*arena_allocated=*/true); + } + return new CallAttemptTracer(this, /*arena_allocated=*/false); +} + +absl::string_view OpenTelemetryPlugin::ClientCallTracer::MethodForStats() + const { + absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/"); + if (registered_method_ || + (otel_plugin_->generic_method_attribute_filter() != nullptr && + otel_plugin_->generic_method_attribute_filter()(method))) { + return method; + } + return "other"; +} + +void OpenTelemetryPlugin::ClientCallTracer::RecordAnnotation( + absl::string_view /*annotation*/) { + // Not implemented +} + +void OpenTelemetryPlugin::ClientCallTracer::RecordAnnotation( + const Annotation& /*annotation*/) { + // Not implemented +} + +} // namespace internal +} // namespace grpc diff --git a/src/cpp/ext/otel/otel_call_tracer.h b/src/cpp/ext/otel/otel_client_call_tracer.h similarity index 82% rename from src/cpp/ext/otel/otel_call_tracer.h rename to src/cpp/ext/otel/otel_client_call_tracer.h index cda80c39f74..e88aeac16a5 100644 --- a/src/cpp/ext/otel/otel_call_tracer.h +++ b/src/cpp/ext/otel/otel_client_call_tracer.h @@ -16,8 +16,8 @@ // // -#ifndef GRPC_SRC_CPP_EXT_OTEL_OTEL_CALL_TRACER_H -#define GRPC_SRC_CPP_EXT_OTEL_OTEL_CALL_TRACER_H +#ifndef GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_CALL_TRACER_H +#define GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_CALL_TRACER_H #include @@ -42,18 +42,19 @@ #include "src/core/lib/slice/slice_buffer.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" -#include "src/cpp/ext/otel/otel_client_filter.h" #include "src/cpp/ext/otel/otel_plugin.h" namespace grpc { namespace internal { -class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer { +class OpenTelemetryPlugin::ClientCallTracer + : public grpc_core::ClientCallTracer { public: - class OpenTelemetryCallAttemptTracer : public CallAttemptTracer { + class CallAttemptTracer + : public grpc_core::ClientCallTracer::CallAttemptTracer { public: - OpenTelemetryCallAttemptTracer(const OpenTelemetryCallTracer* parent, - bool arena_allocated); + CallAttemptTracer(const OpenTelemetryPlugin::ClientCallTracer* parent, + bool arena_allocated); std::string TraceId() override { // Not implemented @@ -96,7 +97,7 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer { optional_labels) override; private: - const OpenTelemetryCallTracer* parent_; + const ClientCallTracer* parent_; const bool arena_allocated_; // Start time (for measuring latency). absl::Time start_time_; @@ -109,11 +110,11 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer { injected_labels_from_plugin_options_; }; - explicit OpenTelemetryCallTracer(OpenTelemetryClientFilter* parent, - grpc_core::Slice path, - grpc_core::Arena* arena, - bool registered_method); - ~OpenTelemetryCallTracer() override; + ClientCallTracer( + const grpc_core::Slice& path, grpc_core::Arena* arena, + bool registered_method, OpenTelemetryPlugin* otel_plugin, + std::shared_ptr scope_config); + ~ClientCallTracer() override; std::string TraceId() override { // Not implemented @@ -130,19 +131,19 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer { return false; } - OpenTelemetryCallAttemptTracer* StartNewAttempt( - bool is_transparent_retry) override; + CallAttemptTracer* StartNewAttempt(bool is_transparent_retry) override; void RecordAnnotation(absl::string_view /*annotation*/) override; void RecordAnnotation(const Annotation& /*annotation*/) override; private: absl::string_view MethodForStats() const; - const OpenTelemetryClientFilter* parent_; // Client method. grpc_core::Slice path_; grpc_core::Arena* arena_; const bool registered_method_; + OpenTelemetryPlugin* otel_plugin_; + std::shared_ptr scope_config_; grpc_core::Mutex mu_; // Non-transparent attempts per call uint64_t retries_ ABSL_GUARDED_BY(&mu_) = 0; @@ -153,4 +154,4 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer { } // namespace internal } // namespace grpc -#endif // GRPC_SRC_CPP_EXT_OTEL_OTEL_CALL_TRACER_H +#endif // GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_CALL_TRACER_H diff --git a/src/cpp/ext/otel/otel_client_filter.cc b/src/cpp/ext/otel/otel_client_filter.cc deleted file mode 100644 index dfef7badf62..00000000000 --- a/src/cpp/ext/otel/otel_client_filter.cc +++ /dev/null @@ -1,328 +0,0 @@ -// -// -// Copyright 2023 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. -// -// - -#include - -#include "src/cpp/ext/otel/otel_client_filter.h" - -#include - -#include -#include -#include -#include -#include - -#include "absl/functional/any_invocable.h" -#include "absl/status/status.h" -#include "absl/strings/str_format.h" -#include "absl/strings/string_view.h" -#include "absl/strings/strip.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" -#include "absl/types/optional.h" -#include "absl/types/span.h" -#include "opentelemetry/context/context.h" -#include "opentelemetry/metrics/sync_instruments.h" - -#include -#include -#include - -#include "src/core/client_channel/client_channel_filter.h" -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/channel/context.h" -#include "src/core/lib/channel/status_util.h" -#include "src/core/lib/channel/tcp_tracer.h" -#include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/promise/context.h" -#include "src/core/lib/resource_quota/arena.h" -#include "src/core/lib/slice/slice.h" -#include "src/core/lib/slice/slice_buffer.h" -#include "src/core/lib/transport/metadata_batch.h" -#include "src/cpp/ext/otel/key_value_iterable.h" -#include "src/cpp/ext/otel/otel_call_tracer.h" -#include "src/cpp/ext/otel/otel_plugin.h" - -namespace grpc { -namespace internal { - -// -// OpenTelemetryClientFilter -// - -const grpc_channel_filter OpenTelemetryClientFilter::kFilter = - grpc_core::MakePromiseBasedFilter( - "otel_client"); - -absl::StatusOr OpenTelemetryClientFilter::Create( - const grpc_core::ChannelArgs& args, ChannelFilter::Args /*filter_args*/) { - return OpenTelemetryClientFilter( - args.GetOwnedString(GRPC_ARG_SERVER_URI).value_or("")); -} - -grpc_core::ArenaPromise -OpenTelemetryClientFilter::MakeCallPromise( - grpc_core::CallArgs call_args, - grpc_core::NextPromiseFactory next_promise_factory) { - auto* path = call_args.client_initial_metadata->get_pointer( - grpc_core::HttpPathMetadata()); - bool registered_method = reinterpret_cast( - call_args.client_initial_metadata->get(grpc_core::GrpcRegisteredMethod()) - .value_or(nullptr)); - auto* call_context = grpc_core::GetContext(); - auto* tracer = - grpc_core::GetContext() - ->ManagedNew( - this, path != nullptr ? path->Ref() : grpc_core::Slice(), - grpc_core::GetContext(), registered_method); - GPR_DEBUG_ASSERT( - call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value == - nullptr); - call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value = tracer; - call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].destroy = nullptr; - return next_promise_factory(std::move(call_args)); -} - -OpenTelemetryClientFilter::OpenTelemetryClientFilter(std::string target) - : active_plugin_options_view_( - ActivePluginOptionsView::MakeForClient(target)) { - // Use the original target string only if a filter on the attribute is not - // registered or if the filter returns true, otherwise use "other". - if (OpenTelemetryPluginState().target_attribute_filter == nullptr || - OpenTelemetryPluginState().target_attribute_filter(target)) { - filtered_target_ = std::move(target); - } else { - filtered_target_ = "other"; - } -} - -// -// OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer -// - -OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer:: - OpenTelemetryCallAttemptTracer(const OpenTelemetryCallTracer* parent, - bool arena_allocated) - : parent_(parent), - arena_allocated_(arena_allocated), - start_time_(absl::Now()) { - if (OpenTelemetryPluginState().client.attempt.started != nullptr) { - std::array, 2> - additional_labels = { - {{OpenTelemetryMethodKey(), parent_->MethodForStats()}, - {OpenTelemetryTargetKey(), parent_->parent_->filtered_target()}}}; - // We might not have all the injected labels that we want at this point, so - // avoid recording a subset of injected labels here. - OpenTelemetryPluginState().client.attempt.started->Add( - 1, KeyValueIterable(/*injected_labels_from_plugin_options=*/{}, - additional_labels, - /*active_plugin_options_view=*/nullptr, - /*optional_labels_span=*/{}, /*is_client=*/true)); - } -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer:: - RecordReceivedInitialMetadata(grpc_metadata_batch* recv_initial_metadata) { - parent_->parent_->active_plugin_options_view().ForEach( - [&](const InternalOpenTelemetryPluginOption& plugin_option, - size_t /*index*/) { - auto* labels_injector = plugin_option.labels_injector(); - if (labels_injector != nullptr) { - injected_labels_from_plugin_options_.push_back( - labels_injector->GetLabels(recv_initial_metadata)); - } - return true; - }); -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer:: - RecordSendInitialMetadata(grpc_metadata_batch* send_initial_metadata) { - parent_->parent_->active_plugin_options_view().ForEach( - [&](const InternalOpenTelemetryPluginOption& plugin_option, - size_t /*index*/) { - auto* labels_injector = plugin_option.labels_injector(); - if (labels_injector != nullptr) { - labels_injector->AddLabels(send_initial_metadata, nullptr); - } - return true; - }); -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordSendMessage( - const grpc_core::SliceBuffer& send_message) { - RecordAnnotation( - absl::StrFormat("Send message: %ld bytes", send_message.Length())); -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer:: - RecordSendCompressedMessage( - const grpc_core::SliceBuffer& send_compressed_message) { - RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes", - send_compressed_message.Length())); -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer:: - RecordReceivedMessage(const grpc_core::SliceBuffer& recv_message) { - RecordAnnotation( - absl::StrFormat("Received message: %ld bytes", recv_message.Length())); -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer:: - RecordReceivedDecompressedMessage( - const grpc_core::SliceBuffer& recv_decompressed_message) { - RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes", - recv_decompressed_message.Length())); -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer:: - RecordReceivedTrailingMetadata( - absl::Status status, grpc_metadata_batch* /*recv_trailing_metadata*/, - const grpc_transport_stream_stats* transport_stream_stats) { - std::array, 3> - additional_labels = { - {{OpenTelemetryMethodKey(), parent_->MethodForStats()}, - {OpenTelemetryTargetKey(), parent_->parent_->filtered_target()}, - {OpenTelemetryStatusKey(), - grpc_status_code_to_string( - static_cast(status.code()))}}}; - KeyValueIterable labels(injected_labels_from_plugin_options_, - additional_labels, - &parent_->parent_->active_plugin_options_view(), - optional_labels_array_, /*is_client=*/true); - if (OpenTelemetryPluginState().client.attempt.duration != nullptr) { - OpenTelemetryPluginState().client.attempt.duration->Record( - absl::ToDoubleSeconds(absl::Now() - start_time_), labels, - opentelemetry::context::Context{}); - } - if (OpenTelemetryPluginState() - .client.attempt.sent_total_compressed_message_size != nullptr) { - OpenTelemetryPluginState() - .client.attempt.sent_total_compressed_message_size->Record( - transport_stream_stats != nullptr - ? transport_stream_stats->outgoing.data_bytes - : 0, - labels, opentelemetry::context::Context{}); - } - if (OpenTelemetryPluginState() - .client.attempt.rcvd_total_compressed_message_size != nullptr) { - OpenTelemetryPluginState() - .client.attempt.rcvd_total_compressed_message_size->Record( - transport_stream_stats != nullptr - ? transport_stream_stats->incoming.data_bytes - : 0, - labels, opentelemetry::context::Context{}); - } -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordCancel( - absl::Status /*cancel_error*/) {} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordEnd( - const gpr_timespec& /*latency*/) { - if (arena_allocated_) { - this->~OpenTelemetryCallAttemptTracer(); - } else { - delete this; - } -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordAnnotation( - absl::string_view /*annotation*/) { - // Not implemented -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordAnnotation( - const Annotation& /*annotation*/) { - // Not implemented -} - -std::shared_ptr -OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::StartNewTcpTrace() { - // No TCP trace. - return nullptr; -} - -void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::AddOptionalLabels( - OptionalLabelComponent component, - std::shared_ptr> optional_labels) { - optional_labels_array_[static_cast(component)] = - std::move(optional_labels); -} - -// -// OpenTelemetryCallTracer -// - -OpenTelemetryCallTracer::OpenTelemetryCallTracer( - OpenTelemetryClientFilter* parent, grpc_core::Slice path, - grpc_core::Arena* arena, bool registered_method) - : parent_(parent), - path_(std::move(path)), - arena_(arena), - registered_method_(registered_method) {} - -OpenTelemetryCallTracer::~OpenTelemetryCallTracer() {} - -OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer* -OpenTelemetryCallTracer::StartNewAttempt(bool is_transparent_retry) { - // We allocate the first attempt on the arena and all subsequent attempts - // on the heap, so that in the common case we don't require a heap - // allocation, nor do we unnecessarily grow the arena. - bool is_first_attempt = true; - { - grpc_core::MutexLock lock(&mu_); - if (transparent_retries_ != 0 || retries_ != 0) { - is_first_attempt = false; - } - if (is_transparent_retry) { - ++transparent_retries_; - } else { - ++retries_; - } - } - if (is_first_attempt) { - return arena_->New( - this, /*arena_allocated=*/true); - } - return new OpenTelemetryCallAttemptTracer(this, /*arena_allocated=*/false); -} - -absl::string_view OpenTelemetryCallTracer::MethodForStats() const { - absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/"); - if (registered_method_ || - (OpenTelemetryPluginState().generic_method_attribute_filter != nullptr && - OpenTelemetryPluginState().generic_method_attribute_filter(method))) { - return method; - } - return "other"; -} - -void OpenTelemetryCallTracer::RecordAnnotation( - absl::string_view /*annotation*/) { - // Not implemented -} - -void OpenTelemetryCallTracer::RecordAnnotation( - const Annotation& /*annotation*/) { - // Not implemented -} - -} // namespace internal -} // namespace grpc diff --git a/src/cpp/ext/otel/otel_client_filter.h b/src/cpp/ext/otel/otel_client_filter.h deleted file mode 100644 index 7c0ddcc6f98..00000000000 --- a/src/cpp/ext/otel/otel_client_filter.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// -// Copyright 2023 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. -// -// - -#ifndef GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_FILTER_H -#define GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_FILTER_H - -#include - -#include -#include - -#include "absl/status/statusor.h" -#include "absl/strings/string_view.h" - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/channel_fwd.h" -#include "src/core/lib/channel/promise_based_filter.h" -#include "src/core/lib/promise/arena_promise.h" -#include "src/core/lib/transport/transport.h" -#include "src/cpp/ext/otel/otel_plugin.h" - -namespace grpc { -namespace internal { - -class OpenTelemetryClientFilter : public grpc_core::ChannelFilter { - public: - static const grpc_channel_filter kFilter; - - static absl::StatusOr Create( - const grpc_core::ChannelArgs& /*args*/, - ChannelFilter::Args /*filter_args*/); - - grpc_core::ArenaPromise MakeCallPromise( - grpc_core::CallArgs call_args, - grpc_core::NextPromiseFactory next_promise_factory) override; - - absl::string_view filtered_target() const { return filtered_target_; } - - const ActivePluginOptionsView& active_plugin_options_view() const { - return active_plugin_options_view_; - } - - private: - explicit OpenTelemetryClientFilter(std::string target); - - std::string filtered_target_; - ActivePluginOptionsView active_plugin_options_view_; -}; - -} // namespace internal -} // namespace grpc - -#endif // GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_FILTER_H diff --git a/src/cpp/ext/otel/otel_plugin.cc b/src/cpp/ext/otel/otel_plugin.cc index b61af9857c1..ca82c67e0ce 100644 --- a/src/cpp/ext/otel/otel_plugin.cc +++ b/src/cpp/ext/otel/otel_plugin.cc @@ -20,11 +20,13 @@ #include "src/cpp/ext/otel/otel_plugin.h" +#include #include #include #include "opentelemetry/metrics/meter.h" #include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/metrics/sync_instruments.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/nostd/unique_ptr.h" @@ -37,21 +39,13 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/surface/channel_stack_type.h" -#include "src/cpp/ext/otel/otel_client_filter.h" +#include "src/cpp/ext/otel/key_value_iterable.h" +#include "src/cpp/ext/otel/otel_client_call_tracer.h" #include "src/cpp/ext/otel/otel_server_call_tracer.h" namespace grpc { namespace internal { -// TODO(yashykt): Extend this to allow multiple OpenTelemetry plugins to be -// registered in the same binary. -struct OpenTelemetryPluginState* g_otel_plugin_state_; - -const struct OpenTelemetryPluginState& OpenTelemetryPluginState() { - GPR_DEBUG_ASSERT(g_otel_plugin_state_ != nullptr); - return *g_otel_plugin_state_; -} - absl::string_view OpenTelemetryMethodKey() { return "grpc.method"; } absl::string_view OpenTelemetryStatusKey() { return "grpc.status"; } @@ -60,7 +54,7 @@ absl::string_view OpenTelemetryTargetKey() { return "grpc.target"; } namespace { absl::flat_hash_set BaseMetrics() { - return absl::flat_hash_set{ + absl::flat_hash_set base_metrics{ std::string(grpc::OpenTelemetryPluginBuilder:: kClientAttemptStartedInstrumentName), std::string(grpc::OpenTelemetryPluginBuilder:: @@ -79,9 +73,67 @@ absl::flat_hash_set BaseMetrics() { kServerCallSentTotalCompressedMessageSizeInstrumentName), std::string(grpc::OpenTelemetryPluginBuilder:: kServerCallRcvdTotalCompressedMessageSizeInstrumentName)}; + grpc_core::GlobalInstrumentsRegistry::ForEach( + [&](const grpc_core::GlobalInstrumentsRegistry:: + GlobalInstrumentDescriptor& descriptor) { + if (descriptor.enable_by_default) { + base_metrics.emplace(descriptor.name); + } + }); + return base_metrics; } } // namespace +class OpenTelemetryPlugin::NPCMetricsKeyValueIterable + : public opentelemetry::common::KeyValueIterable { + public: + NPCMetricsKeyValueIterable( + absl::Span label_keys, + absl::Span label_values, + absl::Span optional_label_keys, + absl::Span optional_label_values, + const OptionalLabelsBitSet& optional_labels_bits) + : label_keys_(label_keys), + label_values_(label_values), + optional_label_keys_(optional_label_keys), + optional_label_values_(optional_label_values), + optional_labels_bits_(optional_labels_bits) {} + + bool ForEachKeyValue(opentelemetry::nostd::function_ref< + bool(opentelemetry::nostd::string_view, + opentelemetry::common::AttributeValue)> + callback) const noexcept override { + for (size_t i = 0; i < label_keys_.size(); i++) { + if (!callback(AbslStrViewToOpenTelemetryStrView(label_keys_[i]), + AbslStrViewToOpenTelemetryStrView(label_values_[i]))) { + return false; + } + } + for (size_t i = 0; i < optional_label_keys_.size(); ++i) { + if (!optional_labels_bits_.test(i)) { + continue; + } + if (!callback( + AbslStrViewToOpenTelemetryStrView(optional_label_keys_[i]), + AbslStrViewToOpenTelemetryStrView(optional_label_values_[i]))) { + return false; + } + } + return true; + } + + size_t size() const noexcept override { + return label_keys_.size() + optional_labels_bits_.count(); + } + + private: + absl::Span label_keys_; + absl::Span label_values_; + absl::Span optional_label_keys_; + absl::Span optional_label_values_; + const OptionalLabelsBitSet& optional_labels_bits_; +}; + // // OpenTelemetryPluginBuilderImpl // @@ -156,112 +208,352 @@ OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::AddPluginOption( return *this; } +OpenTelemetryPluginBuilderImpl& +OpenTelemetryPluginBuilderImpl::AddOptionalLabel( + absl::string_view optional_label_key) { + if (optional_label_keys_ == nullptr) { + optional_label_keys_ = std::make_shared>(); + } + optional_label_keys_->emplace(optional_label_key); + return *this; +} + absl::Status OpenTelemetryPluginBuilderImpl::BuildAndRegisterGlobal() { - opentelemetry::nostd::shared_ptr - meter_provider = meter_provider_; - delete g_otel_plugin_state_; - g_otel_plugin_state_ = new struct OpenTelemetryPluginState; - if (meter_provider == nullptr) { + if (meter_provider_ == nullptr) { return absl::OkStatus(); } - auto meter = meter_provider->GetMeter("grpc-c++", GRPC_CPP_VERSION_STRING); - if (metrics_.contains(grpc::OpenTelemetryPluginBuilder:: - kClientAttemptStartedInstrumentName)) { - g_otel_plugin_state_->client.attempt.started = meter->CreateUInt64Counter( + grpc_core::GlobalStatsPluginRegistry::RegisterStatsPlugin( + std::make_shared( + metrics_, meter_provider_, std::move(target_selector_), + std::move(target_attribute_filter_), + std::move(generic_method_attribute_filter_), + std::move(server_selector_), std::move(plugin_options_), + std::move(optional_label_keys_))); + return absl::OkStatus(); +} + +OpenTelemetryPlugin::OpenTelemetryPlugin( + const absl::flat_hash_set& metrics, + opentelemetry::nostd::shared_ptr + meter_provider, + absl::AnyInvocable + target_selector, + absl::AnyInvocable + target_attribute_filter, + absl::AnyInvocable + generic_method_attribute_filter, + absl::AnyInvocable + server_selector, + std::vector> + plugin_options, + std::shared_ptr> optional_label_keys) + : meter_provider_(std::move(meter_provider)), + target_selector_(std::move(target_selector)), + server_selector_(std::move(server_selector)), + target_attribute_filter_(std::move(target_attribute_filter)), + generic_method_attribute_filter_( + std::move(generic_method_attribute_filter)), + plugin_options_(std::move(plugin_options)) { + auto meter = meter_provider_->GetMeter("grpc-c++", GRPC_CPP_VERSION_STRING); + // Per-call metrics. + if (metrics.contains(grpc::OpenTelemetryPluginBuilder:: + kClientAttemptStartedInstrumentName)) { + client_.attempt.started = meter->CreateUInt64Counter( std::string(grpc::OpenTelemetryPluginBuilder:: kClientAttemptStartedInstrumentName), "Number of client call attempts started", "{attempt}"); } - if (metrics_.contains(grpc::OpenTelemetryPluginBuilder:: - kClientAttemptDurationInstrumentName)) { - g_otel_plugin_state_->client.attempt.duration = - meter->CreateDoubleHistogram( - std::string(grpc::OpenTelemetryPluginBuilder:: - kClientAttemptDurationInstrumentName), - "End-to-end time taken to complete a client call attempt", "s"); + if (metrics.contains(grpc::OpenTelemetryPluginBuilder:: + kClientAttemptDurationInstrumentName)) { + client_.attempt.duration = meter->CreateDoubleHistogram( + std::string(grpc::OpenTelemetryPluginBuilder:: + kClientAttemptDurationInstrumentName), + "End-to-end time taken to complete a client call attempt", "s"); } - if (metrics_.contains( + if (metrics.contains( grpc::OpenTelemetryPluginBuilder:: kClientAttemptSentTotalCompressedMessageSizeInstrumentName)) { - g_otel_plugin_state_->client.attempt.sent_total_compressed_message_size = + client_.attempt.sent_total_compressed_message_size = meter->CreateUInt64Histogram( std::string( grpc::OpenTelemetryPluginBuilder:: kClientAttemptSentTotalCompressedMessageSizeInstrumentName), "Compressed message bytes sent per client call attempt", "By"); } - if (metrics_.contains( + if (metrics.contains( grpc::OpenTelemetryPluginBuilder:: kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName)) { - g_otel_plugin_state_->client.attempt.rcvd_total_compressed_message_size = + client_.attempt.rcvd_total_compressed_message_size = meter->CreateUInt64Histogram( std::string( grpc::OpenTelemetryPluginBuilder:: kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName), "Compressed message bytes received per call attempt", "By"); } - if (metrics_.contains( + if (metrics.contains( grpc::OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName)) { - g_otel_plugin_state_->server.call.started = meter->CreateUInt64Counter( + server_.call.started = meter->CreateUInt64Counter( std::string( grpc::OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName), "Number of server calls started", "{call}"); } - if (metrics_.contains(grpc::OpenTelemetryPluginBuilder:: - kServerCallDurationInstrumentName)) { - g_otel_plugin_state_->server.call.duration = meter->CreateDoubleHistogram( + if (metrics.contains(grpc::OpenTelemetryPluginBuilder:: + kServerCallDurationInstrumentName)) { + server_.call.duration = meter->CreateDoubleHistogram( std::string(grpc::OpenTelemetryPluginBuilder:: kServerCallDurationInstrumentName), "End-to-end time taken to complete a call from server transport's " "perspective", "s"); } - if (metrics_.contains( + if (metrics.contains( grpc::OpenTelemetryPluginBuilder:: kServerCallSentTotalCompressedMessageSizeInstrumentName)) { - g_otel_plugin_state_->server.call.sent_total_compressed_message_size = + server_.call.sent_total_compressed_message_size = meter->CreateUInt64Histogram( std::string( grpc::OpenTelemetryPluginBuilder:: kServerCallSentTotalCompressedMessageSizeInstrumentName), "Compressed message bytes sent per server call", "By"); } - if (metrics_.contains( + if (metrics.contains( grpc::OpenTelemetryPluginBuilder:: kServerCallRcvdTotalCompressedMessageSizeInstrumentName)) { - g_otel_plugin_state_->server.call.rcvd_total_compressed_message_size = + server_.call.rcvd_total_compressed_message_size = meter->CreateUInt64Histogram( std::string( grpc::OpenTelemetryPluginBuilder:: kServerCallRcvdTotalCompressedMessageSizeInstrumentName), "Compressed message bytes received per server call", "By"); } - g_otel_plugin_state_->target_attribute_filter = - std::move(target_attribute_filter_); - g_otel_plugin_state_->server_selector = std::move(server_selector_); - g_otel_plugin_state_->generic_method_attribute_filter = - std::move(generic_method_attribute_filter_); - g_otel_plugin_state_->meter_provider = std::move(meter_provider); - g_otel_plugin_state_->plugin_options = std::move(plugin_options_); - grpc_core::ServerCallTracerFactory::RegisterGlobal( - new grpc::internal::OpenTelemetryServerCallTracerFactory()); - grpc_core::CoreConfiguration::RegisterBuilder( - [target_selector = std::move(target_selector_)]( - grpc_core::CoreConfiguration::Builder* builder) mutable { - builder->channel_init() - ->RegisterFilter( - GRPC_CLIENT_CHANNEL, - &grpc::internal::OpenTelemetryClientFilter::kFilter) - .If([target_selector = std::move(target_selector)]( - const grpc_core::ChannelArgs& args) { - // Only register the filter if no channel selector has been set or - // the target selector returns true for the target. - return target_selector == nullptr || - target_selector( - args.GetString(GRPC_ARG_SERVER_URI).value_or("")); - }); + // Non-per-call metrics. + grpc_core::GlobalInstrumentsRegistry::ForEach( + [&, this](const grpc_core::GlobalInstrumentsRegistry:: + GlobalInstrumentDescriptor& descriptor) { + GPR_ASSERT(descriptor.optional_label_keys.size() <= + kOptionalLabelsSizeLimit); + if (instruments_data_.size() < descriptor.index + 1) { + instruments_data_.resize(descriptor.index + 1); + } + if (!metrics.contains(descriptor.name)) { + return; + } + switch (descriptor.instrument_type) { + case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCounter: + switch (descriptor.value_type) { + case grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64: + instruments_data_[descriptor.index].instrument = + meter->CreateUInt64Counter( + std::string(descriptor.name), + std::string(descriptor.description), + std::string(descriptor.unit)); + break; + case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: + instruments_data_[descriptor.index].instrument = + meter->CreateDoubleCounter( + std::string(descriptor.name), + std::string(descriptor.description), + std::string(descriptor.unit)); + break; + default: + grpc_core::Crash( + absl::StrFormat("Unknown or unsupported value type: %d", + descriptor.value_type)); + } + break; + case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kHistogram: + switch (descriptor.value_type) { + case grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64: + instruments_data_[descriptor.index].instrument = + meter->CreateUInt64Histogram( + std::string(descriptor.name), + std::string(descriptor.description), + std::string(descriptor.unit)); + break; + case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: + instruments_data_[descriptor.index].instrument = + meter->CreateDoubleHistogram( + std::string(descriptor.name), + std::string(descriptor.description), + std::string(descriptor.unit)); + break; + default: + grpc_core::Crash( + absl::StrFormat("Unknown or unsupported value type: %d", + descriptor.value_type)); + } + break; + // TODO(yashkt, yijiem): implement gauges. + case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kGauge: + switch (descriptor.value_type) { + case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64: + break; + case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: + break; + default: + grpc_core::Crash( + absl::StrFormat("Unknown or unsupported value type: %d", + descriptor.value_type)); + } + break; + case grpc_core::GlobalInstrumentsRegistry::InstrumentType:: + kCallbackGauge: + switch (descriptor.value_type) { + case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64: + break; + case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: + break; + default: + grpc_core::Crash( + absl::StrFormat("Unknown or unsupported value type: %d", + descriptor.value_type)); + } + break; + default: + grpc_core::Crash(absl::StrFormat("Unknown instrument_type: %d", + descriptor.instrument_type)); + } + for (size_t i = 0; i < descriptor.optional_label_keys.size(); ++i) { + if (optional_label_keys->find(descriptor.optional_label_keys[i]) != + optional_label_keys->end()) { + instruments_data_[descriptor.index].optional_labels_bits.set(i); + } + } }); - return absl::OkStatus(); +} + +std::pair> +OpenTelemetryPlugin::IsEnabledForChannel(const ChannelScope& scope) const { + if (target_selector_ == nullptr || target_selector_(scope.target())) { + return {true, std::make_shared(this, scope)}; + } + return {false, nullptr}; +} +std::pair> +OpenTelemetryPlugin::IsEnabledForServer( + const grpc_core::ChannelArgs& args) const { + // Return true only if there is no server selector registered or if the server + // selector returns true. + if (server_selector_ == nullptr || server_selector_(args)) { + return {true, std::make_shared(this, args)}; + } + return {false, nullptr}; +} + +void OpenTelemetryPlugin::AddCounter( + grpc_core::GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle, + uint64_t value, absl::Span label_values, + absl::Span optional_values) { + const auto& instrument_data = instruments_data_.at(handle.index); + if (absl::holds_alternative(instrument_data.instrument)) { + // This instrument is disabled. + return; + } + GPR_ASSERT(absl::holds_alternative< + std::unique_ptr>>( + instrument_data.instrument)); + const auto& descriptor = + grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle); + GPR_ASSERT(descriptor.label_keys.size() == label_values.size()); + GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size()); + absl::get>>( + instrument_data.instrument) + ->Add(value, NPCMetricsKeyValueIterable( + descriptor.label_keys, label_values, + descriptor.optional_label_keys, optional_values, + instrument_data.optional_labels_bits)); +} +void OpenTelemetryPlugin::AddCounter( + grpc_core::GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle, + double value, absl::Span label_values, + absl::Span optional_values) { + const auto& instrument_data = instruments_data_.at(handle.index); + if (absl::holds_alternative(instrument_data.instrument)) { + // This instrument is disabled. + return; + } + GPR_ASSERT(absl::holds_alternative< + std::unique_ptr>>( + instrument_data.instrument)); + const auto& descriptor = + grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle); + GPR_ASSERT(descriptor.label_keys.size() == label_values.size()); + GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size()); + absl::get>>( + instrument_data.instrument) + ->Add(value, NPCMetricsKeyValueIterable( + descriptor.label_keys, label_values, + descriptor.optional_label_keys, optional_values, + instrument_data.optional_labels_bits)); +} +void OpenTelemetryPlugin::RecordHistogram( + grpc_core::GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle, + uint64_t value, absl::Span label_values, + absl::Span optional_values) { + const auto& instrument_data = instruments_data_.at(handle.index); + if (absl::holds_alternative(instrument_data.instrument)) { + // This instrument is disabled. + return; + } + GPR_ASSERT(absl::holds_alternative< + std::unique_ptr>>( + instrument_data.instrument)); + const auto& descriptor = + grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle); + GPR_ASSERT(descriptor.label_keys.size() == label_values.size()); + GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size()); + absl::get>>( + instrument_data.instrument) + ->Record(value, + NPCMetricsKeyValueIterable(descriptor.label_keys, label_values, + descriptor.optional_label_keys, + optional_values, + instrument_data.optional_labels_bits), + opentelemetry::context::Context{}); +} +void OpenTelemetryPlugin::RecordHistogram( + grpc_core::GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle, + double value, absl::Span label_values, + absl::Span optional_values) { + const auto& instrument_data = instruments_data_.at(handle.index); + if (absl::holds_alternative(instrument_data.instrument)) { + // This instrument is disabled. + return; + } + GPR_ASSERT(absl::holds_alternative< + std::unique_ptr>>( + instrument_data.instrument)); + const auto& descriptor = + grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle); + GPR_ASSERT(descriptor.label_keys.size() == label_values.size()); + GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size()); + absl::get>>( + instrument_data.instrument) + ->Record(value, + NPCMetricsKeyValueIterable(descriptor.label_keys, label_values, + descriptor.optional_label_keys, + optional_values, + instrument_data.optional_labels_bits), + opentelemetry::context::Context{}); +} + +grpc_core::ClientCallTracer* OpenTelemetryPlugin::GetClientCallTracer( + const grpc_core::Slice& path, bool registered_method, + std::shared_ptr scope_config) { + return grpc_core::GetContext() + ->ManagedNew( + path, grpc_core::GetContext(), registered_method, + this, + std::static_pointer_cast( + scope_config)); +} +grpc_core::ServerCallTracer* OpenTelemetryPlugin::GetServerCallTracer( + std::shared_ptr scope_config) { + return grpc_core::GetContext() + ->ManagedNew( + this, + std::static_pointer_cast( + scope_config)); } } // namespace internal @@ -324,6 +616,12 @@ OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddPluginOption( return *this; } +OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddOptionalLabel( + absl::string_view optional_label_key) { + impl_->AddOptionalLabel(optional_label_key); + return *this; +} + absl::Status OpenTelemetryPluginBuilder::BuildAndRegisterGlobal() { return impl_->BuildAndRegisterGlobal(); } diff --git a/src/cpp/ext/otel/otel_plugin.h b/src/cpp/ext/otel/otel_plugin.h index 90b17ab2353..e8374b6d248 100644 --- a/src/cpp/ext/otel/otel_plugin.h +++ b/src/cpp/ext/otel/otel_plugin.h @@ -40,6 +40,7 @@ #include #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/metrics.h" #include "src/core/lib/transport/metadata_batch.h" namespace grpc { @@ -112,41 +113,6 @@ class InternalOpenTelemetryPluginOption virtual const grpc::internal::LabelsInjector* labels_injector() const = 0; }; -struct OpenTelemetryPluginState { - struct Client { - struct Attempt { - std::unique_ptr> started; - std::unique_ptr> duration; - std::unique_ptr> - sent_total_compressed_message_size; - std::unique_ptr> - rcvd_total_compressed_message_size; - } attempt; - } client; - struct Server { - struct Call { - std::unique_ptr> started; - std::unique_ptr> duration; - std::unique_ptr> - sent_total_compressed_message_size; - std::unique_ptr> - rcvd_total_compressed_message_size; - } call; - } server; - opentelemetry::nostd::shared_ptr - meter_provider; - absl::AnyInvocable - target_attribute_filter; - absl::AnyInvocable - generic_method_attribute_filter; - absl::AnyInvocable - server_selector; - std::vector> - plugin_options; -}; - -const struct OpenTelemetryPluginState& OpenTelemetryPluginState(); - // Tags absl::string_view OpenTelemetryMethodKey(); absl::string_view OpenTelemetryStatusKey(); @@ -202,6 +168,9 @@ class OpenTelemetryPluginBuilderImpl { generic_method_attribute_filter); OpenTelemetryPluginBuilderImpl& AddPluginOption( std::unique_ptr option); + // Records \a optional_label_key on all metrics that provide it. + OpenTelemetryPluginBuilderImpl& AddOptionalLabel( + absl::string_view optional_label_key); absl::Status BuildAndRegisterGlobal(); private: @@ -217,53 +186,232 @@ class OpenTelemetryPluginBuilderImpl { server_selector_; std::vector> plugin_options_; + std::shared_ptr> optional_label_keys_; }; -// Creates a convenience wrapper to help iterate over only those plugin options -// that are active over a given channel/server. -class ActivePluginOptionsView { +class OpenTelemetryPlugin : public grpc_core::StatsPlugin { public: - static ActivePluginOptionsView MakeForClient(absl::string_view target) { - return ActivePluginOptionsView( - [target](const InternalOpenTelemetryPluginOption& plugin_option) { - return plugin_option.IsActiveOnClientChannel(target); - }); - } + OpenTelemetryPlugin( + const absl::flat_hash_set& metrics, + opentelemetry::nostd::shared_ptr + meter_provider, + absl::AnyInvocable + target_selector, + absl::AnyInvocable + target_attribute_filter, + absl::AnyInvocable + generic_method_attribute_filter, + absl::AnyInvocable + server_selector, + std::vector> + plugin_options, + std::shared_ptr> optional_label_keys); - static ActivePluginOptionsView MakeForServer( - const grpc_core::ChannelArgs& args) { - return ActivePluginOptionsView( - [&args](const InternalOpenTelemetryPluginOption& plugin_option) { - return plugin_option.IsActiveOnServer(args); - }); - } + private: + class ClientCallTracer; + class KeyValueIterable; + class NPCMetricsKeyValueIterable; + class ServerCallTracer; + + // Creates a convenience wrapper to help iterate over only those plugin + // options that are active over a given channel/server. + class ActivePluginOptionsView { + public: + static ActivePluginOptionsView MakeForClient( + absl::string_view target, const OpenTelemetryPlugin* otel_plugin) { + return ActivePluginOptionsView( + [target](const InternalOpenTelemetryPluginOption& plugin_option) { + return plugin_option.IsActiveOnClientChannel(target); + }, + otel_plugin); + } + + static ActivePluginOptionsView MakeForServer( + const grpc_core::ChannelArgs& args, + const OpenTelemetryPlugin* otel_plugin) { + return ActivePluginOptionsView( + [&args](const InternalOpenTelemetryPluginOption& plugin_option) { + return plugin_option.IsActiveOnServer(args); + }, + otel_plugin); + } - bool ForEach( - absl::FunctionRef - func) const { - for (size_t i = 0; i < OpenTelemetryPluginState().plugin_options.size(); - ++i) { - const auto& plugin_option = OpenTelemetryPluginState().plugin_options[i]; - if (active_mask_[i] && !func(*plugin_option, i)) { - return false; + bool ForEach(absl::FunctionRef< + bool(const InternalOpenTelemetryPluginOption&, size_t)> + func, + const OpenTelemetryPlugin* otel_plugin) const { + for (size_t i = 0; i < otel_plugin->plugin_options().size(); ++i) { + const auto& plugin_option = otel_plugin->plugin_options()[i]; + if (active_mask_[i] && !func(*plugin_option, i)) { + return false; + } } + return true; } - return true; - } - private: - explicit ActivePluginOptionsView( - absl::FunctionRef func) { - for (size_t i = 0; i < OpenTelemetryPluginState().plugin_options.size(); - ++i) { - const auto& plugin_option = OpenTelemetryPluginState().plugin_options[i]; - if (plugin_option != nullptr && func(*plugin_option)) { - active_mask_.set(i); + private: + explicit ActivePluginOptionsView( + absl::FunctionRef func, + const OpenTelemetryPlugin* otel_plugin) { + for (size_t i = 0; i < otel_plugin->plugin_options().size(); ++i) { + const auto& plugin_option = otel_plugin->plugin_options()[i]; + if (plugin_option != nullptr && func(*plugin_option)) { + active_mask_.set(i); + } } } + + std::bitset<64> active_mask_; + }; + + class ClientScopeConfig : public grpc_core::StatsPlugin::ScopeConfig { + public: + ClientScopeConfig(const OpenTelemetryPlugin* otel_plugin, + const ChannelScope& scope) + : active_plugin_options_view_(ActivePluginOptionsView::MakeForClient( + scope.target(), otel_plugin)), + filtered_target_( + // Use the original target string only if a filter on the + // attribute is not registered or if the filter returns true, + // otherwise use "other". + otel_plugin->target_attribute_filter() == nullptr || + otel_plugin->target_attribute_filter()(scope.target()) + ? scope.target() + : "other") {} + + const ActivePluginOptionsView& active_plugin_options_view() const { + return active_plugin_options_view_; + } + + absl::string_view filtered_target() const { return filtered_target_; } + + private: + ActivePluginOptionsView active_plugin_options_view_; + std::string filtered_target_; + }; + class ServerScopeConfig : public grpc_core::StatsPlugin::ScopeConfig { + public: + ServerScopeConfig(const OpenTelemetryPlugin* otel_plugin, + const grpc_core::ChannelArgs& args) + : active_plugin_options_view_( + ActivePluginOptionsView::MakeForServer(args, otel_plugin)) {} + + const ActivePluginOptionsView& active_plugin_options_view() const { + return active_plugin_options_view_; + } + + private: + ActivePluginOptionsView active_plugin_options_view_; + }; + + struct ClientMetrics { + struct Attempt { + std::unique_ptr> started; + std::unique_ptr> duration; + std::unique_ptr> + sent_total_compressed_message_size; + std::unique_ptr> + rcvd_total_compressed_message_size; + } attempt; + }; + struct ServerMetrics { + struct Call { + std::unique_ptr> started; + std::unique_ptr> duration; + std::unique_ptr> + sent_total_compressed_message_size; + std::unique_ptr> + rcvd_total_compressed_message_size; + } call; + }; + + // StatsPlugin: + std::pair> + IsEnabledForChannel(const ChannelScope& scope) const override; + std::pair> + IsEnabledForServer(const grpc_core::ChannelArgs& args) const override; + void AddCounter( + grpc_core::GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle, + uint64_t value, absl::Span label_values, + absl::Span optional_values) override; + void AddCounter( + grpc_core::GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle, + double value, absl::Span label_values, + absl::Span optional_values) override; + void RecordHistogram( + grpc_core::GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle, + uint64_t value, absl::Span label_values, + absl::Span optional_values) override; + void RecordHistogram( + grpc_core::GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle, + double value, absl::Span label_values, + absl::Span optional_values) override; + void SetGauge( + grpc_core::GlobalInstrumentsRegistry::GlobalInt64GaugeHandle /*handle*/, + int64_t /*value*/, absl::Span /*label_values*/, + absl::Span /*optional_values*/) override {} + void SetGauge( + grpc_core::GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle /*handle*/, + double /*value*/, absl::Span /*label_values*/, + absl::Span /*optional_values*/) override {} + // TODO(yashkt, yijiem): implement async instrument. + void AddCallback(grpc_core::RegisteredMetricCallback* /*callback*/) override { + } + void RemoveCallback( + grpc_core::RegisteredMetricCallback* /*callback*/) override {} + grpc_core::ClientCallTracer* GetClientCallTracer( + const grpc_core::Slice& path, bool registered_method, + std::shared_ptr scope_config) + override; + grpc_core::ServerCallTracer* GetServerCallTracer( + std::shared_ptr scope_config) + override; + + const absl::AnyInvocable& + server_selector() const { + return server_selector_; + } + const absl::AnyInvocable& + target_attribute_filter() const { + return target_attribute_filter_; + } + const absl::AnyInvocable& + generic_method_attribute_filter() const { + return generic_method_attribute_filter_; + } + const std::vector>& + plugin_options() const { + return plugin_options_; } - std::bitset<64> active_mask_; + // Instruments for per-call metrics. + ClientMetrics client_; + ServerMetrics server_; + // Instruments for non-per-call metrics. + struct Disabled {}; + using Instrument = absl::variant< + Disabled, std::unique_ptr>, + std::unique_ptr>, + std::unique_ptr>, + std::unique_ptr>>; + static constexpr int kOptionalLabelsSizeLimit = 64; + using OptionalLabelsBitSet = std::bitset; + struct InstrumentData { + Instrument instrument; + OptionalLabelsBitSet optional_labels_bits; + }; + std::vector instruments_data_; + opentelemetry::nostd::shared_ptr + meter_provider_; + absl::AnyInvocable target_selector_; + absl::AnyInvocable + server_selector_; + absl::AnyInvocable + target_attribute_filter_; + absl::AnyInvocable + generic_method_attribute_filter_; + std::vector> + plugin_options_; }; } // namespace internal diff --git a/src/cpp/ext/otel/otel_server_call_tracer.cc b/src/cpp/ext/otel/otel_server_call_tracer.cc index 9ca45a3db3a..21d09153275 100644 --- a/src/cpp/ext/otel/otel_server_call_tracer.cc +++ b/src/cpp/ext/otel/otel_server_call_tracer.cc @@ -28,7 +28,6 @@ #include "absl/functional/any_invocable.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" -#include "absl/strings/strip.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/optional.h" @@ -50,127 +49,11 @@ namespace grpc { namespace internal { -namespace { - -// OpenTelemetryServerCallTracer implementation - -class OpenTelemetryServerCallTracer : public grpc_core::ServerCallTracer { - public: - explicit OpenTelemetryServerCallTracer(const grpc_core::ChannelArgs& args) - : start_time_(absl::Now()), - active_plugin_options_view_( - ActivePluginOptionsView::MakeForServer(args)), - injected_labels_from_plugin_options_( - OpenTelemetryPluginState().plugin_options.size()) {} - - std::string TraceId() override { - // Not implemented - return ""; - } - - std::string SpanId() override { - // Not implemented - return ""; - } - - bool IsSampled() override { - // Not implemented - return false; - } - - // Please refer to `grpc_transport_stream_op_batch_payload` for details on - // arguments. - void RecordSendInitialMetadata( - grpc_metadata_batch* send_initial_metadata) override { - active_plugin_options_view_.ForEach( - [&](const InternalOpenTelemetryPluginOption& plugin_option, - size_t index) { - auto* labels_injector = plugin_option.labels_injector(); - if (labels_injector != nullptr) { - labels_injector->AddLabels( - send_initial_metadata, - injected_labels_from_plugin_options_[index].get()); - } - return true; - }); - } - - void RecordSendTrailingMetadata( - grpc_metadata_batch* /*send_trailing_metadata*/) override; - - void RecordSendMessage(const grpc_core::SliceBuffer& send_message) override { - RecordAnnotation( - absl::StrFormat("Send message: %ld bytes", send_message.Length())); - } - void RecordSendCompressedMessage( - const grpc_core::SliceBuffer& send_compressed_message) override { - RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes", - send_compressed_message.Length())); - } - - void RecordReceivedInitialMetadata( - grpc_metadata_batch* recv_initial_metadata) override; - - void RecordReceivedMessage( - const grpc_core::SliceBuffer& recv_message) override { - RecordAnnotation( - absl::StrFormat("Received message: %ld bytes", recv_message.Length())); - } - void RecordReceivedDecompressedMessage( - const grpc_core::SliceBuffer& recv_decompressed_message) override { - RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes", - recv_decompressed_message.Length())); - } - - void RecordReceivedTrailingMetadata( - grpc_metadata_batch* /*recv_trailing_metadata*/) override {} - - void RecordCancel(grpc_error_handle /*cancel_error*/) override { - elapsed_time_ = absl::Now() - start_time_; - } - - void RecordEnd(const grpc_call_final_info* final_info) override; - - void RecordAnnotation(absl::string_view /*annotation*/) override { - // Not implemented - } - - void RecordAnnotation(const Annotation& /*annotation*/) override { - // Not implemented - } - std::shared_ptr StartNewTcpTrace() override { - // No TCP trace. - return nullptr; - } - - private: - absl::string_view MethodForStats() const { - absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/"); - if (registered_method_ || - (OpenTelemetryPluginState().generic_method_attribute_filter != - nullptr && - OpenTelemetryPluginState().generic_method_attribute_filter(method))) { - return method; - } - return "other"; - } - - absl::Time start_time_; - absl::Duration elapsed_time_; - grpc_core::Slice path_; - bool registered_method_; - ActivePluginOptionsView active_plugin_options_view_; - // TODO(yashykt): It's wasteful to do this per call. When we re-haul the stats - // infrastructure, this should move to be done per server. - std::vector> - injected_labels_from_plugin_options_; -}; - -void OpenTelemetryServerCallTracer::RecordReceivedInitialMetadata( +void OpenTelemetryPlugin::ServerCallTracer::RecordReceivedInitialMetadata( grpc_metadata_batch* recv_initial_metadata) { path_ = recv_initial_metadata->get_pointer(grpc_core::HttpPathMetadata())->Ref(); - active_plugin_options_view_.ForEach( + scope_config_->active_plugin_options_view().ForEach( [&](const InternalOpenTelemetryPluginOption& plugin_option, size_t index) { auto* labels_injector = plugin_option.labels_injector(); @@ -179,31 +62,48 @@ void OpenTelemetryServerCallTracer::RecordReceivedInitialMetadata( labels_injector->GetLabels(recv_initial_metadata); } return true; - }); + }, + otel_plugin_); registered_method_ = recv_initial_metadata->get(grpc_core::GrpcRegisteredMethod()) .value_or(nullptr) != nullptr; std::array, 1> additional_labels = {{{OpenTelemetryMethodKey(), MethodForStats()}}}; - if (OpenTelemetryPluginState().server.call.started != nullptr) { + if (otel_plugin_->server_.call.started != nullptr) { // We might not have all the injected labels that we want at this point, so // avoid recording a subset of injected labels here. - OpenTelemetryPluginState().server.call.started->Add( + otel_plugin_->server_.call.started->Add( 1, KeyValueIterable(/*injected_labels_from_plugin_options=*/{}, additional_labels, /*active_plugin_options_view=*/nullptr, {}, - /*is_client=*/false)); + /*is_client=*/false, otel_plugin_)); } } -void OpenTelemetryServerCallTracer::RecordSendTrailingMetadata( +void OpenTelemetryPlugin::ServerCallTracer::RecordSendInitialMetadata( + grpc_metadata_batch* send_initial_metadata) { + scope_config_->active_plugin_options_view().ForEach( + [&](const InternalOpenTelemetryPluginOption& plugin_option, + size_t index) { + auto* labels_injector = plugin_option.labels_injector(); + if (labels_injector != nullptr) { + labels_injector->AddLabels( + send_initial_metadata, + injected_labels_from_plugin_options_[index].get()); + } + return true; + }, + otel_plugin_); +} + +void OpenTelemetryPlugin::ServerCallTracer::RecordSendTrailingMetadata( grpc_metadata_batch* /*send_trailing_metadata*/) { // We need to record the time when the trailing metadata was sent to // mark the completeness of the request. elapsed_time_ = absl::Now() - start_time_; } -void OpenTelemetryServerCallTracer::RecordEnd( +void OpenTelemetryPlugin::ServerCallTracer::RecordEnd( const grpc_call_final_info* final_info) { std::array, 2> additional_labels = { @@ -214,47 +114,25 @@ void OpenTelemetryServerCallTracer::RecordEnd( KeyValueIterable labels( injected_labels_from_plugin_options_, additional_labels, /*active_plugin_options_view=*/nullptr, /*optional_labels_span=*/{}, - /*is_client=*/false); - if (OpenTelemetryPluginState().server.call.duration != nullptr) { - OpenTelemetryPluginState().server.call.duration->Record( + /*is_client=*/false, otel_plugin_); + if (otel_plugin_->server_.call.duration != nullptr) { + otel_plugin_->server_.call.duration->Record( absl::ToDoubleSeconds(elapsed_time_), labels, opentelemetry::context::Context{}); } - if (OpenTelemetryPluginState() - .server.call.sent_total_compressed_message_size != nullptr) { - OpenTelemetryPluginState() - .server.call.sent_total_compressed_message_size->Record( - final_info->stats.transport_stream_stats.outgoing.data_bytes, - labels, opentelemetry::context::Context{}); + if (otel_plugin_->server_.call.sent_total_compressed_message_size != + nullptr) { + otel_plugin_->server_.call.sent_total_compressed_message_size->Record( + final_info->stats.transport_stream_stats.outgoing.data_bytes, labels, + opentelemetry::context::Context{}); } - if (OpenTelemetryPluginState() - .server.call.rcvd_total_compressed_message_size != nullptr) { - OpenTelemetryPluginState() - .server.call.rcvd_total_compressed_message_size->Record( - final_info->stats.transport_stream_stats.incoming.data_bytes, - labels, opentelemetry::context::Context{}); + if (otel_plugin_->server_.call.rcvd_total_compressed_message_size != + nullptr) { + otel_plugin_->server_.call.rcvd_total_compressed_message_size->Record( + final_info->stats.transport_stream_stats.incoming.data_bytes, labels, + opentelemetry::context::Context{}); } } -} // namespace - -// -// OpenTelemetryServerCallTracerFactory -// - -grpc_core::ServerCallTracer* -OpenTelemetryServerCallTracerFactory::CreateNewServerCallTracer( - grpc_core::Arena* arena, const grpc_core::ChannelArgs& args) { - return arena->ManagedNew(args); -} - -bool OpenTelemetryServerCallTracerFactory::IsServerTraced( - const grpc_core::ChannelArgs& args) { - // Return true only if there is no server selector registered or if the server - // selector returns true. - return OpenTelemetryPluginState().server_selector == nullptr || - OpenTelemetryPluginState().server_selector(args); -} - } // namespace internal } // namespace grpc diff --git a/src/cpp/ext/otel/otel_server_call_tracer.h b/src/cpp/ext/otel/otel_server_call_tracer.h index c8cea43d4d0..2c73efdef0e 100644 --- a/src/cpp/ext/otel/otel_server_call_tracer.h +++ b/src/cpp/ext/otel/otel_server_call_tracer.h @@ -21,21 +21,116 @@ #include +#include "absl/strings/strip.h" + #include "src/core/lib/channel/call_tracer.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/resource_quota/arena.h" +#include "src/cpp/ext/otel/otel_plugin.h" namespace grpc { namespace internal { -class OpenTelemetryServerCallTracerFactory - : public grpc_core::ServerCallTracerFactory { +// OpenTelemetryPlugin::ServerCallTracer implementation + +class OpenTelemetryPlugin::ServerCallTracer + : public grpc_core::ServerCallTracer { public: - grpc_core::ServerCallTracer* CreateNewServerCallTracer( - grpc_core::Arena* arena, - const grpc_core::ChannelArgs& channel_args) override; + ServerCallTracer( + OpenTelemetryPlugin* otel_plugin, + std::shared_ptr scope_config) + : start_time_(absl::Now()), + injected_labels_from_plugin_options_( + otel_plugin->plugin_options().size()), + otel_plugin_(otel_plugin), + scope_config_(std::move(scope_config)) {} + + std::string TraceId() override { + // Not implemented + return ""; + } + + std::string SpanId() override { + // Not implemented + return ""; + } + + bool IsSampled() override { + // Not implemented + return false; + } + + // Please refer to `grpc_transport_stream_op_batch_payload` for details on + // arguments. + void RecordSendInitialMetadata( + grpc_metadata_batch* send_initial_metadata) override; + + void RecordSendTrailingMetadata( + grpc_metadata_batch* /*send_trailing_metadata*/) override; + + void RecordSendMessage(const grpc_core::SliceBuffer& send_message) override { + RecordAnnotation( + absl::StrFormat("Send message: %ld bytes", send_message.Length())); + } + void RecordSendCompressedMessage( + const grpc_core::SliceBuffer& send_compressed_message) override { + RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes", + send_compressed_message.Length())); + } + + void RecordReceivedInitialMetadata( + grpc_metadata_batch* recv_initial_metadata) override; + + void RecordReceivedMessage( + const grpc_core::SliceBuffer& recv_message) override { + RecordAnnotation( + absl::StrFormat("Received message: %ld bytes", recv_message.Length())); + } + void RecordReceivedDecompressedMessage( + const grpc_core::SliceBuffer& recv_decompressed_message) override { + RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes", + recv_decompressed_message.Length())); + } + + void RecordReceivedTrailingMetadata( + grpc_metadata_batch* /*recv_trailing_metadata*/) override {} + + void RecordCancel(grpc_error_handle /*cancel_error*/) override { + elapsed_time_ = absl::Now() - start_time_; + } + + void RecordEnd(const grpc_call_final_info* final_info) override; + + void RecordAnnotation(absl::string_view /*annotation*/) override { + // Not implemented + } + + void RecordAnnotation(const Annotation& /*annotation*/) override { + // Not implemented + } + std::shared_ptr StartNewTcpTrace() override { + // No TCP trace. + return nullptr; + } + + private: + absl::string_view MethodForStats() const { + absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/"); + if (registered_method_ || + (otel_plugin_->generic_method_attribute_filter() != nullptr && + otel_plugin_->generic_method_attribute_filter()(method))) { + return method; + } + return "other"; + } - bool IsServerTraced(const grpc_core::ChannelArgs& args) override; + absl::Time start_time_; + absl::Duration elapsed_time_; + grpc_core::Slice path_; + bool registered_method_; + std::vector> + injected_labels_from_plugin_options_; + OpenTelemetryPlugin* otel_plugin_; + std::shared_ptr scope_config_; }; } // namespace internal diff --git a/test/core/client_channel/lb_policy/pick_first_test.cc b/test/core/client_channel/lb_policy/pick_first_test.cc index 609f6f31a2f..4b098d07cec 100644 --- a/test/core/client_channel/lb_policy/pick_first_test.cc +++ b/test/core/client_channel/lb_policy/pick_first_test.cc @@ -1168,7 +1168,7 @@ TEST_F(PickFirstTest, MetricValues) { const absl::string_view kLabelValues[] = {target_}; auto stats_plugin = std::make_shared( nullptr, /*use_disabled_by_default_metrics=*/true); - stats_plugin_group_.push_back(stats_plugin); + stats_plugin_group_.AddStatsPlugin(stats_plugin, nullptr); // Send an update containing two addresses. constexpr std::array kAddresses = { "ipv4:127.0.0.1:443", "ipv4:127.0.0.1:444"}; diff --git a/test/core/client_channel/lb_policy/weighted_round_robin_test.cc b/test/core/client_channel/lb_policy/weighted_round_robin_test.cc index edc89309eca..9e8cd2c66d1 100644 --- a/test/core/client_channel/lb_policy/weighted_round_robin_test.cc +++ b/test/core/client_channel/lb_policy/weighted_round_robin_test.cc @@ -1084,7 +1084,7 @@ TEST_F(WeightedRoundRobinTest, MetricValues) { const absl::string_view kOptionalLabelValues[] = {kLocalityName}; auto stats_plugin = std::make_shared( nullptr, /*use_disabled_by_default_metrics=*/true); - stats_plugin_group_.push_back(stats_plugin); + stats_plugin_group_.AddStatsPlugin(stats_plugin, nullptr); // Send address list to LB policy. const std::array kAddresses = { "ipv4:127.0.0.1:441", "ipv4:127.0.0.1:442", "ipv4:127.0.0.1:443"}; diff --git a/test/core/end2end/grpc_core_end2end_test.bzl b/test/core/end2end/grpc_core_end2end_test.bzl index 9b1224db84a..9b0b302ac9f 100644 --- a/test/core/end2end/grpc_core_end2end_test.bzl +++ b/test/core/end2end/grpc_core_end2end_test.bzl @@ -90,6 +90,7 @@ def grpc_core_end2end_test(name, shard_count = 10, tags = []): "//src/core:stats_data", "//src/core:status_helper", "//src/core:time", + "//test/core/util:fake_stats_plugin", "//test/core/util:grpc_test_util", "//test/core/util:test_lb_policies", ], @@ -170,6 +171,7 @@ def grpc_core_end2end_test(name, shard_count = 10, tags = []): "//src/core:time", "//test/core/event_engine/fuzzing_event_engine", "//test/core/event_engine/fuzzing_event_engine:fuzzing_event_engine_proto", + "//test/core/util:fake_stats_plugin", "//test/core/util:fuzz_config_vars", "//test/core/util:fuzz_config_vars_proto", "//test/core/util:grpc_test_util", diff --git a/test/core/end2end/tests/http2_stats.cc b/test/core/end2end/tests/http2_stats.cc index aac381e2644..ffb2efdd7b8 100644 --- a/test/core/end2end/tests/http2_stats.cc +++ b/test/core/end2end/tests/http2_stats.cc @@ -33,6 +33,7 @@ #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/context.h" +#include "src/core/lib/channel/metrics.h" #include "src/core/lib/channel/promise_based_filter.h" #include "src/core/lib/channel/tcp_tracer.h" #include "src/core/lib/config/core_configuration.h" @@ -50,6 +51,7 @@ #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" #include "test/core/end2end/end2end_tests.h" +#include "test/core/util/fake_stats_plugin.h" namespace grpc_core { namespace { @@ -130,33 +132,6 @@ class FakeCallTracer : public ClientCallTracer { grpc_transport_stream_stats FakeCallTracer::FakeCallAttemptTracer::transport_stream_stats_; -class FakeClientFilter : public ChannelFilter { - public: - static const grpc_channel_filter kFilter; - - static absl::StatusOr Create( - const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/) { - return FakeClientFilter(); - } - - ArenaPromise MakeCallPromise( - CallArgs call_args, NextPromiseFactory next_promise_factory) override { - auto* call_context = GetContext(); - auto* tracer = GetContext()->ManagedNew(); - GPR_DEBUG_ASSERT( - call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value == - nullptr); - call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value = tracer; - call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].destroy = - nullptr; - return next_promise_factory(std::move(call_args)); - } -}; - -const grpc_channel_filter FakeClientFilter::kFilter = - MakePromiseBasedFilter( - "fake_client"); - class FakeServerCallTracer : public ServerCallTracer { public: ~FakeServerCallTracer() override {} @@ -203,11 +178,18 @@ class FakeServerCallTracer : public ServerCallTracer { grpc_transport_stream_stats FakeServerCallTracer::transport_stream_stats_; -class FakeServerCallTracerFactory : public ServerCallTracerFactory { +// TODO(yijiem): figure out how to reuse FakeStatsPlugin instead of +// inheriting and overriding it here. +class NewFakeStatsPlugin : public FakeStatsPlugin { public: - ServerCallTracer* CreateNewServerCallTracer( - Arena* arena, const ChannelArgs& /*args*/) override { - return arena->ManagedNew(); + ClientCallTracer* GetClientCallTracer( + const Slice& /*path*/, bool /*registered_method*/, + std::shared_ptr /*scope_config*/) override { + return GetContext()->ManagedNew(); + } + ServerCallTracer* GetServerCallTracer( + std::shared_ptr /*scope_config*/) override { + return GetContext()->ManagedNew(); } }; @@ -219,12 +201,8 @@ CORE_END2END_TEST(Http2FullstackSingleHopTest, StreamStats) { g_mu = new Mutex(); g_client_call_ended_notify = new Notification(); g_server_call_ended_notify = new Notification(); - CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { - builder->channel_init()->RegisterFilter( - GRPC_CLIENT_CHANNEL); - }); - ServerCallTracerFactory::RegisterGlobal(new FakeServerCallTracerFactory); - + GlobalStatsPluginRegistry::RegisterStatsPlugin( + std::make_shared()); auto send_from_client = RandomSlice(10); auto send_from_server = RandomSlice(20); CoreEnd2endTest::IncomingStatusOnClient server_status; diff --git a/test/core/transport/chaotic_good/client_transport_error_test.cc b/test/core/transport/chaotic_good/client_transport_error_test.cc index f4bb0dd732e..ac1555fb473 100644 --- a/test/core/transport/chaotic_good/client_transport_error_test.cc +++ b/test/core/transport/chaotic_good/client_transport_error_test.cc @@ -37,6 +37,7 @@ #include #include "src/core/ext/transport/chaotic_good/client_transport.h" +#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/timer_manager.h" #include "src/core/lib/promise/activity.h" diff --git a/test/core/transport/chaotic_good/client_transport_test.cc b/test/core/transport/chaotic_good/client_transport_test.cc index c64dba13f26..358197031a3 100644 --- a/test/core/transport/chaotic_good/client_transport_test.cc +++ b/test/core/transport/chaotic_good/client_transport_test.cc @@ -36,6 +36,7 @@ #include #include +#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/promise/if.h" #include "src/core/lib/promise/loop.h" #include "src/core/lib/promise/seq.h" diff --git a/test/core/util/fake_stats_plugin.cc b/test/core/util/fake_stats_plugin.cc index d00df284599..a1b43475523 100644 --- a/test/core/util/fake_stats_plugin.cc +++ b/test/core/util/fake_stats_plugin.cc @@ -122,17 +122,17 @@ namespace { template absl::optional FindInstrument( - const absl::flat_hash_map< - absl::string_view, - GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>& instruments, + const std::vector& + instruments, absl::string_view name, GlobalInstrumentsRegistry::ValueType value_type, GlobalInstrumentsRegistry::InstrumentType instrument_type) { - auto it = instruments.find(name); - if (it != instruments.end() && it->second.value_type == value_type && - it->second.instrument_type == instrument_type) { - HandleType handle; - handle.index = it->second.index; - return handle; + for (const auto& descriptor : instruments) { + if (descriptor.name == name && descriptor.value_type == value_type && + descriptor.instrument_type == instrument_type) { + HandleType handle; + handle.index = descriptor.index; + return handle; + } } return absl::nullopt; } @@ -216,9 +216,11 @@ GlobalInstrumentsRegistryTestPeer::FindCallbackDoubleGaugeHandleByName( GlobalInstrumentsRegistry::GlobalInstrumentDescriptor* GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName( absl::string_view name) { - auto& instruments = GlobalInstrumentsRegistry::GetInstrumentList(); - auto it = instruments.find(name); - if (it != instruments.end()) return &it->second; + for (auto& descriptor : GlobalInstrumentsRegistry::GetInstrumentList()) { + if (descriptor.name == name) { + return &descriptor; + } + } return nullptr; } diff --git a/test/core/util/fake_stats_plugin.h b/test/core/util/fake_stats_plugin.h index e6645f1df72..a2fa827516e 100644 --- a/test/core/util/fake_stats_plugin.h +++ b/test/core/util/fake_stats_plugin.h @@ -204,6 +204,8 @@ std::string MakeLabelString( class FakeStatsPlugin : public StatsPlugin { public: + class ScopeConfig : public StatsPlugin::ScopeConfig {}; + explicit FakeStatsPlugin( absl::AnyInvocable channel_filter = nullptr, @@ -266,13 +268,16 @@ class FakeStatsPlugin : public StatsPlugin { }); } - bool IsEnabledForChannel(const ChannelScope& scope) const override { - if (channel_filter_ == nullptr) return true; - return channel_filter_(scope); + std::pair> + IsEnabledForChannel(const ChannelScope& scope) const override { + if (channel_filter_ == nullptr || channel_filter_(scope)) { + return {true, nullptr}; + } + return {false, nullptr}; } - - bool IsEnabledForServer(const ChannelArgs& /*args*/) const override { - return false; + std::pair> IsEnabledForServer( + const ChannelArgs& /*args*/) const override { + return {true, nullptr}; } void AddCounter( @@ -382,6 +387,16 @@ class FakeStatsPlugin : public StatsPlugin { callbacks_.erase(callback); } + ClientCallTracer* GetClientCallTracer( + const Slice& /*path*/, bool /*registered_method*/, + std::shared_ptr /*scope_config*/) override { + return nullptr; + } + ServerCallTracer* GetServerCallTracer( + std::shared_ptr /*scope_config*/) override { + return nullptr; + } + absl::optional GetCounterValue( GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle, absl::Span label_values, diff --git a/test/cpp/ext/otel/BUILD b/test/cpp/ext/otel/BUILD index 8fa212f585c..51f337834bc 100644 --- a/test/cpp/ext/otel/BUILD +++ b/test/cpp/ext/otel/BUILD @@ -41,6 +41,7 @@ grpc_cc_library( deps = [ "//:grpc++", "//src/cpp/ext/otel:otel_plugin", + "//test/core/util:fake_stats_plugin", "//test/core/util:grpc_test_util", "//test/cpp/end2end:test_service_impl", ], diff --git a/test/cpp/ext/otel/otel_plugin_test.cc b/test/cpp/ext/otel/otel_plugin_test.cc index 3cb5cb318ef..c4e467b9778 100644 --- a/test/cpp/ext/otel/otel_plugin_test.cc +++ b/test/cpp/ext/otel/otel_plugin_test.cc @@ -18,10 +18,15 @@ #include "src/cpp/ext/otel/otel_plugin.h" +#include + #include "absl/functional/any_invocable.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "opentelemetry/metrics/provider.h" +#include "opentelemetry/nostd/variant.h" +#include "opentelemetry/sdk/common/attribute_utils.h" +#include "opentelemetry/sdk/metrics/data/point_data.h" #include "opentelemetry/sdk/metrics/meter_provider.h" #include "opentelemetry/sdk/metrics/metric_reader.h" @@ -38,6 +43,73 @@ namespace grpc { namespace testing { namespace { +#define GRPC_ARG_SERVER_SELECTOR_KEY "grpc.testing.server_selector_key" +#define GRPC_ARG_SERVER_SELECTOR_VALUE "grpc.testing.server_selector_value" + +template +void PopulateLabelMap( + T label_keys, T label_values, + std::unordered_map* + label_maps) { + for (size_t i = 0; i < label_keys.size(); ++i) { + (*label_maps)[std::string(label_keys[i])] = std::string(label_values[i]); + } +} + +MATCHER_P4(AttributesEq, label_keys, label_values, optional_label_keys, + optional_label_values, "") { + std::unordered_map + label_map; + PopulateLabelMap(label_keys, label_values, &label_map); + PopulateLabelMap(optional_label_keys, optional_label_values, &label_map); + return ::testing::ExplainMatchResult( + ::testing::UnorderedElementsAreArray(label_map), + arg.attributes.GetAttributes(), result_listener); +} + +template +auto IntOrDoubleEq(T result) { + return ::testing::Eq(result); +} +template <> +auto IntOrDoubleEq(double result) { + return ::testing::DoubleEq(result); +} + +MATCHER_P(CounterResultEq, result, "") { + return ::testing::ExplainMatchResult( + ::testing::VariantWith( + ::testing::Field( + &opentelemetry::sdk::metrics::SumPointData::value_, + ::testing::VariantWith>( + IntOrDoubleEq(result)))), + arg.point_data, result_listener); +} + +MATCHER_P4(HistogramResultEq, sum, min, max, count, "") { + return ::testing::ExplainMatchResult( + ::testing::VariantWith( + ::testing::AllOf( + ::testing::Field( + &opentelemetry::sdk::metrics::HistogramPointData::sum_, + ::testing::VariantWith>( + IntOrDoubleEq(sum))), + ::testing::Field( + &opentelemetry::sdk::metrics::HistogramPointData::min_, + ::testing::VariantWith>( + IntOrDoubleEq(min))), + ::testing::Field( + &opentelemetry::sdk::metrics::HistogramPointData::max_, + ::testing::VariantWith>( + IntOrDoubleEq(max))), + ::testing::Field( + &opentelemetry::sdk::metrics::HistogramPointData::count_, + ::testing::Eq(count)))), + arg.point_data, result_listener); +} + TEST(OpenTelemetryPluginBuildTest, ApiDependency) { opentelemetry::metrics::Provider::GetMeterProvider(); } @@ -933,6 +1005,354 @@ TEST_F(OpenTelemetryPluginOptionEnd2EndTest, EXPECT_EQ(absl::get(server_attributes.at("key5")), "value5"); } +using OpenTelemetryPluginNPCMetricsTest = OpenTelemetryPluginEnd2EndTest; + +TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Counter) { + constexpr absl::string_view kMetricName = "uint64_counter"; + constexpr int kCounterValues[] = {1, 2, 3}; + constexpr int64_t kCounterResult = 6; + constexpr std::array kLabelKeys = {"label_key_1", + "label_key_2"}; + constexpr std::array kOptionalLabelKeys = { + "optional_label_key_1", "optional_label_key_2"}; + constexpr std::array kLabelValues = {"label_value_1", + "label_value_2"}; + constexpr std::array kOptionalLabelValues = { + "optional_label_value_1", "optional_label_value_2"}; + auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterUInt64Counter( + kMetricName, "A simple uint64 counter.", "unit", kLabelKeys, + kOptionalLabelKeys, /*enable_by_default=*/true); + Init(std::move(Options() + .set_metric_names({kMetricName}) + .set_target_selector([](absl::string_view target) { + return absl::StartsWith(target, "dns:///"); + }) + .add_optional_label(kOptionalLabelKeys[0]) + .add_optional_label(kOptionalLabelKeys[1]))); + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel( + grpc_core::StatsPlugin::ChannelScope("dns:///localhost:8080", "")); + for (auto v : kCounterValues) { + stats_plugins.AddCounter(handle, v, kLabelValues, kOptionalLabelValues); + } + auto data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }); + EXPECT_THAT(data, ::testing::ElementsAre(::testing::Pair( + kMetricName, ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, + kOptionalLabelKeys, + kOptionalLabelValues), + CounterResultEq(kCounterResult)))))); +} + +TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleCounter) { + constexpr absl::string_view kMetricName = "double_counter"; + constexpr double kCounterValues[] = {1.23, 2.34, 3.45}; + constexpr double kCounterResult = 7.02; + constexpr std::array kLabelKeys = {"label_key_1", + "label_key_2"}; + constexpr std::array kOptionalLabelKeys = { + "optional_label_key_1", "optional_label_key_2"}; + constexpr std::array kLabelValues = {"label_value_1", + "label_value_2"}; + constexpr std::array kOptionalLabelValues = { + "optional_label_value_1", "optional_label_value_2"}; + auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleCounter( + kMetricName, "A simple double counter.", "unit", kLabelKeys, + kOptionalLabelKeys, /*enable_by_default=*/false); + Init(std::move(Options() + .set_metric_names({kMetricName}) + .set_target_selector([](absl::string_view target) { + return absl::StartsWith(target, "dns:///"); + }) + .add_optional_label(kOptionalLabelKeys[0]) + .add_optional_label(kOptionalLabelKeys[1]))); + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel( + grpc_core::StatsPlugin::ChannelScope("dns:///localhost:8080", "")); + for (auto v : kCounterValues) { + stats_plugins.AddCounter(handle, v, kLabelValues, kOptionalLabelValues); + } + auto data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }); + EXPECT_THAT(data, ::testing::ElementsAre(::testing::Pair( + kMetricName, ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, + kOptionalLabelKeys, + kOptionalLabelValues), + CounterResultEq(kCounterResult)))))); +} + +TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Histogram) { + constexpr absl::string_view kMetricName = "uint64_histogram"; + constexpr int kHistogramValues[] = {1, 1, 2, 3, 4, 4, 5, 6}; + constexpr int64_t kSum = 26; + constexpr int64_t kMin = 1; + constexpr int64_t kMax = 6; + constexpr int64_t kCount = 8; + constexpr std::array kLabelKeys = {"label_key_1", + "label_key_2"}; + constexpr std::array kOptionalLabelKeys = { + "optional_label_key_1", "optional_label_key_2"}; + constexpr std::array kLabelValues = {"label_value_1", + "label_value_2"}; + constexpr std::array kOptionalLabelValues = { + "optional_label_value_1", "optional_label_value_2"}; + auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterUInt64Histogram( + kMetricName, "A simple uint64 histogram.", "unit", kLabelKeys, + kOptionalLabelKeys, /*enable_by_default=*/true); + Init(std::move( + Options() + .set_metric_names({kMetricName}) + .set_server_selector([](const grpc_core::ChannelArgs& args) { + return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) == + GRPC_ARG_SERVER_SELECTOR_VALUE; + }) + .add_optional_label(kOptionalLabelKeys[0]) + .add_optional_label(kOptionalLabelKeys[1]))); + grpc_core::ChannelArgs args; + args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE); + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args); + for (auto v : kHistogramValues) { + stats_plugins.RecordHistogram(handle, v, kLabelValues, + kOptionalLabelValues); + } + auto data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }); + EXPECT_THAT(data, + ::testing::ElementsAre(::testing::Pair( + kMetricName, + ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, + kOptionalLabelValues), + HistogramResultEq(kSum, kMin, kMax, kCount)))))); +} + +TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleHistogram) { + constexpr absl::string_view kMetricName = "double_histogram"; + constexpr double kHistogramValues[] = {1.1, 1.2, 2.2, 3.3, + 4.4, 4.5, 5.5, 6.6}; + constexpr double kSum = 28.8; + constexpr double kMin = 1.1; + constexpr double kMax = 6.6; + constexpr double kCount = 8; + constexpr std::array kLabelKeys = {"label_key_1", + "label_key_2"}; + constexpr std::array kOptionalLabelKeys = { + "optional_label_key_1", "optional_label_key_2"}; + constexpr std::array kLabelValues = {"label_value_1", + "label_value_2"}; + constexpr std::array kOptionalLabelValues = { + "optional_label_value_1", "optional_label_value_2"}; + auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram( + kMetricName, "A simple double histogram.", "unit", kLabelKeys, + kOptionalLabelKeys, /*enable_by_default=*/true); + Init(std::move( + Options() + .set_metric_names({kMetricName}) + .set_server_selector([](const grpc_core::ChannelArgs& args) { + return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) == + GRPC_ARG_SERVER_SELECTOR_VALUE; + }) + .add_optional_label(kOptionalLabelKeys[0]) + .add_optional_label(kOptionalLabelKeys[1]))); + grpc_core::ChannelArgs args; + args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE); + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args); + for (auto v : kHistogramValues) { + stats_plugins.RecordHistogram(handle, v, kLabelValues, + kOptionalLabelValues); + } + auto data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }); + EXPECT_THAT(data, + ::testing::ElementsAre(::testing::Pair( + kMetricName, + ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, + kOptionalLabelValues), + HistogramResultEq(kSum, kMin, kMax, kCount)))))); +} + +TEST_F(OpenTelemetryPluginNPCMetricsTest, + RegisterMultipleOpenTelemetryPlugins) { + constexpr absl::string_view kMetricName = "yet_another_double_histogram"; + constexpr std::array kLabelKeys = {"label_key_1", + "label_key_2"}; + constexpr std::array kOptionalLabelKeys = { + "optional_label_key_1", "optional_label_key_2"}; + constexpr std::array kLabelValues = {"label_value_1", + "label_value_2"}; + constexpr std::array kOptionalLabelValues = { + "optional_label_value_1", "optional_label_value_2"}; + auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram( + kMetricName, "A simple double histogram.", "unit", kLabelKeys, + kOptionalLabelKeys, /*enable_by_default=*/true); + // Build and register a separate OpenTelemetryPlugin and verify its histogram + // recording. + grpc::internal::OpenTelemetryPluginBuilderImpl ot_builder; + auto reader = BuildAndRegisterOpenTelemetryPlugin(std::move( + Options() + .set_metric_names({kMetricName}) + .set_server_selector([](const grpc_core::ChannelArgs& args) { + return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) == + GRPC_ARG_SERVER_SELECTOR_VALUE; + }) + .add_optional_label(kOptionalLabelKeys[0]) + .add_optional_label(kOptionalLabelKeys[1]))); + EXPECT_EQ(ot_builder.BuildAndRegisterGlobal(), absl::OkStatus()); + grpc_core::ChannelArgs args; + args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE); + { + constexpr double kHistogramValues[] = {1.23, 2.34, 3.45, 4.56}; + constexpr double kSum = 11.58; + constexpr double kMin = 1.23; + constexpr double kMax = 4.56; + constexpr int kCount = 4; + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args); + for (auto v : kHistogramValues) { + stats_plugins.RecordHistogram(handle, v, kLabelValues, + kOptionalLabelValues); + } + auto data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }, + reader.get()); + EXPECT_THAT( + data, ::testing::ElementsAre(::testing::Pair( + kMetricName, + ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, + kOptionalLabelValues), + HistogramResultEq(kSum, kMin, kMax, kCount)))))); + } + // Now build and register another OpenTelemetryPlugin using the test fixture + // and record histogram. + constexpr double kHistogramValues[] = {1.1, 1.2, 2.2, 3.3, + 4.4, 4.5, 5.5, 6.6}; + constexpr double kSum = 28.8; + constexpr double kMin = 1.1; + constexpr double kMax = 6.6; + constexpr int kCount = 8; + Init(std::move( + Options() + .set_metric_names({kMetricName}) + .set_server_selector([](const grpc_core::ChannelArgs& args) { + return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) == + GRPC_ARG_SERVER_SELECTOR_VALUE; + }) + .add_optional_label(kOptionalLabelKeys[0]) + .add_optional_label(kOptionalLabelKeys[1]))); + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args); + for (auto v : kHistogramValues) { + stats_plugins.RecordHistogram(handle, v, kLabelValues, + kOptionalLabelValues); + } + auto data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }); + EXPECT_THAT(data, + ::testing::ElementsAre(::testing::Pair( + kMetricName, + ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, + kOptionalLabelValues), + HistogramResultEq(kSum, kMin, kMax, kCount)))))); + // Verify that the first plugin gets the data as well. + data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }, + reader.get()); + EXPECT_THAT(data, + ::testing::ElementsAre(::testing::Pair( + kMetricName, + ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, + kOptionalLabelValues), + HistogramResultEq(kSum, kMin, kMax, kCount)))))); +} + +TEST_F(OpenTelemetryPluginNPCMetricsTest, + DisabledOptionalLabelKeysShouldNotBeRecorded) { + constexpr absl::string_view kMetricName = + "yet_another_yet_another_double_histogram"; + constexpr double kHistogramValues[] = {1.1, 1.2, 2.2, 3.3, + 4.4, 4.5, 5.5, 6.6}; + constexpr double kSum = 28.8; + constexpr double kMin = 1.1; + constexpr double kMax = 6.6; + constexpr double kCount = 8; + constexpr std::array kLabelKeys = {"label_key_1", + "label_key_2"}; + constexpr std::array kOptionalLabelKeys = { + "optional_label_key_1", "optional_label_key_2", "optional_label_key_3", + "optional_label_key_4"}; + constexpr std::array kActualOptionalLabelKeys = { + "optional_label_key_1", "optional_label_key_2"}; + constexpr std::array kLabelValues = {"label_value_1", + "label_value_2"}; + constexpr std::array kOptionalLabelValues = { + "optional_label_value_1", "optional_label_value_2", + "optional_label_value_3", "optional_label_value_4"}; + constexpr std::array kActualOptionalLabelValues = { + "optional_label_value_1", "optional_label_value_2"}; + auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram( + kMetricName, "A simple double histogram.", "unit", kLabelKeys, + kOptionalLabelKeys, /*enable_by_default=*/true); + Init(std::move( + Options() + .set_metric_names({kMetricName}) + .set_server_selector([](const grpc_core::ChannelArgs& args) { + return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) == + GRPC_ARG_SERVER_SELECTOR_VALUE; + }) + .add_optional_label(kOptionalLabelKeys[0]) + .add_optional_label(kOptionalLabelKeys[1]))); + grpc_core::ChannelArgs args; + args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE); + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args); + for (auto v : kHistogramValues) { + stats_plugins.RecordHistogram(handle, v, kLabelValues, + kOptionalLabelValues); + } + auto data = ReadCurrentMetricsData( + [&](const absl::flat_hash_map< + std::string, + std::vector>& + data) { return !data.contains(kMetricName); }); + EXPECT_THAT( + data, + ::testing::ElementsAre(::testing::Pair( + kMetricName, + ::testing::ElementsAre(::testing::AllOf( + AttributesEq(kLabelKeys, kLabelValues, kActualOptionalLabelKeys, + kActualOptionalLabelValues), + HistogramResultEq(kSum, kMin, kMax, kCount)))))); +} + } // namespace } // namespace testing } // namespace grpc diff --git a/test/cpp/ext/otel/otel_test_library.cc b/test/cpp/ext/otel/otel_test_library.cc index ee474a9e330..bf9de832fba 100644 --- a/test/cpp/ext/otel/otel_test_library.cc +++ b/test/cpp/ext/otel/otel_test_library.cc @@ -32,6 +32,7 @@ #include "src/core/lib/channel/promise_based_filter.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gprpp/notification.h" +#include "test/core/util/fake_stats_plugin.h" #include "test/core/util/test_config.h" #include "test/cpp/end2end/test_service_impl.h" #include "test/cpp/util/byte_buffer_proto_helper.h" @@ -83,38 +84,7 @@ const grpc_channel_filter AddServiceLabelsFilter::kFilter = "add_service_labels_filter"); void OpenTelemetryPluginEnd2EndTest::Init(Options config) { - // We are resetting the MeterProvider and OpenTelemetry plugin at the start - // of each test to avoid test results from one test carrying over to another - // test. (Some measurements can get arbitrarily delayed.) - auto meter_provider = - std::make_shared( - std::make_unique(), - *config.resource); - reader_.reset(new grpc::testing::MockMetricReader); - meter_provider->AddMetricReader(reader_); grpc_core::CoreConfiguration::Reset(); - grpc::internal::OpenTelemetryPluginBuilderImpl ot_builder; - ot_builder.DisableAllMetrics(); - for (const auto& metric_name : config.metric_names) { - ot_builder.EnableMetric(metric_name); - } - if (config.use_meter_provider) { - auto meter_provider = - std::make_shared(); - reader_.reset(new grpc::testing::MockMetricReader); - meter_provider->AddMetricReader(reader_); - ot_builder.SetMeterProvider(std::move(meter_provider)); - } - ot_builder.SetTargetSelector(std::move(config.target_selector)); - ot_builder.SetServerSelector(std::move(config.server_selector)); - ot_builder.SetTargetAttributeFilter( - std::move(config.target_attribute_filter)); - ot_builder.SetGenericMethodAttributeFilter( - std::move(config.generic_method_attribute_filter)); - for (auto& option : config.plugin_options) { - ot_builder.AddPluginOption(std::move(option)); - } - ASSERT_EQ(ot_builder.BuildAndRegisterGlobal(), absl::OkStatus()); ChannelArguments channel_args; if (!config.labels_to_inject.empty()) { labels_to_inject_ = config.labels_to_inject; @@ -125,6 +95,7 @@ void OpenTelemetryPluginEnd2EndTest::Init(Options config) { }); channel_args.SetPointer(GRPC_ARG_LABELS_TO_INJECT, &labels_to_inject_); } + reader_ = BuildAndRegisterOpenTelemetryPlugin(std::move(config)); grpc_init(); grpc::ServerBuilder builder; int port; @@ -148,6 +119,8 @@ void OpenTelemetryPluginEnd2EndTest::TearDown() { server_->Shutdown(); grpc_shutdown_blocking(); grpc_core::ServerCallTracerFactory::TestOnlyReset(); + grpc_core::GlobalStatsPluginRegistryTestPeer:: + ResetGlobalStatsPluginRegistry(); } void OpenTelemetryPluginEnd2EndTest::ResetStub( @@ -183,14 +156,18 @@ OpenTelemetryPluginEnd2EndTest::ReadCurrentMetricsData( bool(const absl::flat_hash_map< std::string, std::vector>&)> - continue_predicate) { + continue_predicate, + opentelemetry::sdk::metrics::MetricReader* reader) { + if (reader == nullptr) { + reader = reader_.get(); + } absl::flat_hash_map< std::string, std::vector> data; auto deadline = absl::Now() + absl::Seconds(5); do { - reader_->Collect([&](opentelemetry::sdk::metrics::ResourceMetrics& rm) { + reader->Collect([&](opentelemetry::sdk::metrics::ResourceMetrics& rm) { for (const opentelemetry::sdk::metrics::ScopeMetrics& smd : rm.scope_metric_data_) { for (const opentelemetry::sdk::metrics::MetricData& md : @@ -207,5 +184,46 @@ OpenTelemetryPluginEnd2EndTest::ReadCurrentMetricsData( return data; } +std::shared_ptr +OpenTelemetryPluginEnd2EndTest::BuildAndRegisterOpenTelemetryPlugin( + OpenTelemetryPluginEnd2EndTest::Options options) { + grpc::internal::OpenTelemetryPluginBuilderImpl ot_builder; + // We are resetting the MeterProvider and OpenTelemetry plugin at the start + // of each test to avoid test results from one test carrying over to another + // test. (Some measurements can get arbitrarily delayed.) + auto meter_provider = + std::make_shared( + std::make_unique(), + *options.resource); + std::shared_ptr reader = + std::make_shared(); + meter_provider->AddMetricReader(reader); + ot_builder.DisableAllMetrics(); + for (const auto& metric_name : options.metric_names) { + ot_builder.EnableMetric(metric_name); + } + if (options.use_meter_provider) { + auto meter_provider = + std::make_shared(); + reader.reset(new grpc::testing::MockMetricReader); + meter_provider->AddMetricReader(reader); + ot_builder.SetMeterProvider(std::move(meter_provider)); + } + ot_builder.SetTargetSelector(std::move(options.target_selector)); + ot_builder.SetServerSelector(std::move(options.server_selector)); + ot_builder.SetTargetAttributeFilter( + std::move(options.target_attribute_filter)); + ot_builder.SetGenericMethodAttributeFilter( + std::move(options.generic_method_attribute_filter)); + for (auto& option : options.plugin_options) { + ot_builder.AddPluginOption(std::move(option)); + } + for (auto& optional_label_key : options.optional_label_keys) { + ot_builder.AddOptionalLabel(optional_label_key); + } + EXPECT_EQ(ot_builder.BuildAndRegisterGlobal(), absl::OkStatus()); + return reader; +} + } // namespace testing } // namespace grpc diff --git a/test/cpp/ext/otel/otel_test_library.h b/test/cpp/ext/otel/otel_test_library.h index 11d6d3117a2..d9431201bf8 100644 --- a/test/cpp/ext/otel/otel_test_library.h +++ b/test/cpp/ext/otel/otel_test_library.h @@ -114,6 +114,11 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test { return *this; } + Options& add_optional_label(absl::string_view optional_label_key) { + optional_label_keys.emplace(optional_label_key); + return *this; + } + absl::flat_hash_set metric_names; // TODO(yashykt): opentelemetry::sdk::resource::Resource doesn't have a copy // assignment operator so wrapping it in a unique_ptr till it is fixed. @@ -135,6 +140,7 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test { std::vector< std::unique_ptr> plugin_options; + absl::flat_hash_set optional_label_keys; }; // Note that we can't use SetUp() here since we want to send in parameters. @@ -147,6 +153,10 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test { void SendRPC(); void SendGenericRPC(); + std::shared_ptr + BuildAndRegisterOpenTelemetryPlugin( + OpenTelemetryPluginEnd2EndTest::Options options); + absl::flat_hash_map< std::string, std::vector> @@ -155,7 +165,8 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test { bool(const absl::flat_hash_map< std::string, std::vector>&)> - continue_predicate); + continue_predicate, + opentelemetry::sdk::metrics::MetricReader* reader = nullptr); const absl::string_view kMethodName = "grpc.testing.EchoTestService/Echo"; const absl::string_view kGenericMethodName = "foo/bar"; diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 4d50f2cd55c..b09d01edc46 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -2165,6 +2165,7 @@ src/core/lib/channel/metrics.h \ src/core/lib/channel/promise_based_filter.cc \ src/core/lib/channel/promise_based_filter.h \ src/core/lib/channel/server_call_tracer_filter.cc \ +src/core/lib/channel/server_call_tracer_filter.h \ src/core/lib/channel/status_util.cc \ src/core/lib/channel/status_util.h \ src/core/lib/channel/tcp_tracer.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 5f2f1f4e642..cea615a2f53 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1937,6 +1937,7 @@ src/core/lib/channel/metrics.h \ src/core/lib/channel/promise_based_filter.cc \ src/core/lib/channel/promise_based_filter.h \ src/core/lib/channel/server_call_tracer_filter.cc \ +src/core/lib/channel/server_call_tracer_filter.h \ src/core/lib/channel/status_util.cc \ src/core/lib/channel/status_util.h \ src/core/lib/channel/tcp_tracer.h \