diff --git a/api/envoy/api/v2/route/route.proto b/api/envoy/api/v2/route/route.proto index 2f1337c9c58eb..7d6b382383e60 100644 --- a/api/envoy/api/v2/route/route.proto +++ b/api/envoy/api/v2/route/route.proto @@ -230,6 +230,10 @@ message Route { // Specifies a list of HTTP headers that should be removed from each response // to requests matching this route. repeated string response_headers_to_remove = 11; + + // Presence of the object defines whether the connection manager's tracing configuration + // is overridden by this route specific instance. + Tracing tracing = 15; } // Compared to the :ref:`cluster ` field that specifies a @@ -1007,6 +1011,34 @@ message Decorator { string operation = 1 [(validate.rules).string.min_bytes = 1]; } +message Tracing { + + // Target percentage of requests managed by this HTTP connection manager that will be force + // traced if the :ref:`x-client-trace-id ` + // header is set. This field is a direct analog for the runtime variable + // 'tracing.client_sampling' in the :ref:`HTTP Connection Manager + // `. + // Default: 100% + envoy.type.FractionalPercent client_sampling = 1; + + // Target percentage of requests managed by this HTTP connection manager that will be randomly + // selected for trace generation, if not requested by the client or not forced. This field is + // a direct analog for the runtime variable 'tracing.random_sampling' in the + // :ref:`HTTP Connection Manager `. + // Default: 100% + envoy.type.FractionalPercent random_sampling = 2; + + // Target percentage of requests managed by this HTTP connection manager that will be traced + // after all other sampling checks have been applied (client-directed, force tracing, random + // sampling). This field functions as an upper limit on the total configured sampling rate. For + // instance, setting client_sampling to 100% but overall_sampling to 1% will result in only 1% + // of client requests with the appropriate headers to be force traced. This field is a direct + // analog for the runtime variable 'tracing.global_enabled' in the + // :ref:`HTTP Connection Manager `. + // Default: 100% + envoy.type.FractionalPercent overall_sampling = 3; +} + // A virtual cluster is a way of specifying a regex matching rule against // certain important endpoints such that statistics are generated explicitly for // the matched requests. The reason this is useful is that when doing diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index 01013221d5608..421568a0e5444 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -45,6 +45,7 @@ Version history * server: ``--define manual_stamp=manual_stamp`` was added to allow server stamping outside of binary rules. more info in the `bazel docs `_. * tool: added :repo:`proto ` support for :ref:`router check tool ` tests. +* tracing: add trace sampling configuration to the route, to override the route level. * upstream: added :ref:`upstream_cx_pool_overflow ` for the connection pool circuit breaker. * upstream: an EDS management server can now force removal of a host that is still passing active health checking by first marking the host as failed via EDS health check and subsequently removing diff --git a/include/envoy/router/router.h b/include/envoy/router/router.h index c0bf0e81456b3..f0ad23da97db3 100644 --- a/include/envoy/router/router.h +++ b/include/envoy/router/router.h @@ -768,6 +768,34 @@ class Decorator { typedef std::unique_ptr DecoratorConstPtr; +/** + * An interface representing the Tracing for the route configuration. + */ +class RouteTracing { +public: + virtual ~RouteTracing() {} + + /** + * This method returns the client sampling percentage. + * @return the client sampling percentage + */ + virtual const envoy::type::FractionalPercent& getClientSampling() const PURE; + + /** + * This method returns the random sampling percentage. + * @return the random sampling percentage + */ + virtual const envoy::type::FractionalPercent& getRandomSampling() const PURE; + + /** + * This method returns the overall sampling percentage. + * @return the overall sampling percentage + */ + virtual const envoy::type::FractionalPercent& getOverallSampling() const PURE; +}; + +typedef std::unique_ptr RouteTracingConstPtr; + /** * An interface that holds a DirectResponseEntry or RouteEntry for a request. */ @@ -790,6 +818,11 @@ class Route { */ virtual const Decorator* decorator() const PURE; + /** + * @return the tracing config or nullptr if not defined for the request. + */ + virtual const RouteTracing* tracingConfig() const PURE; + /** * @return const RouteSpecificFilterConfig* the per-filter config pre-processed object for * the given filter name. If there is not per-filter config, or the filter factory returns diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h index 11bfea5a7e085..8beae3707065c 100644 --- a/source/common/http/async_client_impl.h +++ b/source/common/http/async_client_impl.h @@ -270,6 +270,7 @@ class AsyncStreamImpl : public AsyncClient::Stream, const Router::DirectResponseEntry* directResponseEntry() const override { return nullptr; } const Router::RouteEntry* routeEntry() const override { return &route_entry_; } const Router::Decorator* decorator() const override { return nullptr; } + const Router::RouteTracing* tracingConfig() const override { return nullptr; } const Router::RouteSpecificFilterConfig* perFilterConfig(const std::string&) const override { return nullptr; } diff --git a/source/common/http/conn_manager_config.h b/source/common/http/conn_manager_config.h index 2fb4ee9e9c575..599db30f36bbd 100644 --- a/source/common/http/conn_manager_config.h +++ b/source/common/http/conn_manager_config.h @@ -106,9 +106,9 @@ struct ConnectionManagerTracingStats { struct TracingConnectionManagerConfig { Tracing::OperationName operation_name_; std::vector request_headers_for_tags_; - uint64_t client_sampling_; - uint64_t random_sampling_; - uint64_t overall_sampling_; + envoy::type::FractionalPercent client_sampling_; + envoy::type::FractionalPercent random_sampling_; + envoy::type::FractionalPercent overall_sampling_; bool verbose_; }; diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc index 12dce494f3698..657bb4802ef6a 100644 --- a/source/common/http/conn_manager_impl.cc +++ b/source/common/http/conn_manager_impl.cc @@ -708,12 +708,19 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(HeaderMapPtr&& headers, stream_info_.setDownstreamRemoteAddress(ConnectionManagerUtility::mutateRequestHeaders( *request_headers_, connection_manager_.read_callbacks_->connection(), connection_manager_.config_, *snapped_route_config_, connection_manager_.random_generator_, - connection_manager_.runtime_, connection_manager_.local_info_)); + connection_manager_.local_info_)); } ASSERT(stream_info_.downstreamRemoteAddress() != nullptr); ASSERT(!cached_route_); refreshCachedRoute(); + + if (!state_.is_internally_created_) { // Only mutate tracing headers on first pass. + ConnectionManagerUtility::mutateTracingRequestHeader( + *request_headers_, connection_manager_.runtime_, connection_manager_.config_, + cached_route_.value().get()); + } + const bool upgrade_rejected = createFilterChain() == false; // TODO if there are no filters when starting a filter iteration, the connection manager diff --git a/source/common/http/conn_manager_utility.cc b/source/common/http/conn_manager_utility.cc index c6d1fbf7e8948..5c8d31fa21bef 100644 --- a/source/common/http/conn_manager_utility.cc +++ b/source/common/http/conn_manager_utility.cc @@ -52,7 +52,7 @@ ServerConnectionPtr ConnectionManagerUtility::autoCreateCodec( Network::Address::InstanceConstSharedPtr ConnectionManagerUtility::mutateRequestHeaders( HeaderMap& request_headers, Network::Connection& connection, ConnectionManagerConfig& config, - const Router::Config& route_config, Runtime::RandomGenerator& random, Runtime::Loader& runtime, + const Router::Config& route_config, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info) { // If this is a Upgrade request, do not remove the Connection and Upgrade headers, // as we forward them verbatim to the upstream hosts. @@ -213,7 +213,6 @@ Network::Address::InstanceConstSharedPtr ConnectionManagerUtility::mutateRequest request_headers.insertRequestId().value(uuid); } - mutateTracingRequestHeader(request_headers, runtime, config); mutateXfccRequestHeader(request_headers, connection, config); return final_remote_address; @@ -221,7 +220,8 @@ Network::Address::InstanceConstSharedPtr ConnectionManagerUtility::mutateRequest void ConnectionManagerUtility::mutateTracingRequestHeader(HeaderMap& request_headers, Runtime::Loader& runtime, - ConnectionManagerConfig& config) { + ConnectionManagerConfig& config, + const Router::Route* route) { if (!config.tracingConfig() || !request_headers.RequestId()) { return; } @@ -234,23 +234,31 @@ void ConnectionManagerUtility::mutateTracingRequestHeader(HeaderMap& request_hea return; } + const envoy::type::FractionalPercent* client_sampling = &config.tracingConfig()->client_sampling_; + const envoy::type::FractionalPercent* random_sampling = &config.tracingConfig()->random_sampling_; + const envoy::type::FractionalPercent* overall_sampling = + &config.tracingConfig()->overall_sampling_; + + if (route && route->tracingConfig()) { + client_sampling = &route->tracingConfig()->getClientSampling(); + random_sampling = &route->tracingConfig()->getRandomSampling(); + overall_sampling = &route->tracingConfig()->getOverallSampling(); + } + // Do not apply tracing transformations if we are currently tracing. if (UuidTraceStatus::NoTrace == UuidUtils::isTraceableUuid(x_request_id)) { if (request_headers.ClientTraceId() && - runtime.snapshot().featureEnabled("tracing.client_enabled", - config.tracingConfig()->client_sampling_)) { + runtime.snapshot().featureEnabled("tracing.client_enabled", *client_sampling)) { UuidUtils::setTraceableUuid(x_request_id, UuidTraceStatus::Client); } else if (request_headers.EnvoyForceTrace()) { UuidUtils::setTraceableUuid(x_request_id, UuidTraceStatus::Forced); - } else if (runtime.snapshot().featureEnabled("tracing.random_sampling", - config.tracingConfig()->random_sampling_, result, - 10000)) { + } else if (runtime.snapshot().featureEnabled("tracing.random_sampling", *random_sampling, + result)) { UuidUtils::setTraceableUuid(x_request_id, UuidTraceStatus::Sampled); } } - if (!runtime.snapshot().featureEnabled("tracing.global_enabled", - config.tracingConfig()->overall_sampling_, result)) { + if (!runtime.snapshot().featureEnabled("tracing.global_enabled", *overall_sampling, result)) { UuidUtils::setTraceableUuid(x_request_id, UuidTraceStatus::NoTrace); } diff --git a/source/common/http/conn_manager_utility.h b/source/common/http/conn_manager_utility.h index 126982df77533..802d0ef07addb 100644 --- a/source/common/http/conn_manager_utility.h +++ b/source/common/http/conn_manager_utility.h @@ -53,8 +53,7 @@ class ConnectionManagerUtility { static Network::Address::InstanceConstSharedPtr mutateRequestHeaders(HeaderMap& request_headers, Network::Connection& connection, ConnectionManagerConfig& config, const Router::Config& route_config, - Runtime::RandomGenerator& random, Runtime::Loader& runtime, - const LocalInfo::LocalInfo& local_info); + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info); static void mutateResponseHeaders(HeaderMap& response_headers, const HeaderMap* request_headers, const std::string& via); @@ -64,13 +63,14 @@ class ConnectionManagerUtility { // Return false if error happens during the sanitization. static bool maybeNormalizePath(HeaderMap& request_headers, const ConnectionManagerConfig& config); -private: /** * Mutate request headers if request needs to be traced. */ static void mutateTracingRequestHeader(HeaderMap& request_headers, Runtime::Loader& runtime, - ConnectionManagerConfig& config); + ConnectionManagerConfig& config, + const Router::Route* route); +private: static void mutateXfccRequestHeader(HeaderMap& request_headers, Network::Connection& connection, ConnectionManagerConfig& config); }; diff --git a/source/common/router/config_impl.cc b/source/common/router/config_impl.cc index c08cc03234026..e33a4df0d4aef 100644 --- a/source/common/router/config_impl.cc +++ b/source/common/router/config_impl.cc @@ -324,6 +324,39 @@ void DecoratorImpl::apply(Tracing::Span& span) const { const std::string& DecoratorImpl::getOperation() const { return operation_; } +RouteTracingImpl::RouteTracingImpl(const envoy::api::v2::route::Tracing& tracing) { + if (!tracing.has_client_sampling()) { + client_sampling_.set_numerator(100); + client_sampling_.set_denominator(envoy::type::FractionalPercent::HUNDRED); + } else { + client_sampling_ = tracing.client_sampling(); + } + if (!tracing.has_random_sampling()) { + random_sampling_.set_numerator(100); + random_sampling_.set_denominator(envoy::type::FractionalPercent::HUNDRED); + } else { + random_sampling_ = tracing.random_sampling(); + } + if (!tracing.has_overall_sampling()) { + overall_sampling_.set_numerator(100); + overall_sampling_.set_denominator(envoy::type::FractionalPercent::HUNDRED); + } else { + overall_sampling_ = tracing.overall_sampling(); + } +} + +const envoy::type::FractionalPercent& RouteTracingImpl::getClientSampling() const { + return client_sampling_; +} + +const envoy::type::FractionalPercent& RouteTracingImpl::getRandomSampling() const { + return random_sampling_; +} + +const envoy::type::FractionalPercent& RouteTracingImpl::getOverallSampling() const { + return overall_sampling_; +} + RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, const envoy::api::v2::route::Route& route, Server::Configuration::FactoryContext& factory_context) @@ -360,7 +393,7 @@ RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, route.response_headers_to_remove())), metadata_(route.metadata()), typed_metadata_(route.metadata()), match_grpc_(route.match().has_grpc()), opaque_config_(parseOpaqueConfig(route)), - decorator_(parseDecorator(route)), + decorator_(parseDecorator(route)), route_tracing_(parseRouteTracing(route)), direct_response_code_(ConfigUtility::parseDirectResponseCode(route)), direct_response_body_(ConfigUtility::parseDirectResponseBody(route, factory_context.api())), per_filter_configs_(route.typed_per_filter_config(), route.per_filter_config(), @@ -667,6 +700,15 @@ DecoratorConstPtr RouteEntryImplBase::parseDecorator(const envoy::api::v2::route return ret; } +RouteTracingConstPtr +RouteEntryImplBase::parseRouteTracing(const envoy::api::v2::route::Route& route) { + RouteTracingConstPtr ret; + if (route.has_tracing()) { + ret = RouteTracingConstPtr(new RouteTracingImpl(route.tracing())); + } + return ret; +} + const DirectResponseEntry* RouteEntryImplBase::directResponseEntry() const { // A route for a request can exclusively be a route entry, a direct response entry, // or a redirect entry. diff --git a/source/common/router/config_impl.h b/source/common/router/config_impl.h index 9829dbcca3a57..acc360c663d72 100644 --- a/source/common/router/config_impl.h +++ b/source/common/router/config_impl.h @@ -87,6 +87,7 @@ class SslRedirectRoute : public Route { const DirectResponseEntry* directResponseEntry() const override { return &SSL_REDIRECTOR; } const RouteEntry* routeEntry() const override { return nullptr; } const Decorator* decorator() const override { return nullptr; } + const RouteTracing* tracingConfig() const override { return nullptr; } const RouteSpecificFilterConfig* perFilterConfig(const std::string&) const override { return nullptr; } @@ -346,6 +347,28 @@ class DecoratorImpl : public Decorator { const std::string operation_; }; +/** + * Implementation of RouteTracing that reads from the proto route tracing. + */ +class RouteTracingImpl : public RouteTracing { +public: + RouteTracingImpl(const envoy::api::v2::route::Tracing& tracing); + + // Tracing::getClientSampling + const envoy::type::FractionalPercent& getClientSampling() const override; + + // Tracing::getRandomSampling + const envoy::type::FractionalPercent& getRandomSampling() const override; + + // Tracing::getOverallSampling + const envoy::type::FractionalPercent& getOverallSampling() const override; + +private: + envoy::type::FractionalPercent client_sampling_; + envoy::type::FractionalPercent random_sampling_; + envoy::type::FractionalPercent overall_sampling_; +}; + /** * Base implementation for all route entries. */ @@ -436,6 +459,7 @@ class RouteEntryImplBase : public RouteEntry, const DirectResponseEntry* directResponseEntry() const override; const RouteEntry* routeEntry() const override; const Decorator* decorator() const override { return decorator_.get(); } + const RouteTracing* tracingConfig() const override { return route_tracing_.get(); } const RouteSpecificFilterConfig* perFilterConfig(const std::string&) const override; protected: @@ -535,6 +559,7 @@ class RouteEntryImplBase : public RouteEntry, const DirectResponseEntry* directResponseEntry() const override { return nullptr; } const RouteEntry* routeEntry() const override { return this; } const Decorator* decorator() const override { return parent_->decorator(); } + const RouteTracing* tracingConfig() const override { return parent_->tracingConfig(); } const RouteSpecificFilterConfig* perFilterConfig(const std::string& name) const override { return parent_->perFilterConfig(name); @@ -600,6 +625,8 @@ class RouteEntryImplBase : public RouteEntry, static DecoratorConstPtr parseDecorator(const envoy::api::v2::route::Route& route); + static RouteTracingConstPtr parseRouteTracing(const envoy::api::v2::route::Route& route); + bool evaluateRuntimeMatch(const uint64_t random_value) const; HedgePolicyImpl @@ -656,6 +683,7 @@ class RouteEntryImplBase : public RouteEntry, const std::multimap opaque_config_; const DecoratorConstPtr decorator_; + const RouteTracingConstPtr route_tracing_; const absl::optional direct_response_code_; std::string direct_response_body_; PerFilterConfigs per_filter_configs_; diff --git a/source/extensions/filters/network/http_connection_manager/config.cc b/source/extensions/filters/network/http_connection_manager/config.cc index 92cce54bd3092..b975d9569a5b5 100644 --- a/source/extensions/filters/network/http_connection_manager/config.cc +++ b/source/extensions/filters/network/http_connection_manager/config.cc @@ -231,12 +231,18 @@ HttpConnectionManagerConfig::HttpConnectionManagerConfig( request_headers_for_tags.push_back(Http::LowerCaseString(header)); } - uint64_t client_sampling{ - PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(tracing_config, client_sampling, 100, 100)}; - uint64_t random_sampling{PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT( - tracing_config, random_sampling, 10000, 10000)}; - uint64_t overall_sampling{ - PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(tracing_config, overall_sampling, 100, 100)}; + envoy::type::FractionalPercent client_sampling; + client_sampling.set_numerator( + tracing_config.has_client_sampling() ? tracing_config.client_sampling().value() : 100); + envoy::type::FractionalPercent random_sampling; + // TODO: Random sampling historically was an integer and default to out of 10,000. We should + // deprecate that and move to a straight fractional percent config. + random_sampling.set_numerator( + tracing_config.has_random_sampling() ? tracing_config.random_sampling().value() : 10000); + random_sampling.set_denominator(envoy::type::FractionalPercent::TEN_THOUSAND); + envoy::type::FractionalPercent overall_sampling; + overall_sampling.set_numerator( + tracing_config.has_overall_sampling() ? tracing_config.overall_sampling().value() : 100); tracing_config_ = std::make_unique(Http::TracingConnectionManagerConfig{ diff --git a/test/common/http/async_client_impl_test.cc b/test/common/http/async_client_impl_test.cc index 508357a3e8ed1..60fdcf67b4d30 100644 --- a/test/common/http/async_client_impl_test.cc +++ b/test/common/http/async_client_impl_test.cc @@ -919,6 +919,7 @@ class AsyncClientImplRouteTest : public testing::Test { // Test the extended fake route that AsyncClient uses. TEST_F(AsyncClientImplRouteTest, All) { EXPECT_EQ(nullptr, route_impl.decorator()); + EXPECT_EQ(nullptr, route_impl.tracingConfig()); EXPECT_EQ(nullptr, route_impl.perFilterConfig("")); EXPECT_EQ(Code::InternalServerError, route_impl.routeEntry()->clusterNotFoundResponseCode()); EXPECT_EQ(nullptr, route_impl.routeEntry()->corsPolicy()); diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc index d0463bde38d09..2a9b41aa002e7 100644 --- a/test/common/http/conn_manager_impl_test.cc +++ b/test/common/http/conn_manager_impl_test.cc @@ -45,6 +45,7 @@ #include "gtest/gtest.h" using testing::_; +using testing::An; using testing::AnyNumber; using testing::AtLeast; using testing::DoAll; @@ -121,12 +122,17 @@ class HttpConnectionManagerImplTest : public testing::Test, public ConnectionMan conn_manager_->initializeReadFilterCallbacks(filter_callbacks_); if (tracing) { + envoy::type::FractionalPercent percent1; + percent1.set_numerator(100); + envoy::type::FractionalPercent percent2; + percent2.set_numerator(10000); + percent2.set_denominator(envoy::type::FractionalPercent::TEN_THOUSAND); tracing_config_ = std::make_unique( TracingConnectionManagerConfig{Tracing::OperationName::Ingress, {LowerCaseString(":method")}, - 100, - 10000, - 100, + percent1, + percent2, + percent1, false}); } } @@ -697,7 +703,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlow) { EXPECT_CALL(*span, setTag(Eq(":method"), Eq("GET"))); // Verify if the activeSpan interface returns reference to the current span. EXPECT_CALL(*span, setTag(Eq("service-cluster"), Eq("scoobydoo"))); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -762,7 +769,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat Invoke([&](const Tracing::Span& applyToSpan) -> void { EXPECT_EQ(span, &applyToSpan); })); EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -824,7 +832,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat Invoke([&](const Tracing::Span& applyToSpan) -> void { EXPECT_EQ(span, &applyToSpan); })); EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(Eq("testOp"))); @@ -872,8 +881,18 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowIngressDecorat TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorator) { setup(false, ""); - tracing_config_ = std::make_unique(TracingConnectionManagerConfig{ - Tracing::OperationName::Egress, {LowerCaseString(":method")}, 100, 10000, 100, false}); + envoy::type::FractionalPercent percent1; + percent1.set_numerator(100); + envoy::type::FractionalPercent percent2; + percent2.set_numerator(10000); + percent2.set_denominator(envoy::type::FractionalPercent::TEN_THOUSAND); + tracing_config_ = std::make_unique( + TracingConnectionManagerConfig{Tracing::OperationName::Egress, + {LowerCaseString(":method")}, + percent1, + percent2, + percent1, + false}); NiceMock* span = new NiceMock(); EXPECT_CALL(tracer_, startSpan_(_, _, _, _)) @@ -891,7 +910,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato Invoke([&](const Tracing::Span& applyToSpan) -> void { EXPECT_EQ(span, &applyToSpan); })); EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); EXPECT_CALL(*span, setOperation(_)).Times(0); @@ -939,8 +959,18 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecoratorOverrideOp) { setup(false, ""); - tracing_config_ = std::make_unique(TracingConnectionManagerConfig{ - Tracing::OperationName::Egress, {LowerCaseString(":method")}, 100, 10000, 100, false}); + envoy::type::FractionalPercent percent1; + percent1.set_numerator(100); + envoy::type::FractionalPercent percent2; + percent2.set_numerator(10000); + percent2.set_denominator(envoy::type::FractionalPercent::TEN_THOUSAND); + tracing_config_ = std::make_unique( + TracingConnectionManagerConfig{Tracing::OperationName::Egress, + {LowerCaseString(":method")}, + percent1, + percent2, + percent1, + false}); NiceMock* span = new NiceMock(); EXPECT_CALL(tracer_, startSpan_(_, _, _, _)) @@ -958,7 +988,8 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato Invoke([&](const Tracing::Span& applyToSpan) -> void { EXPECT_EQ(span, &applyToSpan); })); EXPECT_CALL(*span, finishSpan()); EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); // Verify that span operation overridden by value supplied in response header. EXPECT_CALL(*span, setOperation(Eq("testOp"))); @@ -1001,10 +1032,21 @@ TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecorato TEST_F(HttpConnectionManagerImplTest, StartAndFinishSpanNormalFlowEgressDecoratorOverrideOpNoActiveSpan) { setup(false, ""); - tracing_config_ = std::make_unique(TracingConnectionManagerConfig{ - Tracing::OperationName::Egress, {LowerCaseString(":method")}, 100, 10000, 100, false}); - - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + envoy::type::FractionalPercent percent1; + percent1.set_numerator(100); + envoy::type::FractionalPercent percent2; + percent2.set_numerator(10000); + percent2.set_denominator(envoy::type::FractionalPercent::TEN_THOUSAND); + tracing_config_ = std::make_unique( + TracingConnectionManagerConfig{Tracing::OperationName::Egress, + {LowerCaseString(":method")}, + percent1, + percent2, + percent1, + false}); + + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(false)); std::shared_ptr filter(new NiceMock()); @@ -1276,7 +1318,8 @@ TEST_F(HttpConnectionManagerImplTest, DoNotStartSpanIfTracingIsNotEnabled) { tracing_config_.reset(); EXPECT_CALL(tracer_, startSpan_(_, _, _, _)).Times(0); - ON_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + ON_CALL(runtime_.snapshot_, + featureEnabled("tracing.global_enabled", An(), _)) .WillByDefault(Return(true)); std::shared_ptr filter(new NiceMock()); diff --git a/test/common/http/conn_manager_utility_test.cc b/test/common/http/conn_manager_utility_test.cc index 806e6cf6ebb7e..89b519f952dcf 100644 --- a/test/common/http/conn_manager_utility_test.cc +++ b/test/common/http/conn_manager_utility_test.cc @@ -19,6 +19,7 @@ #include "gtest/gtest.h" using testing::_; +using testing::An; using testing::InSequence; using testing::Matcher; using testing::NiceMock; @@ -87,7 +88,12 @@ class ConnectionManagerUtilityTest : public testing::Test { ConnectionManagerUtilityTest() { ON_CALL(config_, userAgent()).WillByDefault(ReturnRef(user_agent_)); - tracing_config_ = {Tracing::OperationName::Ingress, {}, 100, 10000, 100, false}; + envoy::type::FractionalPercent percent1; + percent1.set_numerator(100); + envoy::type::FractionalPercent percent2; + percent2.set_numerator(10000); + percent2.set_denominator(envoy::type::FractionalPercent::TEN_THOUSAND); + tracing_config_ = {Tracing::OperationName::Ingress, {}, percent1, percent2, percent1, false}; ON_CALL(config_, tracingConfig()).WillByDefault(Return(&tracing_config_)); ON_CALL(config_, via()).WillByDefault(ReturnRef(via_)); @@ -109,8 +115,9 @@ class ConnectionManagerUtilityTest : public testing::Test { MutateRequestRet ret; ret.downstream_address_ = ConnectionManagerUtility::mutateRequestHeaders(headers, connection_, config_, route_config_, - random_, runtime_, local_info_) + random_, local_info_) ->asString(); + ConnectionManagerUtility::mutateTracingRequestHeader(headers, runtime_, config_, &route_); ret.internal_ = headers.EnvoyInternalRequest() != nullptr; return ret; } @@ -119,6 +126,7 @@ class ConnectionManagerUtilityTest : public testing::Test { NiceMock random_; NiceMock config_; NiceMock route_config_; + NiceMock route_; absl::optional user_agent_; NiceMock runtime_; Http::TracingConnectionManagerConfig tracing_config_; @@ -338,7 +346,8 @@ TEST_F(ConnectionManagerUtilityTest, InternalServiceForceTrace) { TestHeaderMapImpl headers{ {"x-forwarded-for", "10.0.0.1"}, {"x-request-id", uuid}, {"x-envoy-force-trace", "true"}}; EXPECT_CALL(random_, uuid()).Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); EXPECT_EQ((MutateRequestRet{"10.0.0.1:0", true}), @@ -352,7 +361,11 @@ TEST_F(ConnectionManagerUtilityTest, InternalServiceForceTrace) { TestHeaderMapImpl headers{ {"x-forwarded-for", "34.0.0.1"}, {"x-request-id", uuid}, {"x-envoy-force-trace", "true"}}; EXPECT_CALL(random_, uuid()).Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", + An(), _)) + .WillOnce(Return(false)); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); EXPECT_EQ((MutateRequestRet{"34.0.0.1:0", false}), @@ -366,7 +379,8 @@ TEST_F(ConnectionManagerUtilityTest, InternalServiceForceTrace) { TEST_F(ConnectionManagerUtilityTest, EdgeRequestRegenerateRequestIdAndWipeDownstream) { connection_.remote_address_ = std::make_shared("34.0.0.1"); ON_CALL(config_, useRemoteAddress()).WillByDefault(Return(true)); - ON_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + ON_CALL(runtime_.snapshot_, + featureEnabled("tracing.global_enabled", An(), _)) .WillByDefault(Return(true)); { @@ -390,7 +404,8 @@ TEST_F(ConnectionManagerUtilityTest, EdgeRequestRegenerateRequestIdAndWipeDownst {"x-request-id", "will_be_regenerated"}, {"x-client-trace-id", "trace-id"}}; EXPECT_CALL(random_, uuid()); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.client_enabled", 100)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.client_enabled", + An())) .WillOnce(Return(false)); EXPECT_EQ((MutateRequestRet{"34.0.0.1:0", false}), @@ -405,7 +420,8 @@ TEST_F(ConnectionManagerUtilityTest, EdgeRequestRegenerateRequestIdAndWipeDownst {"x-request-id", "will_be_regenerated"}, {"x-client-trace-id", "trace-id"}}; EXPECT_CALL(random_, uuid()); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.client_enabled", 100)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.client_enabled", + An())) .WillOnce(Return(true)); EXPECT_EQ((MutateRequestRet{"34.0.0.1:0", false}), @@ -977,9 +993,26 @@ TEST_F(ConnectionManagerUtilityTest, NonTlsAlwaysForwardClientCert) { // Sampling, global on. TEST_F(ConnectionManagerUtilityTest, RandomSamplingWhenGlobalSet) { - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", 10000, _, 10000)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", + An(), _)) + .WillOnce(Return(true)); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) + .WillOnce(Return(true)); + + Http::TestHeaderMapImpl request_headers{{"x-request-id", "125a4afb-6f55-44ba-ad80-413f09f48a28"}}; + callMutateRequestHeaders(request_headers, Protocol::Http2); + + EXPECT_EQ(UuidTraceStatus::Sampled, + UuidUtils::isTraceableUuid(request_headers.get_("x-request-id"))); +} + +TEST_F(ConnectionManagerUtilityTest, SamplingWithoutRouteOverride) { + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", + An(), _)) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); Http::TestHeaderMapImpl request_headers{{"x-request-id", "125a4afb-6f55-44ba-ad80-413f09f48a28"}}; @@ -989,11 +1022,35 @@ TEST_F(ConnectionManagerUtilityTest, RandomSamplingWhenGlobalSet) { UuidUtils::isTraceableUuid(request_headers.get_("x-request-id"))); } +TEST_F(ConnectionManagerUtilityTest, SamplingWithRouteOverride) { + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", + An(), _)) + .WillOnce(Return(false)); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) + .WillOnce(Return(false)); + + NiceMock tracingConfig; + EXPECT_CALL(route_, tracingConfig()).WillRepeatedly(Return(&tracingConfig)); + const envoy::type::FractionalPercent percent; + EXPECT_CALL(tracingConfig, getClientSampling()).WillRepeatedly(ReturnRef(percent)); + EXPECT_CALL(tracingConfig, getRandomSampling()).WillRepeatedly(ReturnRef(percent)); + EXPECT_CALL(tracingConfig, getOverallSampling()).WillRepeatedly(ReturnRef(percent)); + + Http::TestHeaderMapImpl request_headers{{"x-request-id", "125a4afb-6f55-44ba-ad80-413f09f48a28"}}; + callMutateRequestHeaders(request_headers, Protocol::Http2); + + EXPECT_EQ(UuidTraceStatus::NoTrace, + UuidUtils::isTraceableUuid(request_headers.get_("x-request-id"))); +} + // Sampling must not be done on client traced. TEST_F(ConnectionManagerUtilityTest, SamplingMustNotBeDoneOnClientTraced) { - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", 10000, _, 10000)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", + An(), _)) .Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); // The x_request_id has TRACE_FORCED(a) set in the TRACE_BYTE_POSITION(14) character. @@ -1006,9 +1063,11 @@ TEST_F(ConnectionManagerUtilityTest, SamplingMustNotBeDoneOnClientTraced) { // Sampling, global off. TEST_F(ConnectionManagerUtilityTest, NoTraceWhenSamplingSetButGlobalNotSet) { - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", 10000, _, 10000)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", + An(), _)) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(false)); Http::TestHeaderMapImpl request_headers{{"x-request-id", "125a4afb-6f55-44ba-ad80-413f09f48a28"}}; @@ -1020,9 +1079,11 @@ TEST_F(ConnectionManagerUtilityTest, NoTraceWhenSamplingSetButGlobalNotSet) { // Client, client enabled, global on. TEST_F(ConnectionManagerUtilityTest, ClientSamplingWhenGlobalSet) { - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.client_enabled", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("tracing.client_enabled", An())) .WillOnce(Return(true)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); Http::TestHeaderMapImpl request_headers{ @@ -1036,9 +1097,14 @@ TEST_F(ConnectionManagerUtilityTest, ClientSamplingWhenGlobalSet) { // Client, client disabled, global on. TEST_F(ConnectionManagerUtilityTest, NoTraceWhenClientSamplingNotSetAndGlobalSet) { - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.client_enabled", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("tracing.client_enabled", An())) + .WillOnce(Return(false)); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.random_sampling", + An(), _)) .WillOnce(Return(false)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); Http::TestHeaderMapImpl request_headers{ @@ -1058,7 +1124,8 @@ TEST_F(ConnectionManagerUtilityTest, ForcedTracedWhenGlobalSet) { {"x-request-id", "125a4afb-6f55-44ba-ad80-413f09f48a28"}, {"x-envoy-force-trace", "true"}}; EXPECT_CALL(random_, uuid()).Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(true)); EXPECT_EQ((MutateRequestRet{"10.0.0.1:0", true}), @@ -1074,7 +1141,8 @@ TEST_F(ConnectionManagerUtilityTest, NoTraceWhenForcedTracedButGlobalNotSet) { {"x-request-id", "125a4afb-6f55-44ba-ad80-413f09f48a28"}, {"x-envoy-force-trace", "true"}}; EXPECT_CALL(random_, uuid()).Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", 100, _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("tracing.global_enabled", + An(), _)) .WillOnce(Return(false)); EXPECT_EQ((MutateRequestRet{"10.0.0.1:0", true}), diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index aeaff0b0d376f..88aa1a62e2460 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -4818,6 +4818,60 @@ name: foo EXPECT_EQ("foo", route_entry->virtualHost().routeConfig().name()); } +TEST_F(RouteConfigurationV2, RouteTracingConfig) { + const std::string yaml = R"EOF( +name: foo +virtual_hosts: + - name: bar + domains: ["*"] + routes: + - match: { regex: "/first" } + tracing: + client_sampling: + numerator: 1 + route: { cluster: ww2 } + - match: { regex: "/second" } + tracing: + overall_sampling: + numerator: 1 + route: { cluster: ww2 } + - match: { path: "/third" } + tracing: + client_sampling: + numerator: 1 + random_sampling: + numerator: 200 + denominator: 1 + overall_sampling: + numerator: 3 + route: { cluster: ww2 } + )EOF"; + BazFactory baz_factory; + Registry::InjectFactory registered_factory(baz_factory); + const TestConfigImpl config(parseRouteConfigurationFromV2Yaml(yaml), factory_context_, true); + + const auto route1 = config.route(genHeaders("www.foo.com", "/first", "GET"), 0); + const auto route2 = config.route(genHeaders("www.foo.com", "/second", "GET"), 0); + const auto route3 = config.route(genHeaders("www.foo.com", "/third", "GET"), 0); + + // Check default values for random and overall sampling + EXPECT_EQ(100, route1->tracingConfig()->getRandomSampling().numerator()); + EXPECT_EQ(0, route1->tracingConfig()->getRandomSampling().denominator()); + EXPECT_EQ(100, route1->tracingConfig()->getOverallSampling().numerator()); + EXPECT_EQ(0, route1->tracingConfig()->getOverallSampling().denominator()); + + // Check default values for client sampling + EXPECT_EQ(100, route2->tracingConfig()->getClientSampling().numerator()); + EXPECT_EQ(0, route2->tracingConfig()->getClientSampling().denominator()); + + EXPECT_EQ(1, route3->tracingConfig()->getClientSampling().numerator()); + EXPECT_EQ(0, route3->tracingConfig()->getClientSampling().denominator()); + EXPECT_EQ(200, route3->tracingConfig()->getRandomSampling().numerator()); + EXPECT_EQ(1, route3->tracingConfig()->getRandomSampling().denominator()); + EXPECT_EQ(3, route3->tracingConfig()->getOverallSampling().numerator()); + EXPECT_EQ(0, route3->tracingConfig()->getOverallSampling().denominator()); +} + // Test to check Prefix Rewrite for redirects TEST_F(RouteConfigurationV2, RedirectPrefixRewrite) { std::string RedirectPrefixRewrite = R"EOF( diff --git a/test/extensions/filters/network/http_connection_manager/config_test.cc b/test/extensions/filters/network/http_connection_manager/config_test.cc index 6feb80d6d37f4..9974516f569f5 100644 --- a/test/extensions/filters/network/http_connection_manager/config_test.cc +++ b/test/extensions/filters/network/http_connection_manager/config_test.cc @@ -106,6 +106,66 @@ stat_prefix: router EXPECT_EQ(5 * 60 * 1000, config.streamIdleTimeout().count()); } +TEST_F(HttpConnectionManagerConfigTest, SamplingDefault) { + const std::string yaml_string = R"EOF( + stat_prefix: ingress_http + internal_address_config: + unix_sockets: true + route_config: + name: local_route + tracing: + operation_name: ingress + http_filters: + - name: envoy.router + )EOF"; + + HttpConnectionManagerConfig config(parseHttpConnectionManagerFromV2Yaml(yaml_string), context_, + date_provider_, route_config_provider_manager_); + + EXPECT_EQ(100, config.tracingConfig()->client_sampling_.numerator()); + EXPECT_EQ(envoy::type::FractionalPercent::HUNDRED, + config.tracingConfig()->client_sampling_.denominator()); + EXPECT_EQ(10000, config.tracingConfig()->random_sampling_.numerator()); + EXPECT_EQ(envoy::type::FractionalPercent::TEN_THOUSAND, + config.tracingConfig()->random_sampling_.denominator()); + EXPECT_EQ(100, config.tracingConfig()->overall_sampling_.numerator()); + EXPECT_EQ(envoy::type::FractionalPercent::HUNDRED, + config.tracingConfig()->overall_sampling_.denominator()); +} + +TEST_F(HttpConnectionManagerConfigTest, SamplingConfigured) { + const std::string yaml_string = R"EOF( + stat_prefix: ingress_http + internal_address_config: + unix_sockets: true + route_config: + name: local_route + tracing: + operation_name: ingress + client_sampling: + value: 1 + random_sampling: + value: 2 + overall_sampling: + value: 3 + http_filters: + - name: envoy.router + )EOF"; + + HttpConnectionManagerConfig config(parseHttpConnectionManagerFromV2Yaml(yaml_string), context_, + date_provider_, route_config_provider_manager_); + + EXPECT_EQ(1, config.tracingConfig()->client_sampling_.numerator()); + EXPECT_EQ(envoy::type::FractionalPercent::HUNDRED, + config.tracingConfig()->client_sampling_.denominator()); + EXPECT_EQ(2, config.tracingConfig()->random_sampling_.numerator()); + EXPECT_EQ(envoy::type::FractionalPercent::TEN_THOUSAND, + config.tracingConfig()->random_sampling_.denominator()); + EXPECT_EQ(3, config.tracingConfig()->overall_sampling_.numerator()); + EXPECT_EQ(envoy::type::FractionalPercent::HUNDRED, + config.tracingConfig()->overall_sampling_.denominator()); +} + TEST_F(HttpConnectionManagerConfigTest, UnixSocketInternalAddress) { const std::string yaml_string = R"EOF( stat_prefix: ingress_http diff --git a/test/mocks/router/mocks.cc b/test/mocks/router/mocks.cc index f67ea18e5c758..f99496356e959 100644 --- a/test/mocks/router/mocks.cc +++ b/test/mocks/router/mocks.cc @@ -106,9 +106,13 @@ MockDecorator::MockDecorator() { } MockDecorator::~MockDecorator() {} +MockRouteTracing::MockRouteTracing() {} +MockRouteTracing::~MockRouteTracing() {} + MockRoute::MockRoute() { ON_CALL(*this, routeEntry()).WillByDefault(Return(&route_entry_)); ON_CALL(*this, decorator()).WillByDefault(Return(&decorator_)); + ON_CALL(*this, tracingConfig()).WillByDefault(Return(nullptr)); } MockRoute::~MockRoute() {} diff --git a/test/mocks/router/mocks.h b/test/mocks/router/mocks.h index b8ae9835840d1..4b89f70ee1a3c 100644 --- a/test/mocks/router/mocks.h +++ b/test/mocks/router/mocks.h @@ -335,6 +335,17 @@ class MockDecorator : public Decorator { std::string operation_{"fake_operation"}; }; +class MockRouteTracing : public RouteTracing { +public: + MockRouteTracing(); + ~MockRouteTracing(); + + // Router::RouteTracing + MOCK_CONST_METHOD0(getClientSampling, const envoy::type::FractionalPercent&()); + MOCK_CONST_METHOD0(getRandomSampling, const envoy::type::FractionalPercent&()); + MOCK_CONST_METHOD0(getOverallSampling, const envoy::type::FractionalPercent&()); +}; + class MockRoute : public Route { public: MockRoute(); @@ -344,10 +355,12 @@ class MockRoute : public Route { MOCK_CONST_METHOD0(directResponseEntry, const DirectResponseEntry*()); MOCK_CONST_METHOD0(routeEntry, const RouteEntry*()); MOCK_CONST_METHOD0(decorator, const Decorator*()); + MOCK_CONST_METHOD0(tracingConfig, const RouteTracing*()); MOCK_CONST_METHOD1(perFilterConfig, const RouteSpecificFilterConfig*(const std::string&)); testing::NiceMock route_entry_; testing::NiceMock decorator_; + testing::NiceMock route_tracing_; }; class MockConfig : public Config {