diff --git a/include/envoy/http/context.h b/include/envoy/http/context.h index a9d5ac5c9315..683b0e75e849 100644 --- a/include/envoy/http/context.h +++ b/include/envoy/http/context.h @@ -29,6 +29,7 @@ class Context { virtual CodeStats& codeStats() PURE; virtual const UserAgentContext& userAgentContext() const PURE; + virtual const Stats::StatName& asyncClientStatPrefix() const PURE; }; using ContextPtr = std::unique_ptr; diff --git a/include/envoy/router/BUILD b/include/envoy/router/BUILD index f3e5c450d04e..ed2a65c67c8a 100644 --- a/include/envoy/router/BUILD +++ b/include/envoy/router/BUILD @@ -8,6 +8,11 @@ licenses(["notice"]) # Apache 2 envoy_package() +envoy_cc_library( + name = "context_interface", + hdrs = ["context.h"], +) + envoy_cc_library( name = "rds_interface", hdrs = ["rds.h"], diff --git a/include/envoy/router/context.h b/include/envoy/router/context.h new file mode 100644 index 000000000000..d67cee93c4b7 --- /dev/null +++ b/include/envoy/router/context.h @@ -0,0 +1,21 @@ +#pragma once + +#include "envoy/common/pure.h" + +namespace Envoy { +namespace Router { + +struct StatNames; + +class Context { +public: + virtual ~Context() = default; + + /** + * @return a struct containing StatNames for router stats. + */ + virtual const StatNames& statNames() const PURE; +}; + +} // namespace Router +} // namespace Envoy diff --git a/include/envoy/server/BUILD b/include/envoy/server/BUILD index 0fbd876f0a94..1af7669c5cae 100644 --- a/include/envoy/server/BUILD +++ b/include/envoy/server/BUILD @@ -182,6 +182,7 @@ envoy_cc_library( "//include/envoy/init:manager_interface", "//include/envoy/local_info:local_info_interface", "//include/envoy/network:drain_decision_interface", + "//include/envoy/router:context_interface", "//include/envoy/runtime:runtime_interface", "//include/envoy/server/overload:overload_manager_interface", "//include/envoy/singleton:manager_interface", diff --git a/include/envoy/server/factory_context.h b/include/envoy/server/factory_context.h index 01ffee80f763..1847d7104289 100644 --- a/include/envoy/server/factory_context.h +++ b/include/envoy/server/factory_context.h @@ -15,6 +15,7 @@ #include "envoy/init/manager.h" #include "envoy/network/drain_decision.h" #include "envoy/network/filter.h" +#include "envoy/router/context.h" #include "envoy/runtime/runtime.h" #include "envoy/server/admin.h" #include "envoy/server/drain_manager.h" @@ -115,6 +116,11 @@ class ServerFactoryContext : public virtual CommonFactoryContext { */ virtual Grpc::Context& grpcContext() PURE; + /** + * @return Router::Context& a reference to the router context. + */ + virtual Router::Context& routerContext() PURE; + /** * @return DrainManager& the server-wide drain manager. */ @@ -223,6 +229,11 @@ class FactoryContext : public virtual CommonFactoryContext { */ virtual Grpc::Context& grpcContext() PURE; + /** + * @return Router::Context& a reference to the router context. + */ + virtual Router::Context& routerContext() PURE; + /** * @return ProcessContextOptRef an optional reference to the * process context. Will be unset when running in validation mode. diff --git a/include/envoy/server/instance.h b/include/envoy/server/instance.h index 338479f5ea2a..23852100438f 100644 --- a/include/envoy/server/instance.h +++ b/include/envoy/server/instance.h @@ -190,6 +190,11 @@ class Instance { */ virtual Http::Context& httpContext() PURE; + /** + * @return the server-wide router context. + */ + virtual Router::Context& routerContext() PURE; + /** * @return the server-wide process context. */ diff --git a/include/envoy/stats/BUILD b/include/envoy/stats/BUILD index 484115c77691..27953a270041 100644 --- a/include/envoy/stats/BUILD +++ b/include/envoy/stats/BUILD @@ -66,7 +66,11 @@ envoy_cc_library( envoy_cc_library( name = "stats_macros", hdrs = ["stats_macros.h"], - deps = [":stats_interface"], + deps = [ + ":stats_interface", + "//source/common/stats:symbol_table_lib", + "//source/common/stats:utility_lib", + ], ) envoy_cc_library( diff --git a/include/envoy/stats/stats_macros.h b/include/envoy/stats/stats_macros.h index a37c5566e89c..0f61674cfdca 100644 --- a/include/envoy/stats/stats_macros.h +++ b/include/envoy/stats/stats_macros.h @@ -5,6 +5,9 @@ #include "envoy/stats/histogram.h" #include "envoy/stats/stats.h" +#include "common/stats/symbol_table_impl.h" +#include "common/stats/utility.h" + #include "absl/strings/match.h" #include "absl/strings/str_cat.h" @@ -33,6 +36,36 @@ namespace Envoy { * Finally, when you want to actually instantiate the above struct using a Stats::Pool, you do: * MyCoolStats stats{ * MY_COOL_STATS(POOL_COUNTER(...), POOL_GAUGE(...), POOL_HISTOGRAM(...))}; + * + * + * The above constructs are the simplest way to declare counters, gauges, + * histograms, and text-readouts in your data structures. However they incur + * some overhead to symbolize the names every time they are instantiated. For + * data structures that are re-instantiated extensively during operation, + * e.g. in response to an xDS update, We can separately instantiate a + * StatNameStruct, containing symbolized names for each stat. That should be + * instantiated once at startup and held in some context or factory. Do that + * with: + * + * MAKE_STAT_NAMES_STRUCT(MyStatNames, MY_COOL_STATS); + * + * This generates a structure definition with a constructor that requires a + * SymbolTable. So you must, in a context instantiated once, initialize with: + * + * : my_cool_stat_names_(stat_store.symbolTable()) + * + * Once you have the StatNamesStruct instance declared, you can create a stats + * struct efficiently during operation (e.g. in an xDS handler) with + * + * MAKE_STATS_STRUCT(MyStats, MyStatNames, MY_COOL_STATS); + * + * This new structure is constructed with 2 or 3 args: + * 1. The stat_names struct created from MAKE_STAT_NAMES_STRUCT + * 2. The scope in which to instantiate the stats + * 3. An optional prefix, which will be prepended to each stat name. + * For example: + * + * : my_cool_stats_(context.my_cool_stat_names_, scope, opt_prefix) */ // Fully-qualified for use in external callsites. @@ -59,6 +92,7 @@ static inline std::string statPrefixJoin(absl::string_view prefix, absl::string_ #define POOL_GAUGE_PREFIX(POOL, PREFIX) (POOL).gaugeFromString(Envoy::statPrefixJoin(PREFIX, FINISH_STAT_DECL_MODE_ #define POOL_HISTOGRAM_PREFIX(POOL, PREFIX) (POOL).histogramFromString(Envoy::statPrefixJoin(PREFIX, FINISH_STAT_DECL_UNIT_ #define POOL_TEXT_READOUT_PREFIX(POOL, PREFIX) (POOL).textReadoutFromString(Envoy::statPrefixJoin(PREFIX, FINISH_STAT_DECL_ +#define POOL_STAT_NAME_PREFIX(POOL, PREFIX) (POOL).symbolTable().textReadoutFromString(Envoy::statPrefixJoin(PREFIX, FINISH_STAT_DECL_ #define POOL_COUNTER(POOL) POOL_COUNTER_PREFIX(POOL, "") #define POOL_GAUGE(POOL) POOL_GAUGE_PREFIX(POOL, "") @@ -69,4 +103,65 @@ static inline std::string statPrefixJoin(absl::string_view prefix, absl::string_ #define NULL_STAT_DECL_IGNORE_MODE_(X, MODE) std::string(#X)), #define NULL_POOL_GAUGE(POOL) (POOL).nullGauge(NULL_STAT_DECL_IGNORE_MODE_ + +// Used for declaring StatNames in a structure. +#define GENERATE_STAT_NAME_STRUCT(NAME, ...) Envoy::Stats::StatName NAME##_; +#define GENERATE_STAT_NAME_INIT(NAME, ...) , NAME##_(pool_.add(#NAME)) + +// Macros for declaring stat-structures using StatNames, for those that must be +// instantiated during operation, and where speed and scale matters. These +// macros are not for direct use; they are only for use from +// MAKE_STAT_NAMES_STRUCT. and MAKE_STAT_STRUCT. +#define MAKE_STATS_STRUCT_COUNTER_HELPER_(NAME) \ + , NAME##_(Envoy::Stats::Utility::counterFromStatNames(scope, {prefix, stat_names.NAME##_})) +#define MAKE_STATS_STRUCT_GAUGE_HELPER_(NAME, MODE) \ + , NAME##_(Envoy::Stats::Utility::gaugeFromStatNames(scope, {prefix, stat_names.NAME##_}, \ + Envoy::Stats::Gauge::ImportMode::MODE)) +#define MAKE_STATS_STRUCT_HISTOGRAM_HELPER_(NAME, UNIT) \ + , NAME##_(Envoy::Stats::Utility::histogramFromStatNames(scope, {prefix, stat_names.NAME##_}, \ + Envoy::Stats::Histogram::Unit::UNIT)) +#define MAKE_STATS_STRUCT_TEXT_READOUT_HELPER_(NAME) \ + , NAME##_(Envoy::Stats::Utility::textReadoutFromStatNames(scope, {prefix, stat_names.NAME##_})) + +#define MAKE_STATS_STRUCT_STATNAME_HELPER_(name) +#define GENERATE_STATNAME_STRUCT(name) + +/** + * Generates a struct with StatNames for a subsystem, based on the stats macro + * with COUNTER, GAUGE, HISTOGRAM, TEXT_READOUT, and STATNAME calls. The + * ALL_STATS macro must have all 5 parameters. + */ +#define MAKE_STAT_NAMES_STRUCT(StatNamesStruct, ALL_STATS) \ + struct StatNamesStruct { \ + explicit StatNamesStruct(Envoy::Stats::SymbolTable& symbol_table) \ + : pool_(symbol_table) \ + ALL_STATS(GENERATE_STAT_NAME_INIT, GENERATE_STAT_NAME_INIT, GENERATE_STAT_NAME_INIT, \ + GENERATE_STAT_NAME_INIT, GENERATE_STAT_NAME_INIT) {} \ + Envoy::Stats::StatNamePool pool_; \ + ALL_STATS(GENERATE_STAT_NAME_STRUCT, GENERATE_STAT_NAME_STRUCT, GENERATE_STAT_NAME_STRUCT, \ + GENERATE_STAT_NAME_STRUCT, GENERATE_STAT_NAME_STRUCT) \ + } + +/** + * Instantiates a structure of stats based on a new scope and optional prefix, + * using a predefined structure of stat names. A reference to the stat_names is + * also stored in the structure, for two reasons: (a) as a syntactic convenience + * for using macros to generate the comma separators for the initializer and (b) + * as a convenience at the call-site to access STATNAME-declared names from the + * stats structure. + */ +#define MAKE_STATS_STRUCT(StatsStruct, StatNamesStruct, ALL_STATS) \ + struct StatsStruct { \ + StatsStruct(const StatNamesStruct& stat_names, Envoy::Stats::Scope& scope, \ + Envoy::Stats::StatName prefix = Envoy::Stats::StatName()) \ + : stat_names_(stat_names) \ + ALL_STATS(MAKE_STATS_STRUCT_COUNTER_HELPER_, MAKE_STATS_STRUCT_GAUGE_HELPER_, \ + MAKE_STATS_STRUCT_HISTOGRAM_HELPER_, \ + MAKE_STATS_STRUCT_TEXT_READOUT_HELPER_, \ + MAKE_STATS_STRUCT_STATNAME_HELPER_) {} \ + const StatNamesStruct& stat_names_; \ + ALL_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT, GENERATE_HISTOGRAM_STRUCT, \ + GENERATE_TEXT_READOUT_STRUCT, GENERATE_STATNAME_STRUCT) \ + } + } // namespace Envoy diff --git a/include/envoy/upstream/cluster_manager.h b/include/envoy/upstream/cluster_manager.h index 73b06f76612c..15665dd658d5 100644 --- a/include/envoy/upstream/cluster_manager.h +++ b/include/envoy/upstream/cluster_manager.h @@ -24,6 +24,7 @@ #include "envoy/singleton/manager.h" #include "envoy/ssl/context_manager.h" #include "envoy/stats/store.h" +#include "envoy/stats/symbol_table.h" #include "envoy/tcp/conn_pool.h" #include "envoy/thread_local/thread_local.h" #include "envoy/upstream/health_checker.h" @@ -334,6 +335,16 @@ class ClusterManager { * @return Config::SubscriptionFactory& the subscription factory. */ virtual Config::SubscriptionFactory& subscriptionFactory() PURE; + + /** + * Returns a struct with all the Stats::StatName objects needed by + * Clusters. This helps factor out some relatively heavy name + * construction which occur when there is a large CDS update during operation, + * relative to recreating all stats from strings on-the-fly. + * + * @return the stat names. + */ + virtual const ClusterStatNames& clusterStatNames() const PURE; }; using ClusterManagerPtr = std::unique_ptr; diff --git a/include/envoy/upstream/upstream.h b/include/envoy/upstream/upstream.h index c87950b03f93..d863b0caeb54 100644 --- a/include/envoy/upstream/upstream.h +++ b/include/envoy/upstream/upstream.h @@ -515,7 +515,7 @@ class PrioritySet { /** * All cluster stats. @see stats_macros.h */ -#define ALL_CLUSTER_STATS(COUNTER, GAUGE, HISTOGRAM) \ +#define ALL_CLUSTER_STATS(COUNTER, GAUGE, HISTOGRAM, TEXT_READOUT, STATNAME) \ COUNTER(assignment_stale) \ COUNTER(assignment_timeout_received) \ COUNTER(bind_errors) \ @@ -643,9 +643,8 @@ class PrioritySet { /** * Struct definition for all cluster stats. @see stats_macros.h */ -struct ClusterStats { - ALL_CLUSTER_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT, GENERATE_HISTOGRAM_STRUCT) -}; +MAKE_STAT_NAMES_STRUCT(ClusterStatNames, ALL_CLUSTER_STATS); +MAKE_STATS_STRUCT(ClusterStats, ClusterStatNames, ALL_CLUSTER_STATS); /** * Struct definition for all cluster load report stats. @see stats_macros.h diff --git a/source/common/http/BUILD b/source/common/http/BUILD index 01798486ffef..93f846420100 100644 --- a/source/common/http/BUILD +++ b/source/common/http/BUILD @@ -20,6 +20,7 @@ envoy_cc_library( "//include/envoy/http:context_interface", "//include/envoy/http:header_map_interface", "//include/envoy/http:message_interface", + "//include/envoy/router:context_interface", "//include/envoy/router:router_interface", "//include/envoy/router:router_ratelimit_interface", "//include/envoy/router:shadow_writer_interface", diff --git a/source/common/http/async_client_impl.cc b/source/common/http/async_client_impl.cc index 0ebbbdfd12f7..25e1e3704cd3 100644 --- a/source/common/http/async_client_impl.cc +++ b/source/common/http/async_client_impl.cc @@ -41,10 +41,10 @@ AsyncClientImpl::AsyncClientImpl(Upstream::ClusterInfoConstSharedPtr cluster, Upstream::ClusterManager& cm, Runtime::Loader& runtime, Random::RandomGenerator& random, Router::ShadowWriterPtr&& shadow_writer, - Http::Context& http_context) - : cluster_(cluster), config_("http.async-client.", local_info, stats_store, cm, runtime, random, - std::move(shadow_writer), true, false, false, false, {}, - dispatcher.timeSource(), http_context), + Http::Context& http_context, Router::Context& router_context) + : cluster_(cluster), config_(http_context.asyncClientStatPrefix(), local_info, stats_store, cm, + runtime, random, std::move(shadow_writer), true, false, false, + false, {}, dispatcher.timeSource(), http_context, router_context), dispatcher_(dispatcher) {} AsyncClientImpl::~AsyncClientImpl() { diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h index 31e43a663601..00fc7d09a5dc 100644 --- a/source/common/http/async_client_impl.h +++ b/source/common/http/async_client_impl.h @@ -20,6 +20,7 @@ #include "envoy/http/context.h" #include "envoy/http/header_map.h" #include "envoy/http/message.h" +#include "envoy/router/context.h" #include "envoy/router/router.h" #include "envoy/router/router_ratelimit.h" #include "envoy/router/shadow_writer.h" @@ -49,7 +50,7 @@ class AsyncClientImpl final : public AsyncClient { Event::Dispatcher& dispatcher, const LocalInfo::LocalInfo& local_info, Upstream::ClusterManager& cm, Runtime::Loader& runtime, Random::RandomGenerator& random, Router::ShadowWriterPtr&& shadow_writer, - Http::Context& http_context); + Http::Context& http_context, Router::Context& router_context); ~AsyncClientImpl() override; // Http::AsyncClient diff --git a/source/common/http/context_impl.cc b/source/common/http/context_impl.cc index a7f128f6e12a..05fdd5f54f3d 100644 --- a/source/common/http/context_impl.cc +++ b/source/common/http/context_impl.cc @@ -4,7 +4,8 @@ namespace Envoy { namespace Http { ContextImpl::ContextImpl(Stats::SymbolTable& symbol_table) - : code_stats_(symbol_table), user_agent_context_(symbol_table) {} + : code_stats_(symbol_table), user_agent_context_(symbol_table), + async_client_stat_prefix_(user_agent_context_.pool_.add("http.async-client")) {} } // namespace Http } // namespace Envoy diff --git a/source/common/http/context_impl.h b/source/common/http/context_impl.h index bbd651e86e2c..c7fb0732e8dd 100644 --- a/source/common/http/context_impl.h +++ b/source/common/http/context_impl.h @@ -27,10 +27,14 @@ class ContextImpl : public Context { } const UserAgentContext& userAgentContext() const override { return user_agent_context_; } + const Stats::StatName& asyncClientStatPrefix() const override { + return async_client_stat_prefix_; + } private: CodeStatsImpl code_stats_; UserAgentContext user_agent_context_; + const Stats::StatName async_client_stat_prefix_; envoy::config::trace::v3::Tracing default_tracing_config_; }; diff --git a/source/common/router/BUILD b/source/common/router/BUILD index d0d4294d4467..5bd33b8b7a63 100644 --- a/source/common/router/BUILD +++ b/source/common/router/BUILD @@ -91,6 +91,16 @@ envoy_cc_library( ], ) +envoy_cc_library( + name = "context_lib", + srcs = ["context_impl.cc"], + hdrs = ["context_impl.h"], + deps = [ + "//include/envoy/router:context_interface", + "//include/envoy/stats:stats_macros", + ], +) + envoy_cc_library( name = "debug_config_lib", srcs = ["debug_config.cc"], @@ -270,6 +280,7 @@ envoy_cc_library( ], deps = [ ":config_lib", + ":context_lib", ":debug_config_lib", ":header_parser_lib", ":retry_state_lib", diff --git a/source/common/router/context_impl.cc b/source/common/router/context_impl.cc new file mode 100644 index 000000000000..311a4becc469 --- /dev/null +++ b/source/common/router/context_impl.cc @@ -0,0 +1,9 @@ +#include "common/router/context_impl.h" + +namespace Envoy { +namespace Router { + +ContextImpl::ContextImpl(Stats::SymbolTable& symbol_table) : stat_names_(symbol_table) {} + +} // namespace Router +} // namespace Envoy diff --git a/source/common/router/context_impl.h b/source/common/router/context_impl.h new file mode 100644 index 000000000000..e9467ab5a89e --- /dev/null +++ b/source/common/router/context_impl.h @@ -0,0 +1,43 @@ +#pragma once + +#include "envoy/router/context.h" +#include "envoy/stats/stats_macros.h" + +namespace Envoy { +namespace Router { + +/** + * All router filter stats. @see stats_macros.h + */ +#define ALL_ROUTER_STATS(COUNTER, GAUGE, HISTOGRAM, TEXT_READOUT, STATNAME) \ + COUNTER(no_cluster) \ + COUNTER(no_route) \ + COUNTER(passthrough_internal_redirect_bad_location) \ + COUNTER(passthrough_internal_redirect_no_route) \ + COUNTER(passthrough_internal_redirect_predicate) \ + COUNTER(passthrough_internal_redirect_too_many_redirects) \ + COUNTER(passthrough_internal_redirect_unsafe_scheme) \ + COUNTER(rq_direct_response) \ + COUNTER(rq_redirect) \ + COUNTER(rq_reset_after_downstream_response_started) \ + COUNTER(rq_total) \ + STATNAME(retry) + +MAKE_STAT_NAMES_STRUCT(StatNames, ALL_ROUTER_STATS); + +/** + * Captures router-related structures with cardinality of one per server. + */ +class ContextImpl : public Context { +public: + explicit ContextImpl(Stats::SymbolTable& symbol_table); + ~ContextImpl() override = default; + + const StatNames& statNames() const override { return stat_names_; } + +private: + const StatNames stat_names_; +}; + +} // namespace Router +} // namespace Envoy diff --git a/source/common/router/router.cc b/source/common/router/router.cc index 2c8dd40b8e97..ef3ddd025a46 100644 --- a/source/common/router/router.cc +++ b/source/common/router/router.cc @@ -1212,7 +1212,8 @@ void Filter::onUpstreamHeaders(uint64_t response_code, Http::ResponseHeaderMapPt pending_retries_++; upstream_request.upstreamHost()->stats().rq_error_.inc(); Http::CodeStats& code_stats = httpContext().codeStats(); - code_stats.chargeBasicResponseStat(cluster_->statsScope(), config_.retry_, + code_stats.chargeBasicResponseStat(cluster_->statsScope(), + config_.stats_.stat_names_.retry_, static_cast(response_code)); if (!end_stream || !upstream_request.encodeComplete()) { diff --git a/source/common/router/router.h b/source/common/router/router.h index f5512919d7da..6688d973098d 100644 --- a/source/common/router/router.h +++ b/source/common/router/router.h @@ -29,6 +29,7 @@ #include "common/config/well_known_names.h" #include "common/http/utility.h" #include "common/router/config_impl.h" +#include "common/router/context_impl.h" #include "common/router/upstream_request.h" #include "common/stats/symbol_table_impl.h" #include "common/stream_info/stream_info_impl.h" @@ -37,30 +38,10 @@ namespace Envoy { namespace Router { -/** - * All router filter stats. @see stats_macros.h - */ -// clang-format off -#define ALL_ROUTER_STATS(COUNTER) \ - COUNTER(passthrough_internal_redirect_bad_location) \ - COUNTER(passthrough_internal_redirect_unsafe_scheme) \ - COUNTER(passthrough_internal_redirect_too_many_redirects) \ - COUNTER(passthrough_internal_redirect_no_route) \ - COUNTER(passthrough_internal_redirect_predicate) \ - COUNTER(no_route) \ - COUNTER(no_cluster) \ - COUNTER(rq_redirect) \ - COUNTER(rq_direct_response) \ - COUNTER(rq_total) \ - COUNTER(rq_reset_after_downstream_response_started) -// clang-format on - /** * Struct definition for all router filter stats. @see stats_macros.h */ -struct FilterStats { - ALL_ROUTER_STATS(GENERATE_COUNTER_STRUCT) -}; +MAKE_STATS_STRUCT(FilterStats, StatNames, ALL_ROUTER_STATS); /** * Router filter utilities split out for ease of testing. @@ -179,22 +160,22 @@ class FilterUtility { */ class FilterConfig { public: - FilterConfig(const std::string& stat_prefix, const LocalInfo::LocalInfo& local_info, + FilterConfig(Stats::StatName stat_prefix, const LocalInfo::LocalInfo& local_info, Stats::Scope& scope, Upstream::ClusterManager& cm, Runtime::Loader& runtime, Random::RandomGenerator& random, ShadowWriterPtr&& shadow_writer, bool emit_dynamic_stats, bool start_child_span, bool suppress_envoy_headers, bool respect_expected_rq_timeout, const Protobuf::RepeatedPtrField& strict_check_headers, - TimeSource& time_source, Http::Context& http_context) - : scope_(scope), local_info_(local_info), cm_(cm), runtime_(runtime), - random_(random), stats_{ALL_ROUTER_STATS(POOL_COUNTER_PREFIX(scope, stat_prefix))}, + TimeSource& time_source, Http::Context& http_context, + Router::Context& router_context) + : scope_(scope), local_info_(local_info), cm_(cm), runtime_(runtime), random_(random), + stats_(router_context.statNames(), scope, stat_prefix), emit_dynamic_stats_(emit_dynamic_stats), start_child_span_(start_child_span), suppress_envoy_headers_(suppress_envoy_headers), respect_expected_rq_timeout_(respect_expected_rq_timeout), http_context_(http_context), - stat_name_pool_(scope_.symbolTable()), retry_(stat_name_pool_.add("retry")), + stat_name_pool_(scope_.symbolTable()), zone_name_(stat_name_pool_.add(local_info_.zoneName())), - empty_stat_name_(stat_name_pool_.add("")), shadow_writer_(std::move(shadow_writer)), - time_source_(time_source) { + shadow_writer_(std::move(shadow_writer)), time_source_(time_source) { if (!strict_check_headers.empty()) { strict_check_headers_ = std::make_unique(); for (const auto& header : strict_check_headers) { @@ -203,7 +184,7 @@ class FilterConfig { } } - FilterConfig(const std::string& stat_prefix, Server::Configuration::FactoryContext& context, + FilterConfig(Stats::StatName stat_prefix, Server::Configuration::FactoryContext& context, ShadowWriterPtr&& shadow_writer, const envoy::extensions::filters::http::router::v3::Router& config) : FilterConfig(stat_prefix, context.localInfo(), context.scope(), context.clusterManager(), @@ -211,7 +192,7 @@ class FilterConfig { PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, dynamic_stats, true), config.start_child_span(), config.suppress_envoy_headers(), config.respect_expected_rq_timeout(), config.strict_check_headers(), - context.api().timeSource(), context.httpContext()) { + context.api().timeSource(), context.httpContext(), context.routerContext()) { for (const auto& upstream_log : config.upstream_log()) { upstream_logs_.push_back(AccessLog::AccessLogFactory::fromProto(upstream_log, context)); } @@ -236,8 +217,8 @@ class FilterConfig { HeaderVectorPtr strict_check_headers_; std::list upstream_logs_; Http::Context& http_context_; - Stats::StatNamePool stat_name_pool_; - Stats::StatName retry_; + Stats::StatNamePool + stat_name_pool_; // TODO(#14242): use dynamic name for zone_name and drop pool. Stats::StatName zone_name_; Stats::StatName empty_stat_name_; diff --git a/source/common/stats/BUILD b/source/common/stats/BUILD index edc68f4774e7..b5250438240d 100644 --- a/source/common/stats/BUILD +++ b/source/common/stats/BUILD @@ -182,8 +182,8 @@ envoy_cc_library( ":recent_lookups_lib", "//include/envoy/stats:symbol_table_interface", "//source/common/common:assert_lib", - "//source/common/common:logger_lib", "//source/common/common:mem_block_builder_lib", + "//source/common/common:minimal_logger_lib", "//source/common/common:thread_lib", "//source/common/common:utility_lib", ], @@ -263,5 +263,8 @@ envoy_cc_library( name = "utility_lib", srcs = ["utility.cc"], hdrs = ["utility.h"], - deps = [":symbol_table_lib"], + deps = [ + ":symbol_table_lib", + "//include/envoy/stats:stats_interface", + ], ) diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index 249a0da89fc7..a3d9738384e1 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -44,6 +44,7 @@ envoy_cc_library( "//include/envoy/http:codes_interface", "//include/envoy/local_info:local_info_interface", "//include/envoy/network:dns_interface", + "//include/envoy/router:context_interface", "//include/envoy/runtime:runtime_interface", "//include/envoy/ssl:context_manager_interface", "//include/envoy/thread_local:thread_local_interface", @@ -62,6 +63,7 @@ envoy_cc_library( "//source/common/network:resolver_lib", "//source/common/network:utility_lib", "//source/common/protobuf:utility_lib", + "//source/common/router:context_lib", "//source/common/router:shadow_writer_lib", "//source/common/shared_pool:shared_pool_lib", "//source/common/tcp:conn_pool_lib", diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index f00a4a753db5..822ba56c609c 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -249,7 +249,7 @@ ClusterManagerImpl::ClusterManagerImpl( const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager, Event::Dispatcher& main_thread_dispatcher, Server::Admin& admin, ProtobufMessage::ValidationContext& validation_context, Api::Api& api, - Http::Context& http_context, Grpc::Context& grpc_context) + Http::Context& http_context, Grpc::Context& grpc_context, Router::Context& router_context) : factory_(factory), runtime_(runtime), stats_(stats), tls_(tls), random_(api.randomGenerator()), bind_config_(bootstrap.cluster_manager().upstream_bind_config()), local_info_(local_info), @@ -258,7 +258,8 @@ ClusterManagerImpl::ClusterManagerImpl( config_tracker_entry_( admin.getConfigTracker().add("clusters", [this] { return dumpClusterConfigs(); })), time_source_(main_thread_dispatcher.timeSource()), dispatcher_(main_thread_dispatcher), - http_context_(http_context), + http_context_(http_context), router_context_(router_context), + cluster_stat_names_(stats.symbolTable()), subscription_factory_(local_info, main_thread_dispatcher, *this, validation_context.dynamicValidationVisitor(), api, runtime_) { async_client_manager_ = std::make_unique( @@ -1341,7 +1342,7 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::ClusterEntry( parent.parent_.local_info_, parent.parent_, parent.parent_.runtime_, parent.parent_.random_, Router::ShadowWriterPtr{new Router::ShadowWriterImpl(parent.parent_)}, - parent_.parent_.http_context_) { + parent_.parent_.http_context_, parent_.parent_.router_context_) { priority_set_.getOrCreateHostSet(0); // TODO(mattklein123): Consider converting other LBs over to thread local. All of them could @@ -1511,7 +1512,7 @@ ClusterManagerPtr ProdClusterManagerFactory::clusterManagerFromProto( const envoy::config::bootstrap::v3::Bootstrap& bootstrap) { return ClusterManagerPtr{new ClusterManagerImpl( bootstrap, *this, stats_, tls_, runtime_, local_info_, log_manager_, main_thread_dispatcher_, - admin_, validation_context_, api_, http_context_, grpc_context_)}; + admin_, validation_context_, api_, http_context_, grpc_context_, router_context_)}; } Http::ConnectionPool::InstancePtr ProdClusterManagerFactory::allocateConnPool( diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h index 7db29fb61bb5..f12361bc2830 100644 --- a/source/common/upstream/cluster_manager_impl.h +++ b/source/common/upstream/cluster_manager_impl.h @@ -17,6 +17,7 @@ #include "envoy/config/core/v3/config_source.pb.h" #include "envoy/http/codes.h" #include "envoy/local_info/local_info.h" +#include "envoy/router/context.h" #include "envoy/runtime/runtime.h" #include "envoy/secret/secret_manager.h" #include "envoy/ssl/context_manager.h" @@ -40,21 +41,19 @@ namespace Upstream { */ class ProdClusterManagerFactory : public ClusterManagerFactory { public: - ProdClusterManagerFactory(Server::Admin& admin, Runtime::Loader& runtime, Stats::Store& stats, - ThreadLocal::Instance& tls, Network::DnsResolverSharedPtr dns_resolver, - Ssl::ContextManager& ssl_context_manager, - Event::Dispatcher& main_thread_dispatcher, - const LocalInfo::LocalInfo& local_info, - Secret::SecretManager& secret_manager, - ProtobufMessage::ValidationContext& validation_context, Api::Api& api, - Http::Context& http_context, Grpc::Context& grpc_context, - AccessLog::AccessLogManager& log_manager, - Singleton::Manager& singleton_manager) + ProdClusterManagerFactory( + Server::Admin& admin, Runtime::Loader& runtime, Stats::Store& stats, + ThreadLocal::Instance& tls, Network::DnsResolverSharedPtr dns_resolver, + Ssl::ContextManager& ssl_context_manager, Event::Dispatcher& main_thread_dispatcher, + const LocalInfo::LocalInfo& local_info, Secret::SecretManager& secret_manager, + ProtobufMessage::ValidationContext& validation_context, Api::Api& api, + Http::Context& http_context, Grpc::Context& grpc_context, Router::Context& router_context, + AccessLog::AccessLogManager& log_manager, Singleton::Manager& singleton_manager) : main_thread_dispatcher_(main_thread_dispatcher), validation_context_(validation_context), - api_(api), http_context_(http_context), grpc_context_(grpc_context), admin_(admin), - runtime_(runtime), stats_(stats), tls_(tls), dns_resolver_(dns_resolver), - ssl_context_manager_(ssl_context_manager), local_info_(local_info), - secret_manager_(secret_manager), log_manager_(log_manager), + api_(api), http_context_(http_context), grpc_context_(grpc_context), + router_context_(router_context), admin_(admin), runtime_(runtime), stats_(stats), tls_(tls), + dns_resolver_(dns_resolver), ssl_context_manager_(ssl_context_manager), + local_info_(local_info), secret_manager_(secret_manager), log_manager_(log_manager), singleton_manager_(singleton_manager) {} // Upstream::ClusterManagerFactory @@ -85,6 +84,7 @@ class ProdClusterManagerFactory : public ClusterManagerFactory { Api::Api& api_; Http::Context& http_context_; Grpc::Context& grpc_context_; + Router::Context& router_context_; Server::Admin& admin_; Runtime::Loader& runtime_; Stats::Store& stats_; @@ -223,7 +223,8 @@ class ClusterManagerImpl : public ClusterManager, Logger::LoggablesymbolTable()), + stats_(generateStats(*stats_scope_, factory_context.clusterManager().clusterStatNames())), + load_report_stats_store_(stats_scope_->symbolTable()), load_report_stats_(generateLoadReportStats(load_report_stats_store_)), optional_cluster_stats_((config.has_track_cluster_stats() || config.track_timeout_budgets()) ? std::make_unique(config, *stats_scope_) diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index fac63e0d5fb0..356596e4d5da 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -526,7 +526,8 @@ class ClusterInfoImpl : public ClusterInfo, protected Logger::Loggable(context.clusterManager()), - proto_config)); + prefix.statName(), context, + std::make_unique(context.clusterManager()), proto_config)); return [filter_config](Http::FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(std::make_shared(*filter_config)); diff --git a/source/server/config_validation/BUILD b/source/server/config_validation/BUILD index f56d6069dd57..b6c57bbc824a 100644 --- a/source/server/config_validation/BUILD +++ b/source/server/config_validation/BUILD @@ -101,6 +101,7 @@ envoy_cc_library( "//source/common/grpc:common_lib", "//source/common/local_info:local_info_lib", "//source/common/protobuf:utility_lib", + "//source/common/router:context_lib", "//source/common/router:rds_lib", "//source/common/runtime:runtime_lib", "//source/common/stats:stats_lib", diff --git a/source/server/config_validation/cluster_manager.cc b/source/server/config_validation/cluster_manager.cc index 38e1413da9d9..025500e77f18 100644 --- a/source/server/config_validation/cluster_manager.cc +++ b/source/server/config_validation/cluster_manager.cc @@ -12,7 +12,8 @@ ClusterManagerPtr ValidationClusterManagerFactory::clusterManagerFromProto( const envoy::config::bootstrap::v3::Bootstrap& bootstrap) { return std::make_unique( bootstrap, *this, stats_, tls_, runtime_, local_info_, log_manager_, main_thread_dispatcher_, - admin_, validation_context_, api_, http_context_, grpc_context_, time_system_); + admin_, validation_context_, api_, http_context_, grpc_context_, router_context_, + time_system_); } CdsApiPtr @@ -30,10 +31,11 @@ ValidationClusterManager::ValidationClusterManager( const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager, Event::Dispatcher& main_thread_dispatcher, Server::Admin& admin, ProtobufMessage::ValidationContext& validation_context, Api::Api& api, - Http::Context& http_context, Grpc::Context& grpc_context, Event::TimeSystem& time_system) + Http::Context& http_context, Grpc::Context& grpc_context, Router::Context& router_context, + Event::TimeSystem& time_system) : ClusterManagerImpl(bootstrap, factory, stats, tls, runtime, local_info, log_manager, main_thread_dispatcher, admin, validation_context, api, http_context, - grpc_context), + grpc_context, router_context), async_client_(api, time_system) {} Http::ConnectionPool::Instance* ValidationClusterManager::httpConnPoolForCluster( diff --git a/source/server/config_validation/cluster_manager.h b/source/server/config_validation/cluster_manager.h index 38bda5ad2f8d..22919468e3ec 100644 --- a/source/server/config_validation/cluster_manager.h +++ b/source/server/config_validation/cluster_manager.h @@ -27,14 +27,14 @@ class ValidationClusterManagerFactory : public ProdClusterManagerFactory { Ssl::ContextManager& ssl_context_manager, Event::Dispatcher& main_thread_dispatcher, const LocalInfo::LocalInfo& local_info, Secret::SecretManager& secret_manager, ProtobufMessage::ValidationContext& validation_context, Api::Api& api, - Http::Context& http_context, Grpc::Context& grpc_context, + Http::Context& http_context, Grpc::Context& grpc_context, Router::Context& router_context, AccessLog::AccessLogManager& log_manager, Singleton::Manager& singleton_manager, Event::TimeSystem& time_system) : ProdClusterManagerFactory(admin, runtime, stats, tls, dns_resolver, ssl_context_manager, main_thread_dispatcher, local_info, secret_manager, - validation_context, api, http_context, grpc_context, log_manager, - singleton_manager), - grpc_context_(grpc_context), time_system_(time_system) {} + validation_context, api, http_context, grpc_context, + router_context, log_manager, singleton_manager), + grpc_context_(grpc_context), router_context_(router_context), time_system_(time_system) {} ClusterManagerPtr clusterManagerFromProto(const envoy::config::bootstrap::v3::Bootstrap& bootstrap) override; @@ -46,6 +46,7 @@ class ValidationClusterManagerFactory : public ProdClusterManagerFactory { private: Grpc::Context& grpc_context_; + Router::Context& router_context_; Event::TimeSystem& time_system_; }; @@ -62,7 +63,7 @@ class ValidationClusterManager : public ClusterManagerImpl { Server::Admin& admin, ProtobufMessage::ValidationContext& validation_context, Api::Api& api, Http::Context& http_context, Grpc::Context& grpc_context, - Event::TimeSystem& time_system); + Router::Context& router_context, Event::TimeSystem& time_system); Http::ConnectionPool::Instance* httpConnPoolForCluster(const std::string&, ResourcePriority, absl::optional, diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index 00010de29587..a03ff99684d3 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -51,8 +51,8 @@ ValidationInstance::ValidationInstance( access_log_manager_(options.fileFlushIntervalMsec(), *api_, *dispatcher_, access_log_lock, store), mutex_tracer_(nullptr), grpc_context_(stats_store_.symbolTable()), - http_context_(stats_store_.symbolTable()), time_system_(time_system), - server_contexts_(*this) { + http_context_(stats_store_.symbolTable()), router_context_(stats_store_.symbolTable()), + time_system_(time_system), server_contexts_(*this) { try { initialize(options, local_address, component_factory); } catch (const EnvoyException& e) { @@ -101,7 +101,7 @@ void ValidationInstance::initialize(const Options& options, cluster_manager_factory_ = std::make_unique( admin(), runtime(), stats(), threadLocal(), dnsResolver(), sslContextManager(), dispatcher(), localInfo(), *secret_manager_, messageValidationContext(), *api_, http_context_, - grpc_context_, accessLogManager(), singletonManager(), time_system_); + grpc_context_, router_context_, accessLogManager(), singletonManager(), time_system_); config_.initialize(bootstrap, *this, *cluster_manager_factory_); runtime().initialize(clusterManager()); clusterManager().setInitializedCb([this]() -> void { init_manager_.initialize(init_watcher_); }); diff --git a/source/server/config_validation/server.h b/source/server/config_validation/server.h index f35ec97bbd38..0c90a2b048e3 100644 --- a/source/server/config_validation/server.h +++ b/source/server/config_validation/server.h @@ -16,6 +16,7 @@ #include "common/common/random_generator.h" #include "common/grpc/common.h" #include "common/protobuf/message_validator_impl.h" +#include "common/router/context_impl.h" #include "common/router/rds_impl.h" #include "common/runtime/runtime_impl.h" #include "common/secret/secret_manager_impl.h" @@ -98,6 +99,7 @@ class ValidationInstance final : Logger::Loggable, Stats::Store& stats() override { return stats_store_; } Grpc::Context& grpcContext() override { return grpc_context_; } Http::Context& httpContext() override { return http_context_; } + Router::Context& routerContext() override { return router_context_; } ProcessContextOptRef processContext() override { return absl::nullopt; } ThreadLocal::Instance& threadLocal() override { return thread_local_; } const LocalInfo::LocalInfo& localInfo() const override { return *local_info_; } @@ -205,6 +207,7 @@ class ValidationInstance final : Logger::Loggable, MutexTracer* mutex_tracer_; Grpc::ContextImpl grpc_context_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; Event::TimeSystem& time_system_; ServerFactoryContextImpl server_contexts_; }; diff --git a/source/server/filter_chain_manager_impl.cc b/source/server/filter_chain_manager_impl.cc index 65edde071124..3caf91fc01c6 100644 --- a/source/server/filter_chain_manager_impl.cc +++ b/source/server/filter_chain_manager_impl.cc @@ -84,6 +84,10 @@ Http::Context& PerFilterChainFactoryContextImpl::httpContext() { return parent_context_.httpContext(); } +Router::Context& PerFilterChainFactoryContextImpl::routerContext() { + return parent_context_.routerContext(); +} + const LocalInfo::LocalInfo& PerFilterChainFactoryContextImpl::localInfo() const { return parent_context_.localInfo(); } @@ -676,6 +680,7 @@ AccessLog::AccessLogManager& FactoryContextImpl::accessLogManager() { Upstream::ClusterManager& FactoryContextImpl::clusterManager() { return server_.clusterManager(); } Event::Dispatcher& FactoryContextImpl::dispatcher() { return server_.dispatcher(); } Grpc::Context& FactoryContextImpl::grpcContext() { return server_.grpcContext(); } +Router::Context& FactoryContextImpl::routerContext() { return server_.routerContext(); } bool FactoryContextImpl::healthCheckFailed() { return server_.healthCheckFailed(); } Http::Context& FactoryContextImpl::httpContext() { return server_.httpContext(); } Init::Manager& FactoryContextImpl::initManager() { return server_.initManager(); } diff --git a/source/server/filter_chain_manager_impl.h b/source/server/filter_chain_manager_impl.h index 5649c60eaa13..9ee2a20e0e90 100644 --- a/source/server/filter_chain_manager_impl.h +++ b/source/server/filter_chain_manager_impl.h @@ -54,6 +54,7 @@ class PerFilterChainFactoryContextImpl : public Configuration::FilterChainFactor Event::Dispatcher& dispatcher() override; Network::DrainDecision& drainDecision() override; Grpc::Context& grpcContext() override; + Router::Context& routerContext() override; bool healthCheckFailed() override; Http::Context& httpContext() override; Init::Manager& initManager() override; @@ -132,6 +133,7 @@ class FactoryContextImpl : public Configuration::FactoryContext { Upstream::ClusterManager& clusterManager() override; Event::Dispatcher& dispatcher() override; Grpc::Context& grpcContext() override; + Router::Context& routerContext() override; bool healthCheckFailed() override; Http::Context& httpContext() override; Init::Manager& initManager() override; diff --git a/source/server/listener_impl.cc b/source/server/listener_impl.cc index 517f6263565e..322699861133 100644 --- a/source/server/listener_impl.cc +++ b/source/server/listener_impl.cc @@ -187,6 +187,7 @@ Event::Dispatcher& ListenerFactoryContextBaseImpl::dispatcher() { return server_ Grpc::Context& ListenerFactoryContextBaseImpl::grpcContext() { return server_.grpcContext(); } bool ListenerFactoryContextBaseImpl::healthCheckFailed() { return server_.healthCheckFailed(); } Http::Context& ListenerFactoryContextBaseImpl::httpContext() { return server_.httpContext(); } +Router::Context& ListenerFactoryContextBaseImpl::routerContext() { return server_.routerContext(); } const LocalInfo::LocalInfo& ListenerFactoryContextBaseImpl::localInfo() const { return server_.localInfo(); } @@ -596,6 +597,9 @@ bool PerListenerFactoryContextImpl::healthCheckFailed() { Http::Context& PerListenerFactoryContextImpl::httpContext() { return listener_factory_context_base_->httpContext(); } +Router::Context& PerListenerFactoryContextImpl::routerContext() { + return listener_factory_context_base_->routerContext(); +} const LocalInfo::LocalInfo& PerListenerFactoryContextImpl::localInfo() const { return listener_factory_context_base_->localInfo(); } diff --git a/source/server/listener_impl.h b/source/server/listener_impl.h index b0fb4f5ec772..bd7f33db221d 100644 --- a/source/server/listener_impl.h +++ b/source/server/listener_impl.h @@ -104,6 +104,7 @@ class ListenerFactoryContextBaseImpl final : public Configuration::FactoryContex Grpc::Context& grpcContext() override; bool healthCheckFailed() override; Http::Context& httpContext() override; + Router::Context& routerContext() override; Init::Manager& initManager() override; const LocalInfo::LocalInfo& localInfo() const override; Envoy::Runtime::Loader& runtime() override; @@ -169,6 +170,7 @@ class PerListenerFactoryContextImpl : public Configuration::ListenerFactoryConte Grpc::Context& grpcContext() override; bool healthCheckFailed() override; Http::Context& httpContext() override; + Router::Context& routerContext() override; Init::Manager& initManager() override; const LocalInfo::LocalInfo& localInfo() const override; Envoy::Runtime::Loader& runtime() override; diff --git a/source/server/server.cc b/source/server/server.cc index 7bc011a679a8..ca18d62e4375 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -86,8 +86,8 @@ InstanceImpl::InstanceImpl( mutex_tracer_(options.mutexTracingEnabled() ? &Envoy::MutexTracerImpl::getOrCreateTracer() : nullptr), grpc_context_(store.symbolTable()), http_context_(store.symbolTable()), - process_context_(std::move(process_context)), main_thread_id_(std::this_thread::get_id()), - server_contexts_(*this) { + router_context_(store.symbolTable()), process_context_(std::move(process_context)), + main_thread_id_(std::this_thread::get_id()), server_contexts_(*this) { try { if (!options.logPath().empty()) { try { @@ -524,8 +524,8 @@ void InstanceImpl::initialize(const Options& options, cluster_manager_factory_ = std::make_unique( *admin_, Runtime::LoaderSingleton::get(), stats_store_, thread_local_, dns_resolver_, *ssl_context_manager_, *dispatcher_, *local_info_, *secret_manager_, - messageValidationContext(), *api_, http_context_, grpc_context_, access_log_manager_, - *singleton_manager_); + messageValidationContext(), *api_, http_context_, grpc_context_, router_context_, + access_log_manager_, *singleton_manager_); // Now the configuration gets parsed. The configuration may start setting // thread local data per above. See MainImpl::initialize() for why ConfigImpl diff --git a/source/server/server.h b/source/server/server.h index 0409b9db529b..15d950e5683d 100644 --- a/source/server/server.h +++ b/source/server/server.h @@ -32,6 +32,7 @@ #include "common/init/manager_impl.h" #include "common/memory/heap_shrinker.h" #include "common/protobuf/message_validator_impl.h" +#include "common/router/context_impl.h" #include "common/runtime/runtime_impl.h" #include "common/secret/secret_manager_impl.h" #include "common/upstream/health_discovery_service.h" @@ -172,6 +173,7 @@ class ServerFactoryContextImpl : public Configuration::ServerFactoryContext, TimeSource& timeSource() override { return api().timeSource(); } Api::Api& api() override { return server_.api(); } Grpc::Context& grpcContext() override { return server_.grpcContext(); } + Router::Context& routerContext() override { return server_.routerContext(); } Envoy::Server::DrainManager& drainManager() override { return server_.drainManager(); } ServerLifecycleNotifier& lifecycleNotifier() override { return server_.lifecycleNotifier(); } std::chrono::milliseconds statsFlushInterval() const override { @@ -251,6 +253,7 @@ class InstanceImpl final : Logger::Loggable, Stats::Store& stats() override { return stats_store_; } Grpc::Context& grpcContext() override { return grpc_context_; } Http::Context& httpContext() override { return http_context_; } + Router::Context& routerContext() override { return router_context_; } ProcessContextOptRef processContext() override; ThreadLocal::Instance& threadLocal() override { return thread_local_; } const LocalInfo::LocalInfo& localInfo() const override { return *local_info_; } @@ -358,6 +361,7 @@ class InstanceImpl final : Logger::Loggable, Envoy::MutexTracer* mutex_tracer_; Grpc::ContextImpl grpc_context_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; std::unique_ptr process_context_; std::unique_ptr heap_shrinker_; const std::thread::id main_thread_id_; diff --git a/test/common/grpc/BUILD b/test/common/grpc/BUILD index af6bf2f58106..86752e0f318c 100644 --- a/test/common/grpc/BUILD +++ b/test/common/grpc/BUILD @@ -148,6 +148,7 @@ envoy_cc_test_library( "//source/common/grpc:context_lib", "//source/common/http:context_lib", "//source/common/http/http2:conn_pool_lib", + "//source/common/router:context_lib", "//test/integration:integration_lib", "//test/mocks/local_info:local_info_mocks", "//test/mocks/server:transport_socket_factory_context_mocks", diff --git a/test/common/grpc/grpc_client_integration_test_harness.h b/test/common/grpc/grpc_client_integration_test_harness.h index 39efa6154414..b1fccb6474f5 100644 --- a/test/common/grpc/grpc_client_integration_test_harness.h +++ b/test/common/grpc/grpc_client_integration_test_harness.h @@ -20,9 +20,10 @@ #include "common/http/async_client_impl.h" #include "common/http/codes.h" #include "common/http/http2/conn_pool.h" -#include "common/stats/symbol_table_impl.h" #include "common/network/connection_impl.h" #include "common/network/raw_buffer_socket.h" +#include "common/router/context_impl.h" +#include "common/stats/symbol_table_impl.h" #include "extensions/transport_sockets/tls/context_config_impl.h" #include "extensions/transport_sockets/tls/ssl_socket.h" @@ -239,7 +240,7 @@ class GrpcClientIntegrationTest : public GrpcClientIntegrationParamTest { : method_descriptor_(helloworld::Greeter::descriptor()->FindMethodByName("SayHello")), api_(Api::createApiForTest(*stats_store_, test_time_.timeSystem())), dispatcher_(api_->allocateDispatcher("test_thread")), - http_context_(stats_store_->symbolTable()) {} + http_context_(stats_store_->symbolTable()), router_context_(stats_store_->symbolTable()) {} virtual void initialize() { if (fake_upstream_ == nullptr) { @@ -306,7 +307,7 @@ class GrpcClientIntegrationTest : public GrpcClientIntegrationParamTest { .WillRepeatedly(Return(http_conn_pool_.get())); http_async_client_ = std::make_unique( cluster_info_ptr_, *stats_store_, *dispatcher_, local_info_, cm_, runtime_, random_, - std::move(shadow_writer_ptr_), http_context_); + std::move(shadow_writer_ptr_), http_context_, router_context_); EXPECT_CALL(cm_, httpAsyncClientForCluster(fake_cluster_name_)) .WillRepeatedly(ReturnRef(*http_async_client_)); EXPECT_CALL(cm_, getThreadLocalCluster(Eq(fake_cluster_name_))) @@ -473,6 +474,7 @@ class GrpcClientIntegrationTest : public GrpcClientIntegrationParamTest { Http::AsyncClientPtr http_async_client_; Http::ConnectionPool::InstancePtr http_conn_pool_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; envoy::config::core::v3::Locality host_locality_; Upstream::MockHost* mock_host_ = new NiceMock(); Upstream::MockHostDescription* mock_host_description_ = diff --git a/test/common/http/BUILD b/test/common/http/BUILD index ea256d23386d..c821897bb1e1 100644 --- a/test/common/http/BUILD +++ b/test/common/http/BUILD @@ -23,6 +23,7 @@ envoy_cc_test( "//source/common/http:context_lib", "//source/common/http:headers_lib", "//source/common/http:utility_lib", + "//source/common/router:context_lib", "//source/extensions/upstreams/http/generic:config", "//test/mocks:common_lib", "//test/mocks/buffer:buffer_mocks", diff --git a/test/common/http/async_client_impl_test.cc b/test/common/http/async_client_impl_test.cc index 8e4e27ce3ad1..e717c72c3e25 100644 --- a/test/common/http/async_client_impl_test.cc +++ b/test/common/http/async_client_impl_test.cc @@ -11,6 +11,7 @@ #include "common/http/context_impl.h" #include "common/http/headers.h" #include "common/http/utility.h" +#include "common/router/context_impl.h" #include "test/common/http/common.h" #include "test/mocks/buffer/mocks.h" @@ -41,10 +42,11 @@ namespace { class AsyncClientImplTest : public testing::Test { public: AsyncClientImplTest() - : http_context_(stats_store_.symbolTable()), + : http_context_(stats_store_.symbolTable()), router_context_(stats_store_.symbolTable()), client_(cm_.thread_local_cluster_.cluster_.info_, stats_store_, dispatcher_, local_info_, cm_, runtime_, random_, - Router::ShadowWriterPtr{new NiceMock()}, http_context_) { + Router::ShadowWriterPtr{new NiceMock()}, http_context_, + router_context_) { message_->headers().setMethod("GET"); message_->headers().setHost("host"); message_->headers().setPath("/"); @@ -86,6 +88,7 @@ class AsyncClientImplTest : public testing::Test { NiceMock random_; NiceMock local_info_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; AsyncClientImpl client_; NiceMock stream_info_; }; @@ -235,6 +238,8 @@ TEST_F(AsyncClientImplTracingTest, Basic) { ResponseHeaderMapPtr response_headers(new TestResponseHeaderMapImpl{{":status", "200"}}); response_decoder_->decodeHeaders(std::move(response_headers), false); response_decoder_->decodeData(data, true); + + EXPECT_TRUE(stats_store_.findCounterByString("http.async-client.rq_total").has_value()); } TEST_F(AsyncClientImplTracingTest, BasicNamedChildSpan) { diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc index 3b59a864b240..de071f374da9 100644 --- a/test/common/router/router_test.cc +++ b/test/common/router/router_test.cc @@ -95,10 +95,12 @@ class RouterTestBase : public testing::Test { public: RouterTestBase(bool start_child_span, bool suppress_envoy_headers, Protobuf::RepeatedPtrField strict_headers_to_check) - : http_context_(stats_store_.symbolTable()), shadow_writer_(new MockShadowWriter()), - config_("test.", local_info_, stats_store_, cm_, runtime_, random_, + : pool_(stats_store_.symbolTable()), http_context_(stats_store_.symbolTable()), + router_context_(stats_store_.symbolTable()), shadow_writer_(new MockShadowWriter()), + config_(pool_.add("test"), local_info_, stats_store_, cm_, runtime_, random_, ShadowWriterPtr{shadow_writer_}, true, start_child_span, suppress_envoy_headers, - false, std::move(strict_headers_to_check), test_time_.timeSystem(), http_context_), + false, std::move(strict_headers_to_check), test_time_.timeSystem(), http_context_, + router_context_), router_(config_) { router_.setDecoderFilterCallbacks(callbacks_); upstream_locality_.set_zone("to_az"); @@ -358,11 +360,13 @@ class RouterTestBase : public testing::Test { envoy::config::core::v3::Locality upstream_locality_; envoy::config::core::v3::HttpProtocolOptions common_http_protocol_options_; NiceMock stats_store_; + Stats::StatNamePool pool_; NiceMock cm_; NiceMock runtime_; NiceMock random_; Envoy::ConnectionPool::MockCancellable cancellable_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; NiceMock callbacks_; MockShadowWriter* shadow_writer_; NiceMock local_info_; diff --git a/test/common/router/router_upstream_log_test.cc b/test/common/router/router_upstream_log_test.cc index 58ad643f3ad4..6117949e5d47 100644 --- a/test/common/router/router_upstream_log_test.cc +++ b/test/common/router/router_upstream_log_test.cc @@ -93,7 +93,8 @@ class RouterUpstreamLogTest : public testing::Test { current_upstream_log->CopyFrom(upstream_log.value()); } - config_ = std::make_shared("prefix.", context_, + Stats::StatNameManagedStorage prefix("prefix", context_.scope().symbolTable()); + config_ = std::make_shared(prefix.statName(), context_, ShadowWriterPtr(new MockShadowWriter()), router_proto); router_ = std::make_shared(*config_); router_->setDecoderFilterCallbacks(callbacks_); diff --git a/test/common/stats/BUILD b/test/common/stats/BUILD index 0493f5127b17..c2c66200b1b9 100644 --- a/test/common/stats/BUILD +++ b/test/common/stats/BUILD @@ -99,6 +99,7 @@ envoy_cc_test_library( "//source/common/common:assert_lib", "//source/common/memory:stats_lib", "//source/common/stats:isolated_store_lib", + "//test/test_common:global_lib", ], ) diff --git a/test/common/stats/isolated_store_impl_test.cc b/test/common/stats/isolated_store_impl_test.cc index b3a82ad8773e..801ba1710342 100644 --- a/test/common/stats/isolated_store_impl_test.cc +++ b/test/common/stats/isolated_store_impl_test.cc @@ -205,21 +205,23 @@ TEST_F(StatsIsolatedStoreImplTest, LongStatName) { /** * Test stats macros. @see stats_macros.h */ -#define ALL_TEST_STATS(COUNTER, GAUGE, HISTOGRAM, TEXT_READOUT) \ +#define ALL_TEST_STATS(COUNTER, GAUGE, HISTOGRAM, TEXT_READOUT, STATNAME) \ COUNTER(test_counter) \ GAUGE(test_gauge, Accumulate) \ HISTOGRAM(test_histogram, Microseconds) \ - TEXT_READOUT(test_text_readout) + TEXT_READOUT(test_text_readout) \ + STATNAME(prefix) struct TestStats { ALL_TEST_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT, GENERATE_HISTOGRAM_STRUCT, - GENERATE_TEXT_READOUT_STRUCT) + GENERATE_TEXT_READOUT_STRUCT, GENERATE_STATNAME_STRUCT) }; TEST_F(StatsIsolatedStoreImplTest, StatsMacros) { - TestStats test_stats{ALL_TEST_STATS( - POOL_COUNTER_PREFIX(*store_, "test."), POOL_GAUGE_PREFIX(*store_, "test."), - POOL_HISTOGRAM_PREFIX(*store_, "test."), POOL_TEXT_READOUT_PREFIX(*store_, "test."))}; + TestStats test_stats{ + ALL_TEST_STATS(POOL_COUNTER_PREFIX(*store_, "test."), POOL_GAUGE_PREFIX(*store_, "test."), + POOL_HISTOGRAM_PREFIX(*store_, "test."), + POOL_TEXT_READOUT_PREFIX(*store_, "test."), GENERATE_STATNAME_STRUCT)}; Counter& counter = test_stats.test_counter_; EXPECT_EQ("test.test_counter", counter.name()); @@ -244,5 +246,24 @@ TEST_F(StatsIsolatedStoreImplTest, NullImplCoverage) { EXPECT_EQ(0, g.value()); } +TEST_F(StatsIsolatedStoreImplTest, StatNamesStruct) { + MAKE_STAT_NAMES_STRUCT(StatNames, ALL_TEST_STATS); + StatNames stat_names(store_->symbolTable()); + EXPECT_EQ("prefix", store_->symbolTable().toString(stat_names.prefix_)); + ScopePtr scope1 = store_->createScope("scope1."); + ScopePtr scope2 = store_->createScope("scope2."); + MAKE_STATS_STRUCT(Stats, StatNames, ALL_TEST_STATS); + Stats stats1(stat_names, *scope1); + EXPECT_EQ("scope1.test_counter", stats1.test_counter_.name()); + EXPECT_EQ("scope1.test_gauge", stats1.test_gauge_.name()); + EXPECT_EQ("scope1.test_histogram", stats1.test_histogram_.name()); + EXPECT_EQ("scope1.test_text_readout", stats1.test_text_readout_.name()); + Stats stats2(stat_names, *scope2, stat_names.prefix_); + EXPECT_EQ("scope2.prefix.test_counter", stats2.test_counter_.name()); + EXPECT_EQ("scope2.prefix.test_gauge", stats2.test_gauge_.name()); + EXPECT_EQ("scope2.prefix.test_histogram", stats2.test_histogram_.name()); + EXPECT_EQ("scope2.prefix.test_text_readout", stats2.test_text_readout_.name()); +} + } // namespace Stats } // namespace Envoy diff --git a/test/common/stats/stat_test_utility.h b/test/common/stats/stat_test_utility.h index 1d0eaa3c66cf..93ea031db43b 100644 --- a/test/common/stats/stat_test_utility.h +++ b/test/common/stats/stat_test_utility.h @@ -6,11 +6,40 @@ #include "common/memory/stats.h" #include "common/stats/isolated_store_impl.h" +#include "test/test_common/global.h" + #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" namespace Envoy { namespace Stats { + +class TestSymbolTableHelper { +public: + SymbolTable& symbolTable() { return symbol_table_; } + const SymbolTable& constSymbolTable() const { return symbol_table_; } + +private: + SymbolTableImpl symbol_table_; +}; + +// Symbol table wrapper that instantiates a shared, reference-counted, global +// symbol table. This is needed by the mocking infrastructure, as Envoy mocks +// are constructed without any context, but StatNames that are symbolized from +// one mock may need to be entered into stat storage in another one. Thus they +// must be connected by global state. +// +// TODO(jmarantz): rename this as Stats::TestUtil::GlobalSymbolTable to clarify +// the motivation, and rename the 10 call-sites for it. +class TestSymbolTable { +public: + SymbolTable& operator*() { return global_.get().symbolTable(); } + const SymbolTable& operator*() const { return global_.get().constSymbolTable(); } + SymbolTable* operator->() { return &global_.get().symbolTable(); } + const SymbolTable* operator->() const { return &global_.get().constSymbolTable(); } + Envoy::Test::Global global_; +}; + namespace TestUtil { /** @@ -74,6 +103,11 @@ class MemoryTest { const size_t memory_at_construction_; }; +class SymbolTableProvider { +public: + TestSymbolTable global_symbol_table_; +}; + // Helper class to use in lieu of an actual Stats::Store for doing lookups by // name. The intent is to remove the deprecated Scope::counter(const // std::string&) methods, and always use this class for accessing stats by @@ -87,9 +121,9 @@ class MemoryTest { // use the StatName as a key, we must use strings in tests to avoid forcing // the tests to construct the StatName using the same pattern of dynamic // and symbol strings as production. -class TestStore : public IsolatedStoreImpl { +class TestStore : public SymbolTableProvider, public IsolatedStoreImpl { public: - TestStore() = default; + TestStore() : IsolatedStoreImpl(*global_symbol_table_) {} // Constructs a store using a symbol table, allowing for explicit sharing. explicit TestStore(SymbolTable& symbol_table) : IsolatedStoreImpl(symbol_table) {} diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index ee3340cbb4cf..bdfaf94d290a 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -39,6 +39,7 @@ envoy_cc_test( ], deps = [ ":test_cluster_manager", + "//source/common/router:context_lib", "//test/mocks/upstream:cds_api_mocks", "//test/mocks/upstream:cluster_priority_set_mocks", "//test/mocks/upstream:cluster_real_priority_set_mocks", diff --git a/test/common/upstream/cluster_factory_impl_test.cc b/test/common/upstream/cluster_factory_impl_test.cc index d7d4ba78f9ef..90fa378875d0 100644 --- a/test/common/upstream/cluster_factory_impl_test.cc +++ b/test/common/upstream/cluster_factory_impl_test.cc @@ -64,7 +64,7 @@ class ClusterFactoryTestBase { const NiceMock local_info_; NiceMock dispatcher_; NiceMock runtime_; - Stats::IsolatedStoreImpl stats_; + Stats::TestUtil::TestStore stats_; Singleton::ManagerImpl singleton_manager_{Thread::threadFactoryForTest()}; NiceMock tls_; NiceMock validation_visitor_; diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index 17404a5c8ae5..e43b086c1d07 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -4,6 +4,8 @@ #include "envoy/config/cluster/v3/cluster.pb.validate.h" #include "envoy/config/core/v3/base.pb.h" +#include "common/router/context_impl.h" + #include "test/common/upstream/test_cluster_manager.h" #include "test/mocks/upstream/cds_api.h" #include "test/mocks/upstream/cluster_priority_set.h" @@ -44,14 +46,14 @@ std::string clustersJson(const std::vector& clusters) { class ClusterManagerImplTest : public testing::Test { public: ClusterManagerImplTest() - : http_context_(factory_.stats_.symbolTable()), grpc_context_(factory_.stats_.symbolTable()) { - } + : http_context_(factory_.stats_.symbolTable()), grpc_context_(factory_.stats_.symbolTable()), + router_context_(factory_.stats_.symbolTable()) {} void create(const envoy::config::bootstrap::v3::Bootstrap& bootstrap) { cluster_manager_ = std::make_unique( bootstrap, factory_, factory_.stats_, factory_.tls_, factory_.runtime_, factory_.local_info_, log_manager_, factory_.dispatcher_, admin_, validation_context_, - *factory_.api_, http_context_, grpc_context_); + *factory_.api_, http_context_, grpc_context_, router_context_); cluster_manager_->setPrimaryClustersInitializedCb( [this, bootstrap]() { cluster_manager_->initializeSecondaryClusters(bootstrap); }); } @@ -95,7 +97,8 @@ class ClusterManagerImplTest : public testing::Test { cluster_manager_ = std::make_unique( bootstrap, factory_, factory_.stats_, factory_.tls_, factory_.runtime_, factory_.local_info_, log_manager_, factory_.dispatcher_, admin_, validation_context_, - *factory_.api_, local_cluster_update_, local_hosts_removed_, http_context_, grpc_context_); + *factory_.api_, local_cluster_update_, local_hosts_removed_, http_context_, grpc_context_, + router_context_); } void checkStats(uint64_t added, uint64_t modified, uint64_t removed, uint64_t active, @@ -145,6 +148,7 @@ class ClusterManagerImplTest : public testing::Test { MockLocalHostsRemoved local_hosts_removed_; Http::ContextImpl http_context_; Grpc::ContextImpl grpc_context_; + Router::ContextImpl router_context_; }; envoy::config::bootstrap::v3::Bootstrap defaultConfig() { diff --git a/test/common/upstream/eds_speed_test.cc b/test/common/upstream/eds_speed_test.cc index 50ee28cdd0a4..d939e3513dd8 100644 --- a/test/common/upstream/eds_speed_test.cc +++ b/test/common/upstream/eds_speed_test.cc @@ -146,7 +146,7 @@ class EdsSpeedTest { const std::string type_url_; uint64_t version_{}; bool initialized_{}; - Stats::IsolatedStoreImpl stats_; + Stats::TestUtil::TestStore stats_; Config::SubscriptionStats subscription_stats_; Ssl::MockContextManager ssl_context_manager_; envoy::config::cluster::v3::Cluster eds_cluster_; diff --git a/test/common/upstream/load_balancer_benchmark.cc b/test/common/upstream/load_balancer_benchmark.cc index 7c0a7c4cf8fe..4d536e187b64 100644 --- a/test/common/upstream/load_balancer_benchmark.cc +++ b/test/common/upstream/load_balancer_benchmark.cc @@ -66,7 +66,8 @@ class BaseTester : public Event::TestUsingSimulatedTime { PrioritySetImpl priority_set_; PrioritySetImpl local_priority_set_; Stats::IsolatedStoreImpl stats_store_; - ClusterStats stats_{ClusterInfoImpl::generateStats(stats_store_)}; + ClusterStatNames stat_names_{stats_store_.symbolTable()}; + ClusterStats stats_{ClusterInfoImpl::generateStats(stats_store_, stat_names_)}; NiceMock runtime_; Random::RandomGeneratorImpl random_; envoy::config::cluster::v3::Cluster::CommonLbConfig common_config_; diff --git a/test/common/upstream/load_balancer_fuzz_base.h b/test/common/upstream/load_balancer_fuzz_base.h index 210eae065008..bc069cca8491 100644 --- a/test/common/upstream/load_balancer_fuzz_base.h +++ b/test/common/upstream/load_balancer_fuzz_base.h @@ -18,7 +18,9 @@ namespace Upstream { // the subsequent updates to those sets. class LoadBalancerFuzzBase { public: - LoadBalancerFuzzBase() : stats_(ClusterInfoImpl::generateStats(stats_store_)){}; + LoadBalancerFuzzBase() + : stat_names_(stats_store_.symbolTable()), + stats_(ClusterInfoImpl::generateStats(stats_store_, stat_names_)){}; // Initializes load balancer components shared amongst every load balancer, random_, and // priority_set_ @@ -38,6 +40,7 @@ class LoadBalancerFuzzBase { // These public objects shared amongst all types of load balancers will be used to construct load // balancers in specific load balancer fuzz classes Stats::IsolatedStoreImpl stats_store_; + ClusterStatNames stat_names_; ClusterStats stats_; NiceMock runtime_; Random::PsuedoRandomGenerator64 random_; diff --git a/test/common/upstream/load_balancer_impl_test.cc b/test/common/upstream/load_balancer_impl_test.cc index 8597b952117a..63f981cd7ab6 100644 --- a/test/common/upstream/load_balancer_impl_test.cc +++ b/test/common/upstream/load_balancer_impl_test.cc @@ -40,11 +40,14 @@ class LoadBalancerTestBase : public Event::TestUsingSimulatedTime, // all the load balancers have equivalent functionality for failover host sets. MockHostSet& hostSet() { return GetParam() ? host_set_ : failover_host_set_; } - LoadBalancerTestBase() : stats_(ClusterInfoImpl::generateStats(stats_store_)) { + LoadBalancerTestBase() + : stat_names_(stats_store_.symbolTable()), + stats_(ClusterInfoImpl::generateStats(stats_store_, stat_names_)) { least_request_lb_config_.mutable_choice_count()->set_value(2); } Stats::IsolatedStoreImpl stats_store_; + ClusterStatNames stat_names_; ClusterStats stats_; NiceMock runtime_; NiceMock random_; diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index 84988675596c..ef431232f63b 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -70,7 +70,8 @@ TEST(DISABLED_LeastRequestLoadBalancerWeightTest, Weight) { {}, hosts, {}, absl::nullopt); Stats::IsolatedStoreImpl stats_store; - ClusterStats stats{ClusterInfoImpl::generateStats(stats_store)}; + ClusterStatNames stat_names(stats_store.symbolTable()); + ClusterStats stats{ClusterInfoImpl::generateStats(stats_store, stat_names)}; stats.max_host_weight_.set(weight); NiceMock runtime; Random::RandomGeneratorImpl random; @@ -104,7 +105,9 @@ TEST(DISABLED_LeastRequestLoadBalancerWeightTest, Weight) { */ class DISABLED_SimulationTest : public testing::Test { public: - DISABLED_SimulationTest() : stats_(ClusterInfoImpl::generateStats(stats_store_)) { + DISABLED_SimulationTest() + : stat_names_(stats_store_.symbolTable()), + stats_(ClusterInfoImpl::generateStats(stats_store_, stat_names_)) { ON_CALL(runtime_.snapshot_, getInteger("upstream.healthy_panic_threshold", 50U)) .WillByDefault(Return(50U)); ON_CALL(runtime_.snapshot_, featureEnabled("upstream.zone_routing.enabled", 100)) @@ -242,6 +245,7 @@ class DISABLED_SimulationTest : public testing::Test { NiceMock time_source_; Random::RandomGeneratorImpl random_; Stats::IsolatedStoreImpl stats_store_; + ClusterStatNames stat_names_; ClusterStats stats_; envoy::config::cluster::v3::Cluster::CommonLbConfig common_config_; }; diff --git a/test/common/upstream/logical_dns_cluster_test.cc b/test/common/upstream/logical_dns_cluster_test.cc index d3b74b73a7f5..db1511775067 100644 --- a/test/common/upstream/logical_dns_cluster_test.cc +++ b/test/common/upstream/logical_dns_cluster_test.cc @@ -193,7 +193,7 @@ class LogicalDnsClusterTest : public Event::TestUsingSimulatedTime, public testi tls_.shutdownThread(); } - Stats::IsolatedStoreImpl stats_store_; + Stats::TestUtil::TestStore stats_store_; Ssl::MockContextManager ssl_context_manager_; std::shared_ptr> dns_resolver_{ new NiceMock}; diff --git a/test/common/upstream/maglev_lb_test.cc b/test/common/upstream/maglev_lb_test.cc index da01022d893f..3204f7048e66 100644 --- a/test/common/upstream/maglev_lb_test.cc +++ b/test/common/upstream/maglev_lb_test.cc @@ -42,7 +42,9 @@ class TestLoadBalancerContext : public LoadBalancerContextBase { // functionality is covered here. class MaglevLoadBalancerTest : public Event::TestUsingSimulatedTime, public testing::Test { public: - MaglevLoadBalancerTest() : stats_(ClusterInfoImpl::generateStats(stats_store_)) {} + MaglevLoadBalancerTest() + : stat_names_(stats_store_.symbolTable()), + stats_(ClusterInfoImpl::generateStats(stats_store_, stat_names_)) {} void createLb() { lb_ = std::make_unique(priority_set_, stats_, stats_store_, runtime_, @@ -61,6 +63,7 @@ class MaglevLoadBalancerTest : public Event::TestUsingSimulatedTime, public test MockHostSet& host_set_ = *priority_set_.getMockHostSet(0); std::shared_ptr info_{new NiceMock()}; Stats::IsolatedStoreImpl stats_store_; + ClusterStatNames stat_names_; ClusterStats stats_; absl::optional config_; envoy::config::cluster::v3::Cluster::CommonLbConfig common_config_; diff --git a/test/common/upstream/original_dst_cluster_test.cc b/test/common/upstream/original_dst_cluster_test.cc index fe9028141e60..0306e583ed89 100644 --- a/test/common/upstream/original_dst_cluster_test.cc +++ b/test/common/upstream/original_dst_cluster_test.cc @@ -92,7 +92,7 @@ class OriginalDstClusterTest : public Event::TestUsingSimulatedTime, public test cluster_->initialize([&]() -> void { initialized_.ready(); }); } - Stats::IsolatedStoreImpl stats_store_; + Stats::TestUtil::TestStore stats_store_; Ssl::MockContextManager ssl_context_manager_; OriginalDstClusterSharedPtr cluster_; ReadyWatcher membership_updated_; diff --git a/test/common/upstream/ring_hash_lb_test.cc b/test/common/upstream/ring_hash_lb_test.cc index 2da9634bab71..83824605a226 100644 --- a/test/common/upstream/ring_hash_lb_test.cc +++ b/test/common/upstream/ring_hash_lb_test.cc @@ -55,7 +55,9 @@ class TestLoadBalancerContext : public LoadBalancerContextBase { class RingHashLoadBalancerTest : public Event::TestUsingSimulatedTime, public testing::TestWithParam { public: - RingHashLoadBalancerTest() : stats_(ClusterInfoImpl::generateStats(stats_store_)) {} + RingHashLoadBalancerTest() + : stat_names_(stats_store_.symbolTable()), + stats_(ClusterInfoImpl::generateStats(stats_store_, stat_names_)) {} void init() { lb_ = std::make_unique(priority_set_, stats_, stats_store_, runtime_, @@ -72,6 +74,7 @@ class RingHashLoadBalancerTest : public Event::TestUsingSimulatedTime, MockHostSet& failover_host_set_ = *priority_set_.getMockHostSet(1); std::shared_ptr info_{new NiceMock()}; Stats::IsolatedStoreImpl stats_store_; + ClusterStatNames stat_names_; ClusterStats stats_; absl::optional config_; envoy::config::cluster::v3::Cluster::CommonLbConfig common_config_; diff --git a/test/common/upstream/subset_lb_test.cc b/test/common/upstream/subset_lb_test.cc index 41345a6d27a0..3ab29348bc9d 100644 --- a/test/common/upstream/subset_lb_test.cc +++ b/test/common/upstream/subset_lb_test.cc @@ -128,8 +128,8 @@ class SubsetLoadBalancerTest : public Event::TestUsingSimulatedTime, public testing::TestWithParam { public: SubsetLoadBalancerTest() - : scope_(stats_store_.createScope("testprefix")), - stats_(ClusterInfoImpl::generateStats(stats_store_)) { + : scope_(stats_store_.createScope("testprefix")), stat_names_(stats_store_.symbolTable()), + stats_(ClusterInfoImpl::generateStats(stats_store_, stat_names_)) { stats_.max_host_weight_.set(1UL); least_request_lb_config_.mutable_choice_count()->set_value(2); } @@ -477,6 +477,7 @@ class SubsetLoadBalancerTest : public Event::TestUsingSimulatedTime, NiceMock random_; Stats::IsolatedStoreImpl stats_store_; Stats::ScopePtr scope_; + ClusterStatNames stat_names_; ClusterStats stats_; PrioritySetImpl local_priority_set_; HostVectorSharedPtr local_hosts_; diff --git a/test/common/upstream/test_cluster_manager.h b/test/common/upstream/test_cluster_manager.h index 0c221529cb45..ea4fafa1bf53 100644 --- a/test/common/upstream/test_cluster_manager.h +++ b/test/common/upstream/test_cluster_manager.h @@ -167,10 +167,11 @@ class TestClusterManagerImpl : public ClusterManagerImpl { AccessLog::AccessLogManager& log_manager, Event::Dispatcher& main_thread_dispatcher, Server::Admin& admin, ProtobufMessage::ValidationContext& validation_context, Api::Api& api, - Http::Context& http_context, Grpc::Context& grpc_context) + Http::Context& http_context, Grpc::Context& grpc_context, + Router::Context& router_context) : ClusterManagerImpl(bootstrap, factory, stats, tls, runtime, local_info, log_manager, main_thread_dispatcher, admin, validation_context, api, http_context, - grpc_context) {} + grpc_context, router_context) {} std::map> activeClusters() { std::map> clusters; @@ -185,19 +186,17 @@ class TestClusterManagerImpl : public ClusterManagerImpl { // it with the right values at the right times. class MockedUpdatedClusterManagerImpl : public TestClusterManagerImpl { public: - MockedUpdatedClusterManagerImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, - ClusterManagerFactory& factory, Stats::Store& stats, - ThreadLocal::Instance& tls, Runtime::Loader& runtime, - const LocalInfo::LocalInfo& local_info, - AccessLog::AccessLogManager& log_manager, - Event::Dispatcher& main_thread_dispatcher, Server::Admin& admin, - ProtobufMessage::ValidationContext& validation_context, - Api::Api& api, MockLocalClusterUpdate& local_cluster_update, - MockLocalHostsRemoved& local_hosts_removed, - Http::Context& http_context, Grpc::Context& grpc_context) + MockedUpdatedClusterManagerImpl( + const envoy::config::bootstrap::v3::Bootstrap& bootstrap, ClusterManagerFactory& factory, + Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::Loader& runtime, + const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager, + Event::Dispatcher& main_thread_dispatcher, Server::Admin& admin, + ProtobufMessage::ValidationContext& validation_context, Api::Api& api, + MockLocalClusterUpdate& local_cluster_update, MockLocalHostsRemoved& local_hosts_removed, + Http::Context& http_context, Grpc::Context& grpc_context, Router::Context& router_context) : TestClusterManagerImpl(bootstrap, factory, stats, tls, runtime, local_info, log_manager, main_thread_dispatcher, admin, validation_context, api, http_context, - grpc_context), + grpc_context, router_context), local_cluster_update_(local_cluster_update), local_hosts_removed_(local_hosts_removed) {} protected: diff --git a/test/config_test/config_test.cc b/test/config_test/config_test.cc index 01dd62447612..c66bd6b583b1 100644 --- a/test/config_test/config_test.cc +++ b/test/config_test/config_test.cc @@ -93,8 +93,8 @@ class ConfigTest { server_.admin(), server_.runtime(), server_.stats(), server_.threadLocal(), server_.dnsResolver(), ssl_context_manager_, server_.dispatcher(), server_.localInfo(), server_.secretManager(), server_.messageValidationContext(), *api_, server_.httpContext(), - server_.grpcContext(), server_.accessLogManager(), server_.singletonManager(), - time_system_); + server_.grpcContext(), server_.routerContext(), server_.accessLogManager(), + server_.singletonManager(), time_system_); ON_CALL(server_, clusterManager()).WillByDefault(Invoke([&]() -> Upstream::ClusterManager& { return *main_config.clusterManager(); diff --git a/test/extensions/clusters/aggregate/BUILD b/test/extensions/clusters/aggregate/BUILD index 22c6ab2a47ba..68cee34d03e7 100644 --- a/test/extensions/clusters/aggregate/BUILD +++ b/test/extensions/clusters/aggregate/BUILD @@ -37,6 +37,7 @@ envoy_extension_cc_test( srcs = ["cluster_update_test.cc"], extension_name = "envoy.clusters.aggregate", deps = [ + "//source/common/router:context_lib", "//source/common/upstream:cluster_factory_lib", "//source/common/upstream:cluster_manager_lib", "//source/extensions/clusters/aggregate:cluster", diff --git a/test/extensions/clusters/aggregate/cluster_test.cc b/test/extensions/clusters/aggregate/cluster_test.cc index 12a26a187020..1d78f5e8779e 100644 --- a/test/extensions/clusters/aggregate/cluster_test.cc +++ b/test/extensions/clusters/aggregate/cluster_test.cc @@ -32,7 +32,9 @@ const std::string secondary_name("secondary"); class AggregateClusterTest : public Event::TestUsingSimulatedTime, public testing::Test { public: - AggregateClusterTest() : stats_(Upstream::ClusterInfoImpl::generateStats(stats_store_)) { + AggregateClusterTest() + : stat_names_(stats_store_.symbolTable()), + stats_(Upstream::ClusterInfoImpl::generateStats(stats_store_, stat_names_)) { ON_CALL(*primary_info_, name()).WillByDefault(ReturnRef(primary_name)); ON_CALL(*secondary_info_, name()).WillByDefault(ReturnRef(secondary_name)); } @@ -126,7 +128,7 @@ class AggregateClusterTest : public Event::TestUsingSimulatedTime, public testin ON_CALL(secondary_, loadBalancer()).WillByDefault(ReturnRef(secondary_load_balancer_)); } - Stats::IsolatedStoreImpl stats_store_; + Stats::TestUtil::TestStore stats_store_; Ssl::MockContextManager ssl_context_manager_; NiceMock cm_; NiceMock random_; @@ -142,6 +144,7 @@ class AggregateClusterTest : public Event::TestUsingSimulatedTime, public testin Upstream::ThreadAwareLoadBalancerPtr thread_aware_lb_; Upstream::LoadBalancerFactorySharedPtr lb_factory_; Upstream::LoadBalancerPtr lb_; + Upstream::ClusterStatNames stat_names_; Upstream::ClusterStats stats_; std::shared_ptr primary_info_{ new NiceMock()}; diff --git a/test/extensions/clusters/aggregate/cluster_update_test.cc b/test/extensions/clusters/aggregate/cluster_update_test.cc index 71a013988fc0..853793ddfa60 100644 --- a/test/extensions/clusters/aggregate/cluster_update_test.cc +++ b/test/extensions/clusters/aggregate/cluster_update_test.cc @@ -2,6 +2,7 @@ #include "envoy/extensions/clusters/aggregate/v3/cluster.pb.h" #include "envoy/extensions/clusters/aggregate/v3/cluster.pb.validate.h" +#include "common/router/context_impl.h" #include "common/singleton/manager_impl.h" #include "common/upstream/cluster_factory_impl.h" #include "common/upstream/cluster_manager_impl.h" @@ -33,14 +34,15 @@ envoy::config::bootstrap::v3::Bootstrap parseBootstrapFromV2Yaml(const std::stri class AggregateClusterUpdateTest : public Event::TestUsingSimulatedTime, public testing::Test { public: AggregateClusterUpdateTest() - : http_context_(stats_store_.symbolTable()), grpc_context_(stats_store_.symbolTable()) {} + : http_context_(stats_store_.symbolTable()), grpc_context_(stats_store_.symbolTable()), + router_context_(stats_store_.symbolTable()) {} void initialize(const std::string& yaml_config) { auto bootstrap = parseBootstrapFromV2Yaml(yaml_config); cluster_manager_ = std::make_unique( bootstrap, factory_, factory_.stats_, factory_.tls_, factory_.runtime_, factory_.local_info_, log_manager_, factory_.dispatcher_, admin_, validation_context_, - *factory_.api_, http_context_, grpc_context_); + *factory_.api_, http_context_, grpc_context_, router_context_); cluster_manager_->initializeSecondaryClusters(bootstrap); EXPECT_EQ(cluster_manager_->activeClusters().size(), 1); cluster_ = cluster_manager_->getThreadLocalCluster("aggregate_cluster"); @@ -56,6 +58,7 @@ class AggregateClusterUpdateTest : public Event::TestUsingSimulatedTime, public AccessLog::MockAccessLogManager log_manager_; Http::ContextImpl http_context_; Grpc::ContextImpl grpc_context_; + Router::ContextImpl router_context_; const std::string default_yaml_config_ = R"EOF( static_resources: @@ -271,7 +274,7 @@ TEST_F(AggregateClusterUpdateTest, InitializeAggregateClusterAfterOtherClusters) cluster_manager_ = std::make_unique( bootstrap, factory_, factory_.stats_, factory_.tls_, factory_.runtime_, factory_.local_info_, log_manager_, factory_.dispatcher_, admin_, validation_context_, *factory_.api_, - http_context_, grpc_context_); + http_context_, grpc_context_, router_context_); cluster_manager_->initializeSecondaryClusters(bootstrap); EXPECT_EQ(cluster_manager_->activeClusters().size(), 2); cluster_ = cluster_manager_->getThreadLocalCluster("aggregate_cluster"); diff --git a/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc b/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc index 4bce356d487a..3bf37f32648c 100644 --- a/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc +++ b/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc @@ -108,7 +108,7 @@ class ClusterTest : public testing::Test, MOCK_METHOD(void, onMemberUpdateCb, (const Upstream::HostVector& hosts_added, const Upstream::HostVector& hosts_removed)); - Stats::IsolatedStoreImpl stats_store_; + Stats::TestUtil::TestStore stats_store_; Ssl::MockContextManager ssl_context_manager_; NiceMock cm_; NiceMock tls_; @@ -215,7 +215,7 @@ class ClusterFactoryTest : public testing::Test { } private: - Stats::IsolatedStoreImpl stats_store_; + Stats::TestUtil::TestStore stats_store_; NiceMock ssl_context_manager_; NiceMock cm_; NiceMock tls_; diff --git a/test/extensions/clusters/redis/redis_cluster_test.cc b/test/extensions/clusters/redis/redis_cluster_test.cc index 6b5845359069..508e1bf4d5b0 100644 --- a/test/extensions/clusters/redis/redis_cluster_test.cc +++ b/test/extensions/clusters/redis/redis_cluster_test.cc @@ -550,7 +550,7 @@ class RedisClusterTest : public testing::Test, EXPECT_CALL(active_dns_query_, cancel()); } - Stats::IsolatedStoreImpl stats_store_; + Stats::TestUtil::TestStore stats_store_; Ssl::MockContextManager ssl_context_manager_; std::shared_ptr> dns_resolver_{ new NiceMock}; diff --git a/test/mocks/router/router_filter_interface.cc b/test/mocks/router/router_filter_interface.cc index 81d9b8be1a34..f1fb2ab0518c 100644 --- a/test/mocks/router/router_filter_interface.cc +++ b/test/mocks/router/router_filter_interface.cc @@ -8,7 +8,8 @@ namespace Envoy { namespace Router { MockRouterFilterInterface::MockRouterFilterInterface() - : config_("prefix.", context_, ShadowWriterPtr(new MockShadowWriter()), router_proto) { + : pool_(*symbol_table_), config_(pool_.add("prefix"), context_, + ShadowWriterPtr(new MockShadowWriter()), router_proto) { auto cluster_info = new NiceMock(); cluster_info->timeout_budget_stats_ = nullptr; ON_CALL(*cluster_info, timeoutBudgetStats()).WillByDefault(Return(absl::nullopt)); diff --git a/test/mocks/router/router_filter_interface.h b/test/mocks/router/router_filter_interface.h index 40b6ac609b8e..3e8fbec51cac 100644 --- a/test/mocks/router/router_filter_interface.h +++ b/test/mocks/router/router_filter_interface.h @@ -54,6 +54,8 @@ class MockRouterFilterInterface : public RouterFilterInterface { envoy::extensions::filters::http::router::v3::Router router_proto; NiceMock context_; + Stats::TestSymbolTable symbol_table_; + Stats::StatNamePool pool_; FilterConfig config_; Upstream::ClusterInfoConstSharedPtr cluster_info_; std::list requests_; diff --git a/test/mocks/server/BUILD b/test/mocks/server/BUILD index 84fe48578be9..1ab093a3b698 100644 --- a/test/mocks/server/BUILD +++ b/test/mocks/server/BUILD @@ -182,6 +182,7 @@ envoy_cc_mock( "//include/envoy/server:instance_interface", "//source/common/grpc:context_lib", "//source/common/http:context_lib", + "//source/common/router:context_lib", "//source/common/secret:secret_manager_impl_lib", "//source/common/singleton:manager_impl_lib", "//source/common/stats:stats_lib", @@ -224,6 +225,7 @@ envoy_cc_mock( srcs = ["factory_context.cc"], hdrs = ["factory_context.h"], deps = [ + "//source/common/router:context_lib", "//test/mocks/server:drain_manager_mocks", "//test/mocks/server:instance_mocks", "//test/mocks/server:overload_manager_mocks", @@ -278,6 +280,7 @@ envoy_cc_mock( hdrs = ["filter_chain_factory_context.h"], deps = [ "//include/envoy/server:filter_config_interface", + "//source/common/router:context_lib", "//test/mocks/server:factory_context_mocks", ], ) diff --git a/test/mocks/server/factory_context.cc b/test/mocks/server/factory_context.cc index b02076911f4f..723019095c70 100644 --- a/test/mocks/server/factory_context.cc +++ b/test/mocks/server/factory_context.cc @@ -15,7 +15,8 @@ using ::testing::ReturnRef; MockFactoryContext::MockFactoryContext() : singleton_manager_(new Singleton::ManagerImpl(Thread::threadFactoryForTest())), - grpc_context_(scope_.symbolTable()), http_context_(scope_.symbolTable()) { + grpc_context_(scope_.symbolTable()), http_context_(scope_.symbolTable()), + router_context_(scope_.symbolTable()) { ON_CALL(*this, getServerFactoryContext()).WillByDefault(ReturnRef(server_factory_context_)); ON_CALL(*this, accessLogManager()).WillByDefault(ReturnRef(access_log_manager_)); ON_CALL(*this, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); diff --git a/test/mocks/server/factory_context.h b/test/mocks/server/factory_context.h index d8be7913563a..50c8e8c97e21 100644 --- a/test/mocks/server/factory_context.h +++ b/test/mocks/server/factory_context.h @@ -2,6 +2,8 @@ #include "envoy/server/configuration.h" +#include "common/router/context_impl.h" + #include "extensions/transport_sockets/tls/context_manager_impl.h" #include "admin.h" @@ -43,6 +45,7 @@ class MockFactoryContext : public virtual FactoryContext { Event::TestTimeSystem& timeSystem() { return time_system_; } Grpc::Context& grpcContext() override { return grpc_context_; } Http::Context& httpContext() override { return http_context_; } + Router::Context& routerContext() override { return router_context_; } MOCK_METHOD(ProcessContextOptRef, processContext, ()); MOCK_METHOD(ProtobufMessage::ValidationContext&, messageValidationContext, ()); MOCK_METHOD(ProtobufMessage::ValidationVisitor&, messageValidationVisitor, ()); @@ -68,6 +71,7 @@ class MockFactoryContext : public virtual FactoryContext { testing::NiceMock overload_manager_; Grpc::ContextImpl grpc_context_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; testing::NiceMock api_; }; } // namespace Configuration diff --git a/test/mocks/server/instance.cc b/test/mocks/server/instance.cc index f89bb4e31d19..5679749d3f6a 100644 --- a/test/mocks/server/instance.cc +++ b/test/mocks/server/instance.cc @@ -16,6 +16,7 @@ MockInstance::MockInstance() cluster_manager_(timeSource()), ssl_context_manager_(timeSource()), singleton_manager_(new Singleton::ManagerImpl(Thread::threadFactoryForTest())), grpc_context_(stats_store_.symbolTable()), http_context_(stats_store_.symbolTable()), + router_context_(stats_store_.symbolTable()), server_factory_context_( std::make_shared>()), transport_socket_factory_context_( @@ -24,6 +25,7 @@ MockInstance::MockInstance() ON_CALL(*this, stats()).WillByDefault(ReturnRef(stats_store_)); ON_CALL(*this, grpcContext()).WillByDefault(ReturnRef(grpc_context_)); ON_CALL(*this, httpContext()).WillByDefault(ReturnRef(http_context_)); + ON_CALL(*this, routerContext()).WillByDefault(ReturnRef(router_context_)); ON_CALL(*this, dnsResolver()).WillByDefault(Return(dns_resolver_)); ON_CALL(*this, api()).WillByDefault(ReturnRef(api_)); ON_CALL(*this, admin()).WillByDefault(ReturnRef(admin_)); @@ -54,7 +56,7 @@ namespace Configuration { MockServerFactoryContext::MockServerFactoryContext() : singleton_manager_(new Singleton::ManagerImpl(Thread::threadFactoryForTest())), - grpc_context_(scope_.symbolTable()) { + grpc_context_(scope_.symbolTable()), router_context_(scope_.symbolTable()) { ON_CALL(*this, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); ON_CALL(*this, dispatcher()).WillByDefault(ReturnRef(dispatcher_)); ON_CALL(*this, drainDecision()).WillByDefault(ReturnRef(drain_manager_)); diff --git a/test/mocks/server/instance.h b/test/mocks/server/instance.h index cf9f8bf3e885..d5f2b5e67b84 100644 --- a/test/mocks/server/instance.h +++ b/test/mocks/server/instance.h @@ -4,6 +4,7 @@ #include "common/grpc/context_impl.h" #include "common/http/context_impl.h" +#include "common/router/context_impl.h" #include "common/stats/symbol_table_impl.h" #include "extensions/transport_sockets/tls/context_manager_impl.h" @@ -75,6 +76,7 @@ class MockInstance : public Instance { MOCK_METHOD(Stats::Store&, stats, ()); MOCK_METHOD(Grpc::Context&, grpcContext, ()); MOCK_METHOD(Http::Context&, httpContext, ()); + MOCK_METHOD(Router::Context&, routerContext, ()); MOCK_METHOD(ProcessContextOptRef, processContext, ()); MOCK_METHOD(ThreadLocal::Instance&, threadLocal, ()); MOCK_METHOD(const LocalInfo::LocalInfo&, localInfo, (), (const)); @@ -115,6 +117,7 @@ class MockInstance : public Instance { Singleton::ManagerPtr singleton_manager_; Grpc::ContextImpl grpc_context_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; testing::NiceMock validation_context_; std::shared_ptr> server_factory_context_; @@ -143,6 +146,7 @@ class MockServerFactoryContext : public virtual ServerFactoryContext { MOCK_METHOD(ProtobufMessage::ValidationVisitor&, messageValidationVisitor, ()); MOCK_METHOD(Api::Api&, api, ()); Grpc::Context& grpcContext() override { return grpc_context_; } + Router::Context& routerContext() override { return router_context_; } MOCK_METHOD(Server::DrainManager&, drainManager, ()); MOCK_METHOD(Init::Manager&, initManager, ()); MOCK_METHOD(ServerLifecycleNotifier&, lifecycleNotifier, ()); @@ -161,6 +165,7 @@ class MockServerFactoryContext : public virtual ServerFactoryContext { Event::GlobalTimeSystem time_system_; testing::NiceMock api_; Grpc::ContextImpl grpc_context_; + Router::ContextImpl router_context_; }; } // namespace Configuration } // namespace Server diff --git a/test/mocks/server/listener_factory_context.cc b/test/mocks/server/listener_factory_context.cc index 054ffa49dbbe..10ec7dc48156 100644 --- a/test/mocks/server/listener_factory_context.cc +++ b/test/mocks/server/listener_factory_context.cc @@ -15,7 +15,8 @@ using ::testing::ReturnRef; MockListenerFactoryContext::MockListenerFactoryContext() : singleton_manager_(new Singleton::ManagerImpl(Thread::threadFactoryForTest())), - grpc_context_(scope_.symbolTable()), http_context_(scope_.symbolTable()) { + grpc_context_(scope_.symbolTable()), http_context_(scope_.symbolTable()), + router_context_(scope_.symbolTable()) { ON_CALL(*this, getServerFactoryContext()).WillByDefault(ReturnRef(server_factory_context_)); ON_CALL(*this, accessLogManager()).WillByDefault(ReturnRef(access_log_manager_)); ON_CALL(*this, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); diff --git a/test/mocks/server/listener_factory_context.h b/test/mocks/server/listener_factory_context.h index 12723f28996f..5e7e6de00ac3 100644 --- a/test/mocks/server/listener_factory_context.h +++ b/test/mocks/server/listener_factory_context.h @@ -46,6 +46,7 @@ class MockListenerFactoryContext : public ListenerFactoryContext { Event::TestTimeSystem& timeSystem() { return time_system_; } Grpc::Context& grpcContext() override { return grpc_context_; } Http::Context& httpContext() override { return http_context_; } + Router::Context& routerContext() override { return router_context_; } MOCK_METHOD(ProcessContextOptRef, processContext, ()); MOCK_METHOD(ProtobufMessage::ValidationContext&, messageValidationContext, ()); MOCK_METHOD(ProtobufMessage::ValidationVisitor&, messageValidationVisitor, ()); @@ -71,6 +72,7 @@ class MockListenerFactoryContext : public ListenerFactoryContext { testing::NiceMock overload_manager_; Grpc::ContextImpl grpc_context_; Http::ContextImpl http_context_; + Router::ContextImpl router_context_; testing::NiceMock api_; Network::MockListenerConfig listener_config_; diff --git a/test/mocks/stats/BUILD b/test/mocks/stats/BUILD index 55b3c0a19474..2fbabbb328d0 100644 --- a/test/mocks/stats/BUILD +++ b/test/mocks/stats/BUILD @@ -24,6 +24,5 @@ envoy_cc_mock( "//source/common/stats:timespan_lib", "//test/common/stats:stat_test_utility_lib", "//test/mocks:common_lib", - "//test/test_common:global_lib", ], ) diff --git a/test/mocks/stats/mocks.cc b/test/mocks/stats/mocks.cc index cd5e01fb5b0c..6af79f074331 100644 --- a/test/mocks/stats/mocks.cc +++ b/test/mocks/stats/mocks.cc @@ -70,7 +70,7 @@ MockMetricSnapshot::~MockMetricSnapshot() = default; MockSink::MockSink() = default; MockSink::~MockSink() = default; -MockStore::MockStore() : TestUtil::TestStore(*global_symbol_table_) { +MockStore::MockStore() { ON_CALL(*this, counter(_)).WillByDefault(ReturnRef(counter_)); ON_CALL(*this, histogram(_, _)) .WillByDefault(Invoke([this](const std::string& name, Histogram::Unit unit) -> Histogram& { @@ -89,7 +89,7 @@ MockStore::MockStore() : TestUtil::TestStore(*global_symbol_table_) { } MockStore::~MockStore() = default; -MockIsolatedStatsStore::MockIsolatedStatsStore() : TestUtil::TestStore(*global_symbol_table_) {} +MockIsolatedStatsStore::MockIsolatedStatsStore() = default; MockIsolatedStatsStore::~MockIsolatedStatsStore() = default; MockStatsMatcher::MockStatsMatcher() = default; diff --git a/test/mocks/stats/mocks.h b/test/mocks/stats/mocks.h index ba12c326c33d..1970354d7bc3 100644 --- a/test/mocks/stats/mocks.h +++ b/test/mocks/stats/mocks.h @@ -21,31 +21,12 @@ #include "common/stats/timespan_impl.h" #include "test/common/stats/stat_test_utility.h" -#include "test/test_common/global.h" #include "gmock/gmock.h" namespace Envoy { namespace Stats { -class TestSymbolTableHelper { -public: - SymbolTable& symbolTable() { return symbol_table_; } - const SymbolTable& constSymbolTable() const { return symbol_table_; } - -private: - SymbolTableImpl symbol_table_; -}; - -class TestSymbolTable { -public: - SymbolTable& operator*() { return global_.get().symbolTable(); } - const SymbolTable& operator*() const { return global_.get().constSymbolTable(); } - SymbolTable* operator->() { return &global_.get().symbolTable(); } - const SymbolTable* operator->() const { return &global_.get().constSymbolTable(); } - Envoy::Test::Global global_; -}; - template class MockMetric : public BaseClass { public: MockMetric() : name_(*this), tag_pool_(*symbol_table_) {} @@ -298,12 +279,7 @@ class MockSink : public Sink { MOCK_METHOD(void, onHistogramComplete, (const Histogram& histogram, uint64_t value)); }; -class SymbolTableProvider { -public: - TestSymbolTable global_symbol_table_; -}; - -class MockStore : public SymbolTableProvider, public TestUtil::TestStore { +class MockStore : public TestUtil::TestStore { public: MockStore(); ~MockStore() override; @@ -357,7 +333,7 @@ class MockStore : public SymbolTableProvider, public TestUtil::TestStore { * With IsolatedStoreImpl it's hard to test timing stats. * MockIsolatedStatsStore mocks only deliverHistogramToSinks for better testing. */ -class MockIsolatedStatsStore : public SymbolTableProvider, public TestUtil::TestStore { +class MockIsolatedStatsStore : public TestUtil::TestStore { public: MockIsolatedStatsStore(); ~MockIsolatedStatsStore() override; diff --git a/test/mocks/upstream/BUILD b/test/mocks/upstream/BUILD index f249847bac2c..b7a3ceaaedf6 100644 --- a/test/mocks/upstream/BUILD +++ b/test/mocks/upstream/BUILD @@ -39,7 +39,6 @@ envoy_cc_mock( ":cluster_info_mocks", "//include/envoy/upstream:upstream_interface", "//source/common/network:utility_lib", - "//source/common/stats:stats_lib", "//test/mocks/network:transport_socket_mocks", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/data/cluster/v2alpha:pkg_cc_proto", @@ -53,7 +52,7 @@ envoy_cc_mock( deps = [ "//include/envoy/upstream:upstream_interface", "//source/common/network:raw_buffer_socket_lib", - "//source/common/stats:isolated_store_lib", + "//test/common/stats:stat_test_utility_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], ) diff --git a/test/mocks/upstream/cluster_info.cc b/test/mocks/upstream/cluster_info.cc index 87afe77c3014..635eac985354 100644 --- a/test/mocks/upstream/cluster_info.cc +++ b/test/mocks/upstream/cluster_info.cc @@ -39,7 +39,8 @@ MockIdleTimeEnabledClusterInfo::~MockIdleTimeEnabledClusterInfo() = default; MockClusterInfo::MockClusterInfo() : http2_options_(::Envoy::Http2::Utility::initializeAndValidateOptions( envoy::config::core::v3::Http2ProtocolOptions())), - stats_(ClusterInfoImpl::generateStats(stats_store_)), + stat_names_(stats_store_.symbolTable()), + stats_(ClusterInfoImpl::generateStats(stats_store_, stat_names_)), transport_socket_matcher_(new NiceMock()), load_report_stats_(ClusterInfoImpl::generateLoadReportStats(load_report_stats_store_)), request_response_size_stats_(std::make_unique( diff --git a/test/mocks/upstream/cluster_info.h b/test/mocks/upstream/cluster_info.h index 7e1427b2de03..0ff62d774c2e 100644 --- a/test/mocks/upstream/cluster_info.h +++ b/test/mocks/upstream/cluster_info.h @@ -156,6 +156,7 @@ class MockClusterInfo : public ClusterInfo { uint64_t max_requests_per_connection_{}; uint32_t max_response_headers_count_{Http::DEFAULT_MAX_HEADERS_COUNT}; NiceMock stats_store_; + ClusterStatNames stat_names_; ClusterStats stats_; Upstream::TransportSocketMatcherPtr transport_socket_matcher_; NiceMock load_report_stats_store_; diff --git a/test/mocks/upstream/cluster_manager.cc b/test/mocks/upstream/cluster_manager.cc index c78bffd50770..0adcadba2348 100644 --- a/test/mocks/upstream/cluster_manager.cc +++ b/test/mocks/upstream/cluster_manager.cc @@ -16,7 +16,7 @@ using ::testing::ReturnRef; MockClusterManager::MockClusterManager(TimeSource&) : MockClusterManager() {} -MockClusterManager::MockClusterManager() { +MockClusterManager::MockClusterManager() : cluster_stat_names_(*symbol_table_) { ON_CALL(*this, httpConnPoolForCluster(_, _, _, _)).WillByDefault(Return(&conn_pool_)); ON_CALL(*this, tcpConnPoolForCluster(_, _, _)).WillByDefault(Return(&tcp_conn_pool_)); ON_CALL(*this, httpAsyncClientForCluster(_)).WillByDefault(ReturnRef(async_client_)); diff --git a/test/mocks/upstream/cluster_manager.h b/test/mocks/upstream/cluster_manager.h index 347b481c74c4..1e583c456d2e 100644 --- a/test/mocks/upstream/cluster_manager.h +++ b/test/mocks/upstream/cluster_manager.h @@ -70,6 +70,7 @@ class MockClusterManager : public ClusterManager { MOCK_METHOD(ClusterUpdateCallbacksHandle*, addThreadLocalClusterUpdateCallbacks_, (ClusterUpdateCallbacks & callbacks)); MOCK_METHOD(Config::SubscriptionFactory&, subscriptionFactory, ()); + const ClusterStatNames& clusterStatNames() const override { return cluster_stat_names_; } NiceMock conn_pool_; NiceMock async_client_; @@ -83,6 +84,8 @@ class MockClusterManager : public ClusterManager { NiceMock subscription_factory_; absl::flat_hash_map> active_clusters_; absl::flat_hash_map> warming_clusters_; + Stats::TestSymbolTable symbol_table_; + ClusterStatNames cluster_stat_names_; }; } // namespace Upstream diff --git a/test/mocks/upstream/transport_socket_match.h b/test/mocks/upstream/transport_socket_match.h index 16c1fd9fec20..7638b83fc9cf 100644 --- a/test/mocks/upstream/transport_socket_match.h +++ b/test/mocks/upstream/transport_socket_match.h @@ -5,7 +5,7 @@ #include "envoy/config/core/v3/base.pb.h" #include "envoy/upstream/upstream.h" -#include "common/stats/isolated_store_impl.h" +#include "test/common/stats/stat_test_utility.h" #include "gmock/gmock.h" @@ -22,7 +22,7 @@ class MockTransportSocketMatcher : public TransportSocketMatcher { private: Network::TransportSocketFactoryPtr socket_factory_; - Stats::IsolatedStoreImpl stats_store_; + Stats::TestUtil::TestStore stats_store_; TransportSocketMatchStats stats_; }; diff --git a/test/server/config_validation/cluster_manager_test.cc b/test/server/config_validation/cluster_manager_test.cc index 1318d192f14f..bcc3accfe878 100644 --- a/test/server/config_validation/cluster_manager_test.cc +++ b/test/server/config_validation/cluster_manager_test.cc @@ -44,13 +44,14 @@ TEST(ValidationClusterManagerTest, MockedMethods) { NiceMock admin; Http::ContextImpl http_context(stats_store.symbolTable()); Grpc::ContextImpl grpc_context(stats_store.symbolTable()); + Router::ContextImpl router_context(stats_store.symbolTable()); AccessLog::MockAccessLogManager log_manager; Singleton::ManagerImpl singleton_manager{Thread::threadFactoryForTest()}; ValidationClusterManagerFactory factory( admin, runtime, stats_store, tls, dns_resolver, ssl_context_manager, dispatcher, local_info, - secret_manager, validation_context, *api, http_context, grpc_context, log_manager, - singleton_manager, time_system); + secret_manager, validation_context, *api, http_context, grpc_context, router_context, + log_manager, singleton_manager, time_system); const envoy::config::bootstrap::v3::Bootstrap bootstrap; ClusterManagerPtr cluster_manager = factory.clusterManagerFromProto(bootstrap); diff --git a/test/server/configuration_impl_test.cc b/test/server/configuration_impl_test.cc index 1c9781081f0b..3d993bdda820 100644 --- a/test/server/configuration_impl_test.cc +++ b/test/server/configuration_impl_test.cc @@ -65,8 +65,8 @@ class ConfigurationImplTest : public testing::Test { server_.admin(), server_.runtime(), server_.stats(), server_.threadLocal(), server_.dnsResolver(), server_.sslContextManager(), server_.dispatcher(), server_.localInfo(), server_.secretManager(), server_.messageValidationContext(), *api_, - server_.httpContext(), server_.grpcContext(), server_.accessLogManager(), - server_.singletonManager()) {} + server_.httpContext(), server_.grpcContext(), server_.routerContext(), + server_.accessLogManager(), server_.singletonManager()) {} void addStatsdFakeClusterConfig(envoy::config::metrics::v3::StatsSink& sink) { envoy::config::metrics::v3::StatsdSink statsd_sink; diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index 6b6d8d2e4690..f9a3cc2862f6 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -30,6 +30,7 @@ DSR HEXDIG HEXDIGIT OWS +STATNAME SkyWalking TIDs ceil