Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve substitution formatter parsing performance #35498

Merged
merged 12 commits into from
Aug 2, 2024
4 changes: 2 additions & 2 deletions envoy/formatter/substitution_formatter_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ template <class FormatterContext> class CommandParserBase {
* @return FormattterProviderPtr substitution provider for the parsed command.
*/
virtual FormatterProviderBasePtr<FormatterContext>
parse(const std::string& command, const std::string& command_arg,
absl::optional<size_t>& max_length) const PURE;
parse(absl::string_view command, absl::string_view command_arg,
absl::optional<size_t> max_length) const PURE;
};

template <class FormatterContext>
Expand Down
89 changes: 39 additions & 50 deletions source/common/formatter/http_specific_formatter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ AccessLogTypeFormatter::formatValueWithContext(const HttpFormatterContext& conte
return ValueUtil::stringValue(AccessLogType_Name(context.accessLogType()));
}

HeaderFormatter::HeaderFormatter(const std::string& main_header,
const std::string& alternative_header,
HeaderFormatter::HeaderFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: main_header_(main_header), alternative_header_(alternative_header), max_length_(max_length) {}

Expand Down Expand Up @@ -81,8 +81,8 @@ ProtobufWkt::Value HeaderFormatter::formatValue(const Http::HeaderMap& headers)
return ValueUtil::stringValue(std::string(val));
}

ResponseHeaderFormatter::ResponseHeaderFormatter(const std::string& main_header,
const std::string& alternative_header,
ResponseHeaderFormatter::ResponseHeaderFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: HeaderFormatter(main_header, alternative_header, max_length) {}

Expand All @@ -98,8 +98,8 @@ ResponseHeaderFormatter::formatValueWithContext(const HttpFormatterContext& cont
return HeaderFormatter::formatValue(context.responseHeaders());
}

RequestHeaderFormatter::RequestHeaderFormatter(const std::string& main_header,
const std::string& alternative_header,
RequestHeaderFormatter::RequestHeaderFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: HeaderFormatter(main_header, alternative_header, max_length) {}

Expand All @@ -115,8 +115,8 @@ RequestHeaderFormatter::formatValueWithContext(const HttpFormatterContext& conte
return HeaderFormatter::formatValue(context.requestHeaders());
}

ResponseTrailerFormatter::ResponseTrailerFormatter(const std::string& main_header,
const std::string& alternative_header,
ResponseTrailerFormatter::ResponseTrailerFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: HeaderFormatter(main_header, alternative_header, max_length) {}

Expand Down Expand Up @@ -299,96 +299,85 @@ BuiltInHttpCommandParser::getKnownFormatters() {
FormatterProviderLookupTbl,
{{"REQ",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;

THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<RequestHeaderFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<RequestHeaderFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"RESP",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;

THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<ResponseHeaderFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<ResponseHeaderFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"TRAILER",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;

THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<ResponseTrailerFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<ResponseTrailerFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"LOCAL_REPLY_BODY",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<LocalReplyBodyFormatter>();
}}},
{"ACCESS_LOG_TYPE",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<AccessLogTypeFormatter>();
}}},
{"GRPC_STATUS",
{CommandSyntaxChecker::PARAMS_OPTIONAL,
[](const std::string& format, const absl::optional<size_t>&) {
[](absl::string_view format, absl::optional<size_t>) {
return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(),
GrpcStatusFormatter::parseFormat(format));
}}},
{"GRPC_STATUS_NUMBER",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, const absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(),
GrpcStatusFormatter::Number);
}}},
{"REQUEST_HEADERS_BYTES",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<HeadersByteSizeFormatter>(
HeadersByteSizeFormatter::HeaderType::RequestHeaders);
}}},
{"RESPONSE_HEADERS_BYTES",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<HeadersByteSizeFormatter>(
HeadersByteSizeFormatter::HeaderType::ResponseHeaders);
}}},
{"RESPONSE_TRAILERS_BYTES",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<HeadersByteSizeFormatter>(
HeadersByteSizeFormatter::HeaderType::ResponseTrailers);
}}},
{"STREAM_INFO_REQ",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;
THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<RequestHeaderFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<RequestHeaderFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"TRACE_ID",
{CommandSyntaxChecker::COMMAND_ONLY, [](const std::string&, absl::optional<size_t>&) {
{CommandSyntaxChecker::COMMAND_ONLY, [](absl::string_view, absl::optional<size_t>) {
return std::make_unique<TraceIDFormatter>();
}}}});
}

FormatterProviderPtr BuiltInHttpCommandParser::parse(const std::string& command,
const std::string& subcommand,
absl::optional<size_t>& max_length) const {
FormatterProviderPtr BuiltInHttpCommandParser::parse(absl::string_view command,
absl::string_view subcommand,
absl::optional<size_t> max_length) const {
const FormatterProviderLookupTbl& providers = getKnownFormatters();

auto it = providers.find(command);
Expand Down
14 changes: 7 additions & 7 deletions source/common/formatter/http_specific_formatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class AccessLogTypeFormatter : public FormatterProvider {

class HeaderFormatter {
public:
HeaderFormatter(const std::string& main_header, const std::string& alternative_header,
HeaderFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

protected:
Expand Down Expand Up @@ -97,7 +97,7 @@ class HeadersByteSizeFormatter : public FormatterProvider {
*/
class RequestHeaderFormatter : public FormatterProvider, HeaderFormatter {
public:
RequestHeaderFormatter(const std::string& main_header, const std::string& alternative_header,
RequestHeaderFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

// FormatterProvider
Expand All @@ -114,7 +114,7 @@ class RequestHeaderFormatter : public FormatterProvider, HeaderFormatter {
*/
class ResponseHeaderFormatter : public FormatterProvider, HeaderFormatter {
public:
ResponseHeaderFormatter(const std::string& main_header, const std::string& alternative_header,
ResponseHeaderFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

// FormatterProvider
Expand All @@ -131,7 +131,7 @@ class ResponseHeaderFormatter : public FormatterProvider, HeaderFormatter {
*/
class ResponseTrailerFormatter : public FormatterProvider, HeaderFormatter {
public:
ResponseTrailerFormatter(const std::string& main_header, const std::string& alternative_header,
ResponseTrailerFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

// FormatterProvider
Expand Down Expand Up @@ -205,12 +205,12 @@ class BuiltInHttpCommandParser : public CommandParser {
BuiltInHttpCommandParser() = default;

// CommandParser
FormatterProviderPtr parse(const std::string& command, const std::string& subcommand,
absl::optional<size_t>& max_length) const override;
FormatterProviderPtr parse(absl::string_view command, absl::string_view subcommand,
absl::optional<size_t> max_length) const override;

private:
using FormatterProviderCreateFunc =
std::function<FormatterProviderPtr(const std::string&, absl::optional<size_t>&)>;
std::function<FormatterProviderPtr(absl::string_view, absl::optional<size_t>)>;

using FormatterProviderLookupTbl =
absl::flat_hash_map<absl::string_view, std::pair<CommandSyntaxChecker::CommandSyntaxFlags,
Expand Down
Loading