Skip to content

Commit

Permalink
[filter]: Add option to disable fault filter stats that trace downstr…
Browse files Browse the repository at this point in the history
…eam server name (#16235)


Signed-off-by: chaoqin-li1123 <[email protected]>
  • Loading branch information
chaoqin-li1123 authored May 4, 2021
1 parent b9d21f0 commit 38d1c19
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 10 deletions.
8 changes: 7 additions & 1 deletion api/envoy/extensions/filters/http/fault/v3/fault.proto
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ message FaultAbort {
type.v3.FractionalPercent percentage = 3;
}

// [#next-free-field: 15]
// [#next-free-field: 16]
message HTTPFault {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.fault.v2.HTTPFault";
Expand Down Expand Up @@ -141,4 +141,10 @@ message HTTPFault {
// The runtime key to override the :ref:`default <config_http_filters_fault_injection_runtime>`
// runtime. The default is: fault.http.abort.grpc_status
string abort_grpc_status_runtime = 14;

// To control whether stats storage is allocated dynamically for each downstream server.
// If set to true, "x-envoy-downstream-service-cluster" field of header will be ignored by this filter.
// If set to false, dynamic stats storage will be allocated for the downstream cluster name.
// Default value is false.
bool disable_downstream_cluster_stats = 15;
}
8 changes: 7 additions & 1 deletion api/envoy/extensions/filters/http/fault/v4alpha/fault.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions source/extensions/filters/http/fault/fault_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ FaultSettings::FaultSettings(const envoy::extensions::filters::http::fault::v3::
fault, max_active_faults_runtime, RuntimeKeys::get().MaxActiveFaultsKey)),
response_rate_limit_percent_runtime_(
PROTOBUF_GET_STRING_OR_DEFAULT(fault, response_rate_limit_percent_runtime,
RuntimeKeys::get().ResponseRateLimitPercentKey)) {
RuntimeKeys::get().ResponseRateLimitPercentKey)),
disable_downstream_cluster_stats_(fault.disable_downstream_cluster_stats()) {
if (fault.has_abort()) {
request_abort_config_ =
std::make_unique<Filters::Common::Fault::FaultAbortConfig>(fault.abort());
Expand Down Expand Up @@ -89,8 +90,10 @@ FaultFilterConfig::FaultFilterConfig(
stats_prefix_(stat_name_set_->add(absl::StrCat(stats_prefix, "fault"))) {}

void FaultFilterConfig::incCounter(Stats::StatName downstream_cluster, Stats::StatName stat_name) {
Stats::Utility::counterFromStatNames(scope_, {stats_prefix_, downstream_cluster, stat_name})
.inc();
if (!settings_.disableDownstreamClusterStats()) {
Stats::Utility::counterFromStatNames(scope_, {stats_prefix_, downstream_cluster, stat_name})
.inc();
}
}

FaultFilter::FaultFilter(FaultFilterConfigSharedPtr config) : config_(config) {}
Expand Down Expand Up @@ -134,7 +137,7 @@ Http::FilterHeadersStatus FaultFilter::decodeHeaders(Http::RequestHeaderMap& hea

if (headers.EnvoyDownstreamServiceCluster()) {
downstream_cluster_ = std::string(headers.getEnvoyDownstreamServiceClusterValue());
if (!downstream_cluster_.empty()) {
if (!downstream_cluster_.empty() && !fault_settings_->disableDownstreamClusterStats()) {
downstream_cluster_storage_ = std::make_unique<Stats::StatNameDynamicStorage>(
downstream_cluster_, config_->scope().symbolTable());
}
Expand Down Expand Up @@ -369,7 +372,7 @@ FaultFilter::abortGrpcStatus(const Http::RequestHeaderMap& request_headers) {

void FaultFilter::recordDelaysInjectedStats() {
// Downstream specific stats.
if (!downstream_cluster_.empty()) {
if (!downstream_cluster_.empty() && !fault_settings_->disableDownstreamClusterStats()) {
config_->incDelays(downstream_cluster_storage_->statName());
}

Expand All @@ -378,7 +381,7 @@ void FaultFilter::recordDelaysInjectedStats() {

void FaultFilter::recordAbortsInjectedStats() {
// Downstream specific stats.
if (!downstream_cluster_.empty()) {
if (!downstream_cluster_.empty() && !fault_settings_->disableDownstreamClusterStats()) {
config_->incAborts(downstream_cluster_storage_->statName());
}

Expand Down
3 changes: 3 additions & 0 deletions source/extensions/filters/http/fault/fault_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class FaultSettings : public Router::RouteSpecificFilterConfig {
const std::string& responseRateLimitPercentRuntime() const {
return response_rate_limit_percent_runtime_;
}
bool disableDownstreamClusterStats() const { return disable_downstream_cluster_stats_; }

private:
class RuntimeKeyValues {
Expand All @@ -96,6 +97,7 @@ class FaultSettings : public Router::RouteSpecificFilterConfig {
const std::vector<Http::HeaderUtility::HeaderDataPtr> fault_filter_headers_;
absl::flat_hash_set<std::string> downstream_nodes_{}; // Inject failures for specific downstream
absl::optional<uint64_t> max_active_faults_;

Filters::Common::Fault::FaultRateLimitConfigPtr response_rate_limit_;
const std::string delay_percent_runtime_;
const std::string abort_percent_runtime_;
Expand All @@ -104,6 +106,7 @@ class FaultSettings : public Router::RouteSpecificFilterConfig {
const std::string abort_grpc_status_runtime_;
const std::string max_active_faults_runtime_;
const std::string response_rate_limit_percent_runtime_;
const bool disable_downstream_cluster_stats_;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ name: fault
numerator: 100
)EOF";

const std::string disable_stats_fault_config_ =
R"EOF(
name: fault
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
abort:
header_abort: {}
percentage:
numerator: 100
delay:
header_delay: {}
percentage:
numerator: 100
response_rate_limit:
header_limit: {}
percentage:
numerator: 100
disable_downstream_cluster_stats: true
)EOF";

const std::string abort_grpc_fault_config_ =
R"EOF(
name: fault
Expand Down Expand Up @@ -173,6 +193,56 @@ TEST_P(FaultIntegrationTestAllProtocols, HeaderFaultAbortConfig) {
EXPECT_EQ(0UL, test_server_->gauge("http.config_test.fault.active_faults")->value());
}

// Request abort controlled via header configuration and enable downstream server stats.
TEST_P(FaultIntegrationTestAllProtocols, HeaderFaultAbortConfigEnableDownstreamServerStats) {
initializeFilter(header_fault_config_);
codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http")));

auto response = codec_client_->makeHeaderOnlyRequest(
Http::TestRequestHeaderMapImpl{{":method", "GET"},
{":path", "/test/long/url"},
{":scheme", "http"},
{":authority", "host"},
{"x-envoy-fault-abort-request", "429"},
{"x-envoy-downstream-service-cluster", "superman"}});
ASSERT_TRUE(response->waitForEndStream());

EXPECT_TRUE(response->complete());
EXPECT_THAT(response->headers(), Envoy::Http::HttpStatusIs("429"));

EXPECT_EQ(1UL, test_server_->counter("http.config_test.fault.aborts_injected")->value());
EXPECT_EQ(0UL, test_server_->counter("http.config_test.fault.delays_injected")->value());
EXPECT_EQ(0UL, test_server_->counter("http.config_test.fault.response_rl_injected")->value());
EXPECT_EQ(0UL, test_server_->gauge("http.config_test.fault.active_faults")->value());
EXPECT_EQ(1UL, test_server_->counter("http.config_test.fault.superman.aborts_injected")->value());
EXPECT_EQ(nullptr, test_server_->counter("http.config_test.fault.superman.delays_injected"));
}

// Request abort controlled via header configuration and disable downstream server stats.
TEST_P(FaultIntegrationTestAllProtocols, HeaderFaultAbortConfigDisableDownstreamServerStats) {
initializeFilter(disable_stats_fault_config_);
codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http")));

auto response = codec_client_->makeHeaderOnlyRequest(
Http::TestRequestHeaderMapImpl{{":method", "GET"},
{":path", "/test/long/url"},
{":scheme", "http"},
{":authority", "host"},
{"x-envoy-fault-abort-request", "429"},
{"x-envoy-downstream-service-cluster", "superman"}});
ASSERT_TRUE(response->waitForEndStream());

EXPECT_TRUE(response->complete());
EXPECT_THAT(response->headers(), Envoy::Http::HttpStatusIs("429"));

EXPECT_EQ(1UL, test_server_->counter("http.config_test.fault.aborts_injected")->value());
EXPECT_EQ(0UL, test_server_->counter("http.config_test.fault.delays_injected")->value());
EXPECT_EQ(0UL, test_server_->counter("http.config_test.fault.response_rl_injected")->value());
EXPECT_EQ(0UL, test_server_->gauge("http.config_test.fault.active_faults")->value());
EXPECT_EQ(nullptr, test_server_->counter("http.config_test.fault.superman.aborts_injected"));
EXPECT_EQ(nullptr, test_server_->counter("http.config_test.fault.superman.delays_injected"));
}

// Request faults controlled via header configuration.
TEST_P(FaultIntegrationTestAllProtocols, HeaderFaultsConfig0PercentageHeaders) {
initializeFilter(header_fault_config_);
Expand Down
58 changes: 58 additions & 0 deletions test/extensions/filters/http/fault/fault_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ class FaultFilterTest : public testing::Test {
fixed_delay: 5s
)EOF";

const std::string fixed_delay_only_disable_stats_yaml = R"EOF(
delay:
percentage:
numerator: 100
denominator: HUNDRED
fixed_delay: 5s
disable_downstream_cluster_stats: true
)EOF";

const std::string abort_only_yaml = R"EOF(
abort:
percentage:
Expand Down Expand Up @@ -717,6 +726,55 @@ TEST_F(FaultFilterTest, DelayForDownstreamCluster) {
EXPECT_EQ(0UL, stats_.counter("prefix.fault.cluster.aborts_injected").value());
}

TEST_F(FaultFilterTest, DelayForDownstreamClusterDisableTracing) {
setUpTest(fixed_delay_only_disable_stats_yaml);

EXPECT_CALL(runtime_.snapshot_,
getInteger("fault.http.max_active_faults", std::numeric_limits<uint64_t>::max()))
.WillOnce(Return(std::numeric_limits<uint64_t>::max()));

request_headers_.addCopy("x-envoy-downstream-service-cluster", "cluster");

// Delay related calls.
EXPECT_CALL(
runtime_.snapshot_,
featureEnabled("fault.http.cluster.delay.fixed_delay_percent",
testing::Matcher<const envoy::type::v3::FractionalPercent&>(Percent(100))))
.WillOnce(Return(true));

EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000))
.WillOnce(Return(125UL));
EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.cluster.delay.fixed_duration_ms", 125UL))
.WillOnce(Return(500UL));
expectDelayTimer(500UL);
EXPECT_CALL(decoder_filter_callbacks_.stream_info_,
setResponseFlag(StreamInfo::ResponseFlag::DelayInjected));

EXPECT_EQ(Http::FilterHeadersStatus::StopIteration,
filter_->decodeHeaders(request_headers_, false));

// Delay only case, no aborts.
EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.cluster.abort.http_status", _)).Times(0);
EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0);
EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0);
EXPECT_CALL(decoder_filter_callbacks_.stream_info_,
setResponseFlag(StreamInfo::ResponseFlag::FaultInjected))
.Times(0);
EXPECT_CALL(decoder_filter_callbacks_, continueDecoding());
EXPECT_EQ(Http::FilterDataStatus::StopIterationAndWatermark, filter_->decodeData(data_, false));

EXPECT_CALL(decoder_filter_callbacks_.dispatcher_, pushTrackedObject(_));
EXPECT_CALL(decoder_filter_callbacks_.dispatcher_, popTrackedObject(_));
timer_->invokeCallback();

EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_->decodeTrailers(request_trailers_));

EXPECT_EQ(1UL, config_->stats().delays_injected_.value());
EXPECT_EQ(0UL, config_->stats().aborts_injected_.value());
EXPECT_EQ(0UL, stats_.counter("prefix.fault.cluster.delays_injected").value());
EXPECT_EQ(0UL, stats_.counter("prefix.fault.cluster.aborts_injected").value());
}

TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) {
setUpTest(fixed_delay_and_abort_yaml);

Expand Down

0 comments on commit 38d1c19

Please sign in to comment.