-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
http fault: implement header controlled faults
Part of #5942 Signed-off-by: Matt Klein <mklein@lyft.com>
- Loading branch information
1 parent
8593e6a
commit b34e7ff
Showing
20 changed files
with
543 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
licenses(["notice"]) # Apache 2 | ||
|
||
load( | ||
"//bazel:envoy_build_system.bzl", | ||
"envoy_cc_library", | ||
"envoy_package", | ||
) | ||
|
||
envoy_package() | ||
|
||
envoy_cc_library( | ||
name = "fault_config_lib", | ||
srcs = ["fault_config.cc"], | ||
hdrs = ["fault_config.h"], | ||
deps = [ | ||
"//include/envoy/http:header_map_interface", | ||
"//source/common/protobuf:utility_lib", | ||
"@envoy_api//envoy/config/filter/fault/v2:fault_cc", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#include "extensions/filters/common/fault/fault_config.h" | ||
|
||
#include "common/protobuf/utility.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Filters { | ||
namespace Common { | ||
namespace Fault { | ||
|
||
FaultDelayConfig::FaultDelayConfig(const envoy::config::filter::fault::v2::FaultDelay& delay_config) | ||
: percentage_(delay_config.percentage()) { | ||
switch (delay_config.fault_delay_secifier_case()) { | ||
case envoy::config::filter::fault::v2::FaultDelay::kFixedDelay: | ||
provider_ = std::make_unique<FixedDelayProvider>( | ||
std::chrono::milliseconds(PROTOBUF_GET_MS_REQUIRED(delay_config, fixed_delay))); | ||
break; | ||
case envoy::config::filter::fault::v2::FaultDelay::kHeaderDelay: | ||
provider_ = std::make_unique<HeaderDelayProvider>(); | ||
break; | ||
case envoy::config::filter::fault::v2::FaultDelay::FAULT_DELAY_SECIFIER_NOT_SET: | ||
NOT_REACHED_GCOVR_EXCL_LINE; | ||
} | ||
} | ||
|
||
absl::optional<std::chrono::milliseconds> | ||
FaultDelayConfig::HeaderDelayProvider::duration(const Http::HeaderEntry* header) const { | ||
if (header == nullptr) { | ||
return absl::nullopt; | ||
} | ||
|
||
uint64_t value; | ||
if (!StringUtil::atoull(header->value().getStringView().data(), value)) { | ||
return absl::nullopt; | ||
} | ||
|
||
return std::chrono::milliseconds(value); | ||
} | ||
|
||
FaultRateLimitConfig::FaultRateLimitConfig( | ||
const envoy::config::filter::fault::v2::FaultRateLimit& rate_limit_config) | ||
: percentage_(rate_limit_config.percentage()) { | ||
switch (rate_limit_config.limit_type_case()) { | ||
case envoy::config::filter::fault::v2::FaultRateLimit::kFixedLimit: | ||
provider_ = | ||
std::make_unique<FixedRateLimitProvider>(rate_limit_config.fixed_limit().limit_kbps()); | ||
break; | ||
case envoy::config::filter::fault::v2::FaultRateLimit::kHeaderLimit: | ||
provider_ = std::make_unique<HeaderRateLimitProvider>(); | ||
break; | ||
case envoy::config::filter::fault::v2::FaultRateLimit::LIMIT_TYPE_NOT_SET: | ||
NOT_REACHED_GCOVR_EXCL_LINE; | ||
} | ||
} | ||
|
||
absl::optional<uint64_t> | ||
FaultRateLimitConfig::HeaderRateLimitProvider::rateKbps(const Http::HeaderEntry* header) const { | ||
if (header == nullptr) { | ||
return absl::nullopt; | ||
} | ||
|
||
uint64_t value; | ||
if (!StringUtil::atoull(header->value().getStringView().data(), value)) { | ||
return absl::nullopt; | ||
} | ||
|
||
if (value == 0) { | ||
return absl::nullopt; | ||
} | ||
|
||
return value; | ||
} | ||
|
||
} // namespace Fault | ||
} // namespace Common | ||
} // namespace Filters | ||
} // namespace Extensions | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#pragma once | ||
|
||
#include "envoy/config/filter/fault/v2/fault.pb.h" | ||
#include "envoy/http/header_map.h" | ||
|
||
#include "common/singleton/const_singleton.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Filters { | ||
namespace Common { | ||
namespace Fault { | ||
|
||
class HeaderNameValues { | ||
public: | ||
const Http::LowerCaseString ThrottleRequestLatency{"x-envoy-throttle-request-latency"}; | ||
const Http::LowerCaseString ThrottleResponseThroughput{"x-envoy-throttle-response-throughput"}; | ||
}; | ||
|
||
typedef ConstSingleton<HeaderNameValues> HeaderNames; | ||
|
||
/** | ||
* Generic configuration for a delay fault. | ||
*/ | ||
class FaultDelayConfig { | ||
public: | ||
FaultDelayConfig(const envoy::config::filter::fault::v2::FaultDelay& delay_config); | ||
|
||
const envoy::type::FractionalPercent& percentage() const { return percentage_; } | ||
absl::optional<std::chrono::milliseconds> duration(const Http::HeaderEntry* header) const { | ||
return provider_->duration(header); | ||
} | ||
|
||
private: | ||
// Abstract delay provider. | ||
class DelayProvider { | ||
public: | ||
virtual ~DelayProvider() = default; | ||
|
||
// Return the duration to use. Optionally passed an HTTP header that may contain the delay | ||
// depending on the provider implementation. | ||
virtual absl::optional<std::chrono::milliseconds> | ||
duration(const Http::HeaderEntry* header) const PURE; | ||
}; | ||
|
||
// Delay provider that uses a fixed delay. | ||
class FixedDelayProvider : public DelayProvider { | ||
public: | ||
FixedDelayProvider(std::chrono::milliseconds delay) : delay_(delay) {} | ||
|
||
// DelayProvider | ||
absl::optional<std::chrono::milliseconds> duration(const Http::HeaderEntry*) const override { | ||
return delay_; | ||
} | ||
|
||
private: | ||
const std::chrono::milliseconds delay_; | ||
}; | ||
|
||
// Delay provider the reads a delay from an HTTP header. | ||
class HeaderDelayProvider : public DelayProvider { | ||
public: | ||
// DelayProvider | ||
absl::optional<std::chrono::milliseconds> | ||
duration(const Http::HeaderEntry* header) const override; | ||
}; | ||
|
||
using DelayProviderPtr = std::unique_ptr<DelayProvider>; | ||
|
||
DelayProviderPtr provider_; | ||
const envoy::type::FractionalPercent percentage_; | ||
}; | ||
|
||
using FaultDelayConfigPtr = std::unique_ptr<FaultDelayConfig>; | ||
using FaultDelayConfigSharedPtr = std::shared_ptr<FaultDelayConfig>; | ||
|
||
/** | ||
* Generic configuration for a rate limit fault. | ||
*/ | ||
class FaultRateLimitConfig { | ||
public: | ||
FaultRateLimitConfig(const envoy::config::filter::fault::v2::FaultRateLimit& rate_limit_config); | ||
|
||
const envoy::type::FractionalPercent& percentage() const { return percentage_; } | ||
absl::optional<uint64_t> rateKbps(const Http::HeaderEntry* header) const { | ||
return provider_->rateKbps(header); | ||
} | ||
|
||
private: | ||
// Abstract rate limit provider. | ||
class RateLimitProvider { | ||
public: | ||
virtual ~RateLimitProvider() = default; | ||
|
||
// Return the rate limit to use in KiB/s. Optionally passed an HTTP header that may contain the | ||
// rate limit depending on the provider implementation. | ||
virtual absl::optional<uint64_t> rateKbps(const Http::HeaderEntry* header) const PURE; | ||
}; | ||
|
||
// Rate limit provider that uses a fixed rate limit. | ||
class FixedRateLimitProvider : public RateLimitProvider { | ||
public: | ||
FixedRateLimitProvider(uint64_t fixed_rate_kbps) : fixed_rate_kbps_(fixed_rate_kbps) {} | ||
absl::optional<uint64_t> rateKbps(const Http::HeaderEntry*) const override { | ||
return fixed_rate_kbps_; | ||
} | ||
|
||
private: | ||
const uint64_t fixed_rate_kbps_; | ||
}; | ||
|
||
// Rate limit provider that reads the rate limit from an HTTP header. | ||
class HeaderRateLimitProvider : public RateLimitProvider { | ||
public: | ||
absl::optional<uint64_t> rateKbps(const Http::HeaderEntry* header) const override; | ||
}; | ||
|
||
using RateLimitProviderPtr = std::unique_ptr<RateLimitProvider>; | ||
|
||
RateLimitProviderPtr provider_; | ||
const envoy::type::FractionalPercent percentage_; | ||
}; | ||
|
||
using FaultRateLimitConfigPtr = std::unique_ptr<FaultRateLimitConfig>; | ||
|
||
} // namespace Fault | ||
} // namespace Common | ||
} // namespace Filters | ||
} // namespace Extensions | ||
} // namespace Envoy |
Oops, something went wrong.