From 0c8331d741cdaec2e5034f8d3d408c019e2af59f Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Mon, 29 Apr 2024 23:58:36 +0000 Subject: [PATCH 1/6] Add URI_PEER_SAN string formatter Signed-off-by: Keith Mattix II --- .../common/formatter/stream_info_formatter.cc | 9 ++++ .../formatter/substitution_formatter_test.cc | 43 +++++++++++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/source/common/formatter/stream_info_formatter.cc b/source/common/formatter/stream_info_formatter.cc index 1aa75193225ff..5b014a2fa4429 100644 --- a/source/common/formatter/stream_info_formatter.cc +++ b/source/common/formatter/stream_info_formatter.cc @@ -9,6 +9,7 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_replace.h" +#include "substitution_format_utility.h" namespace Envoy { namespace Formatter { @@ -1206,6 +1207,14 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide return connection_info.subjectPeerCertificate(); }); }}}, + {"UPSTREAM_PEER_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanPeerCertificate(), ","); + }); + }}}, {"DOWNSTREAM_LOCAL_ADDRESS", {CommandSyntaxChecker::COMMAND_ONLY, [](const std::string&, absl::optional) { diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index 04c25bf76f1f2..4cf12768727f5 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -1090,7 +1090,6 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { StreamInfoFormatter upstream_format("VIRTUAL_CLUSTER_NAME"); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); } - { // Use a local stream info for these tests as as setSslConnection can only be called once. NiceMock stream_info; @@ -1103,7 +1102,6 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } - { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_PEER_URI_SAN"); @@ -1856,7 +1854,46 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue(expected_cert))); } - + { + // Use a local stream info for these tests as as setSslConnection can only be called once. + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_URI_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san"}; + EXPECT_CALL(*connection_info, uriSanPeerCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san"))); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_URI_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san1", "san2"}; + EXPECT_CALL(*connection_info, uriSanPeerCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_URI_SAN"); + auto connection_info = std::make_shared(); + EXPECT_CALL(*connection_info, uriSanPeerCertificate()) + .WillRepeatedly(Return(std::vector())); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); + StreamInfoFormatter upstream_format("UPSTREAM_PEER_URI_SAN"); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_SUBJECT"); From e28881979df7be8861a0884717919201f6b8eece Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Mon, 6 May 2024 20:35:13 +0000 Subject: [PATCH 2/6] Fix formatting Signed-off-by: Keith Mattix II --- changelogs/current.yaml | 6 +- .../observability/access_log/usage.rst | 31 +- .../common/formatter/stream_info_formatter.cc | 1857 +++++++++-------- .../formatter/substitution_formatter_test.cc | 201 +- 4 files changed, 1240 insertions(+), 855 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 0d6985e8d9574..c0d54f3bbb722 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -124,7 +124,11 @@ new_features: - area: redis change: | Added support for `inline commands `_. - +- area: access_log + change: | + added new ``access_log`` command operators to retrieve upstream connection information change: ``%UPSTREAM_PEER_URI_SAN%``, + ``%UPSTREAM_PEER_IP_SAN%``, ``%UPSTREAM_PEER_DNS_SAN%``, ``%UPSTREAM_LOCAL_URI_SAN%``, ``%UPSTREAM_LOCAL_DNS_SAN%``, + ``%UPSTREAM_LOCAL_IP_SAN%``. deprecated: - area: tracing change: | diff --git a/docs/root/configuration/observability/access_log/usage.rst b/docs/root/configuration/observability/access_log/usage.rst index ce9defc7c64dd..e91e06d13ceda 100644 --- a/docs/root/configuration/observability/access_log/usage.rst +++ b/docs/root/configuration/observability/access_log/usage.rst @@ -1169,7 +1169,36 @@ UDP UPSTREAM_PEER_CERT_V_END can be customized using a `format string `_. See :ref:`START_TIME ` for additional format specifiers and examples. - +%UPSTREAM_PEER_URI_SAN% + HTTP/TCP/THRIFT + The URIs present in the SAN of the peer certificate used to establish the upstream TLS connection. + UDP + Not implemented ("-"). +%UPSTREAM_PEER_DNS_SAN% + HTTP/TCP/THRIFT + The DNS names present in the SAN of the peer certificate used to establish the upstream TLS connection. + UDP + Not implemented ("-"). +%UPSTREAM_PEER_IP_SAN% + HTTP/TCP/THRIFT + The ip addresses present in the SAN of the peer certificate used to establish the upstream TLS connection. + UDP + Not implemented ("-"). +%UPSTREAM_LOCAL_URI_SAN% + HTTP/TCP/THRIFT + The URIs present in the SAN of the local certificate used to establish the upstream TLS connection. + UDP + Not implemented ("-"). +%UPSTREAM_LOCAL_IP_SAN% + HTTP/TCP/THRIFT + The ip addresses present in the SAN of the local certificate used to establish the upstream TLS connection. + UDP + Not implemented ("-"). +%UPSTREAM_LOCAL_DNS_SAN% + HTTP/TCP/THRIFT + The DNS names present in the SAN of the local certificate used to establish the upstream TLS connection. + UDP + Not implemented ("-"). %HOSTNAME% The system hostname. diff --git a/source/common/formatter/stream_info_formatter.cc b/source/common/formatter/stream_info_formatter.cc index 5b014a2fa4429..c74b0b5c5e464 100644 --- a/source/common/formatter/stream_info_formatter.cc +++ b/source/common/formatter/stream_info_formatter.cc @@ -796,855 +796,1014 @@ class StreamInfoUpstreamSslConnectionInfoFormatterProvider : public StreamInfoFo }; const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProviders() { - CONSTRUCT_ON_FIRST_USE( - StreamInfoFormatterProviderLookupTable, - { - {"REQUEST_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.lastDownstreamRxByteReceived(); - }); - }}}, - {"REQUEST_TX_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.lastUpstreamTxByteSent(); - }); - }}}, - {"RESPONSE_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.firstUpstreamRxByteReceived(); - }); - }}}, - {"RESPONSE_TX_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - auto downstream = timing.lastDownstreamTxByteSent(); - auto upstream = timing.firstUpstreamRxByteReceived(); - - absl::optional result; - if (downstream && upstream) { - result = downstream.value() - upstream.value(); - } - - return result; - }); - }}}, - {"DOWNSTREAM_HANDSHAKE_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.downstreamHandshakeComplete(); - }); - }}}, - {"ROUNDTRIP_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.lastDownstreamAckReceived(); - }); - }}}, - {"BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesReceived(); - }); - }}}, - {"BYTES_RETRANSMITTED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesRetransmitted(); - }); - }}}, - {"PACKETS_RETRANSMITTED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.packetsRetransmitted(); - }); - }}}, - {"UPSTREAM_WIRE_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesReceived() : 0; - }); - }}}, - {"UPSTREAM_HEADER_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesReceived() : 0; - }); - }}}, - {"DOWNSTREAM_WIRE_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesReceived() : 0; - }); - }}}, - {"DOWNSTREAM_HEADER_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesReceived() : 0; - }); - }}}, - {"PROTOCOL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return SubstitutionFormatUtils::protocolToString(stream_info.protocol()); - }); - }}}, - {"UPSTREAM_PROTOCOL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.upstreamInfo() - ? SubstitutionFormatUtils::protocolToString( - stream_info.upstreamInfo()->upstreamProtocol()) - : absl::nullopt; - }); - }}}, - {"RESPONSE_CODE", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.responseCode().value_or(0); - }); - }}}, - {"RESPONSE_CODE_DETAILS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.responseCodeDetails(); - }); - }}}, - {"CONNECTION_TERMINATION_DETAILS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.connectionTerminationDetails(); - }); - }}}, - {"BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesSent(); - }); - }}}, - {"UPSTREAM_WIRE_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesSent() : 0; - }); - }}}, - {"UPSTREAM_HEADER_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesSent() : 0; - }); - }}}, - {"DOWNSTREAM_WIRE_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesSent() : 0; - }); - }}}, - {"DOWNSTREAM_HEADER_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesSent() : 0; - }); - }}}, - {"DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.currentDuration(); - }); - }}}, - {"COMMON_DURATION", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& sub_command, absl::optional) { - return CommonDurationFormatter::create(sub_command); - }}}, - {"RESPONSE_FLAGS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return StreamInfo::ResponseFlagUtils::toShortString(stream_info); - }); - }}}, - {"RESPONSE_FLAGS_LONG", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return StreamInfo::ResponseFlagUtils::toString(stream_info); - }); - }}}, - {"UPSTREAM_HOST", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> std::shared_ptr { - if (stream_info.upstreamInfo() && stream_info.upstreamInfo()->upstreamHost()) { - return stream_info.upstreamInfo()->upstreamHost()->address(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_CONNECTION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - uint64_t upstream_connection_id = 0; - if (stream_info.upstreamInfo().has_value()) { - upstream_connection_id = - stream_info.upstreamInfo()->upstreamConnectionId().value_or(0); - } - return upstream_connection_id; - }); - }}}, - {"UPSTREAM_CLUSTER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - std::string upstream_cluster_name; - if (stream_info.upstreamClusterInfo().has_value() && - stream_info.upstreamClusterInfo().value() != nullptr) { - upstream_cluster_name = - stream_info.upstreamClusterInfo().value()->observabilityName(); - } - - return upstream_cluster_name.empty() - ? absl::nullopt - : absl::make_optional(upstream_cluster_name); - }); - }}}, - {"UPSTREAM_LOCAL_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> std::shared_ptr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) - -> std::shared_ptr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_LOCAL_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const StreamInfo::StreamInfo& stream_info) - -> std::shared_ptr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> std::shared_ptr { - if (stream_info.upstreamInfo() && stream_info.upstreamInfo()->upstreamHost()) { - return stream_info.upstreamInfo()->upstreamHost()->address(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) - -> std::shared_ptr { - if (stream_info.upstreamInfo() && stream_info.upstreamInfo()->upstreamHost()) { - return stream_info.upstreamInfo()->upstreamHost()->address(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const StreamInfo::StreamInfo& stream_info) - -> std::shared_ptr { - if (stream_info.upstreamInfo() && stream_info.upstreamInfo()->upstreamHost()) { - return stream_info.upstreamInfo()->upstreamHost()->address(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_REQUEST_ATTEMPT_COUNT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.attemptCount().value_or(0); - }); - }}}, - {"UPSTREAM_TLS_CIPHER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.ciphersuiteString(); - }); - }}}, - {"UPSTREAM_TLS_VERSION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.tlsVersion(); - }); - }}}, - {"UPSTREAM_TLS_SESSION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sessionId(); - }); - }}}, - {"UPSTREAM_PEER_ISSUER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.issuerPeerCertificate(); - }); - }}}, - {"UPSTREAM_PEER_CERT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.urlEncodedPemEncodedPeerCertificate(); - }); - }}}, - {"UPSTREAM_PEER_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectPeerCertificate(); - }); - }}}, - {"UPSTREAM_PEER_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.uriSanPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().localAddress(); - }); - }}}, - {"DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().localAddress(); - }); - }}}, - {"DOWNSTREAM_LOCAL_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().localAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().remoteAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().remoteAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().remoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().directRemoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().directRemoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().directRemoteAddress(); - }); - }}}, - {"CONNECTION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().connectionID().value_or(0); - }); - }}}, - {"REQUESTED_SERVER_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamAddressProvider().requestedServerName().empty()) { - result = std::string( - stream_info.downstreamAddressProvider().requestedServerName()); - } - return result; - }); - }}}, - {"ROUTE_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - std::string route_name = stream_info.getRouteName(); - if (!route_name.empty()) { - result = route_name; - } - return result; - }); - }}}, - {"DOWNSTREAM_PEER_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.uriSanPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.dnsSansPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.ipSansPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.uriSanLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.dnsSansLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.ipSansLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_LOCAL_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectLocalCertificate(); - }); - }}}, - {"DOWNSTREAM_TLS_SESSION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sessionId(); - }); - }}}, - {"DOWNSTREAM_TLS_CIPHER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.ciphersuiteString(); - }); - }}}, - {"DOWNSTREAM_TLS_VERSION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.tlsVersion(); - }); - }}}, - {"DOWNSTREAM_PEER_FINGERPRINT_256", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sha256PeerCertificateDigest(); - }); - }}}, - {"DOWNSTREAM_PEER_FINGERPRINT_1", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sha1PeerCertificateDigest(); - }); - }}}, - {"DOWNSTREAM_PEER_SERIAL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.serialNumberPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_PEER_ISSUER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.issuerPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_PEER_CERT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.urlEncodedPemEncodedPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_TRANSPORT_FAILURE_REASON", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamTransportFailureReason().empty()) { - result = absl::StrReplaceAll(stream_info.downstreamTransportFailureReason(), - {{" ", "_"}}); - } - return result; - }); - }}}, - {"UPSTREAM_TRANSPORT_FAILURE_REASON", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (stream_info.upstreamInfo().has_value() && - !stream_info.upstreamInfo() - .value() - .get() - .upstreamTransportFailureReason() - .empty()) { - result = - stream_info.upstreamInfo().value().get().upstreamTransportFailureReason(); - } - if (result) { - std::replace(result->begin(), result->end(), ' ', '_'); - } - return result; - }); - }}}, - {"HOSTNAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - absl::optional hostname = SubstitutionFormatUtils::getHostname(); - return std::make_unique( - [hostname](const StreamInfo::StreamInfo&) { return hostname; }); - }}}, - {"FILTER_CHAIN_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - if (const auto info = stream_info.downstreamAddressProvider().filterChainInfo(); - info.has_value()) { - if (!info->name().empty()) { - return std::string(info->name()); - } - } - return absl::nullopt; - }); - }}}, - {"VIRTUAL_CLUSTER_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - return stream_info.virtualClusterName(); - }); - }}}, - {"TLS_JA3_FINGERPRINT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamAddressProvider().ja3Hash().empty()) { - result = std::string(stream_info.downstreamAddressProvider().ja3Hash()); - } - return result; - }); - }}}, - {"STREAM_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - auto provider = stream_info.getStreamIdProvider(); - if (!provider.has_value()) { - return {}; - } - auto id = provider->toStringView(); - if (!id.has_value()) { - return {}; - } - return absl::make_optional(id.value()); - }); - }}}, - {"START_TIME", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique( - format, - std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - return stream_info.startTime(); - })); - }}}, - {"EMIT_TIME", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique( - format, - std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - return stream_info.timeSource().systemTime(); - })); - }}}, - {"DYNAMIC_METADATA", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& format, absl::optional max_length) { - std::string filter_namespace; - std::vector path; - - SubstitutionFormatUtils::parseSubcommand(format, ':', filter_namespace, path); - return std::make_unique(filter_namespace, path, max_length); - }}}, - - {"CLUSTER_METADATA", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& format, absl::optional max_length) { - std::string filter_namespace; - std::vector path; - - SubstitutionFormatUtils::parseSubcommand(format, ':', filter_namespace, path); - return std::make_unique(filter_namespace, path, max_length); - }}}, - {"UPSTREAM_METADATA", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& format, absl::optional max_length) { - std::string filter_namespace; - std::vector path; - - SubstitutionFormatUtils::parseSubcommand(format, ':', filter_namespace, path); - return std::make_unique(filter_namespace, path, - max_length); - }}}, - {"FILTER_STATE", - {CommandSyntaxChecker::PARAMS_OPTIONAL | CommandSyntaxChecker::LENGTH_ALLOWED, - [](const std::string& format, absl::optional max_length) { - return FilterStateFormatter::create(format, max_length, false); - }}}, - {"UPSTREAM_FILTER_STATE", - {CommandSyntaxChecker::PARAMS_OPTIONAL | CommandSyntaxChecker::LENGTH_ALLOWED, - [](const std::string& format, absl::optional max_length) { - return FilterStateFormatter::create(format, max_length, true); - }}}, - {"DOWNSTREAM_PEER_CERT_V_START", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"DOWNSTREAM_PEER_CERT_V_END", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"UPSTREAM_PEER_CERT_V_START", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"UPSTREAM_PEER_CERT_V_END", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"ENVIRONMENT", - {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, - [](const std::string& key, absl::optional max_length) { - return std::make_unique(key, max_length); - }}}, - {"UPSTREAM_CONNECTION_POOL_READY_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, const absl::optional&) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - if (auto upstream_info = stream_info.upstreamInfo(); - upstream_info.has_value()) { - if (auto connection_pool_callback_latency = - upstream_info.value() - .get() - .upstreamTiming() - .connectionPoolCallbackLatency(); - connection_pool_callback_latency.has_value()) { - return connection_pool_callback_latency; - } - } - return absl::nullopt; - }); - }}}, - }); + CONSTRUCT_ON_FIRST_USE(StreamInfoFormatterProviderLookupTable, + { + {"REQUEST_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.lastDownstreamRxByteReceived(); + }); + }}}, + {"REQUEST_TX_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.lastUpstreamTxByteSent(); + }); + }}}, + {"RESPONSE_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.firstUpstreamRxByteReceived(); + }); + }}}, + {"RESPONSE_TX_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + auto downstream = timing.lastDownstreamTxByteSent(); + auto upstream = timing.firstUpstreamRxByteReceived(); + + absl::optional result; + if (downstream && upstream) { + result = downstream.value() - upstream.value(); + } + + return result; + }); + }}}, + {"DOWNSTREAM_HANDSHAKE_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.downstreamHandshakeComplete(); + }); + }}}, + {"ROUNDTRIP_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.lastDownstreamAckReceived(); + }); + }}}, + {"BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesReceived(); + }); + }}}, + {"BYTES_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesRetransmitted(); + }); + }}}, + {"PACKETS_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.packetsRetransmitted(); + }); + }}}, + {"UPSTREAM_WIRE_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesReceived() : 0; + }); + }}}, + {"UPSTREAM_HEADER_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesReceived() : 0; + }); + }}}, + {"DOWNSTREAM_WIRE_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesReceived() : 0; + }); + }}}, + {"DOWNSTREAM_HEADER_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesReceived() : 0; + }); + }}}, + {"PROTOCOL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return SubstitutionFormatUtils::protocolToString( + stream_info.protocol()); + }); + }}}, + {"UPSTREAM_PROTOCOL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.upstreamInfo() + ? SubstitutionFormatUtils::protocolToString( + stream_info.upstreamInfo() + ->upstreamProtocol()) + : absl::nullopt; + }); + }}}, + {"RESPONSE_CODE", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.responseCode().value_or(0); + }); + }}}, + {"RESPONSE_CODE_DETAILS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.responseCodeDetails(); + }); + }}}, + {"CONNECTION_TERMINATION_DETAILS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.connectionTerminationDetails(); + }); + }}}, + {"BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesSent(); + }); + }}}, + {"UPSTREAM_WIRE_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesSent() : 0; + }); + }}}, + {"UPSTREAM_HEADER_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesSent() : 0; + }); + }}}, + {"DOWNSTREAM_WIRE_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesSent() : 0; + }); + }}}, + {"DOWNSTREAM_HEADER_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesSent() : 0; + }); + }}}, + {"DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.currentDuration(); + }); + }}}, + {"COMMON_DURATION", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& sub_command, absl::optional) { + return CommonDurationFormatter::create(sub_command); + }}}, + {"RESPONSE_FLAGS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return StreamInfo::ResponseFlagUtils::toShortString( + stream_info); + }); + }}}, + {"RESPONSE_FLAGS_LONG", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return StreamInfo::ResponseFlagUtils::toString(stream_info); + }); + }}}, + {"UPSTREAM_HOST", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> std::shared_ptr< + const Envoy::Network::Address::Instance> { + if (stream_info.upstreamInfo() && + stream_info.upstreamInfo()->upstreamHost()) { + return stream_info.upstreamInfo() + ->upstreamHost() + ->address(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_CONNECTION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + uint64_t upstream_connection_id = 0; + if (stream_info.upstreamInfo().has_value()) { + upstream_connection_id = stream_info.upstreamInfo() + ->upstreamConnectionId() + .value_or(0); + } + return upstream_connection_id; + }); + }}}, + {"UPSTREAM_CLUSTER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + std::string upstream_cluster_name; + if (stream_info.upstreamClusterInfo().has_value() && + stream_info.upstreamClusterInfo().value() != nullptr) { + upstream_cluster_name = stream_info.upstreamClusterInfo() + .value() + ->observabilityName(); + } + + return upstream_cluster_name.empty() + ? absl::nullopt + : absl::make_optional( + upstream_cluster_name); + }); + }}}, + {"UPSTREAM_LOCAL_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> std::shared_ptr< + const Envoy::Network::Address::Instance> { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo() + .value() + .get() + .upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) + -> std::shared_ptr< + const Envoy::Network::Address::Instance> { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo() + .value() + .get() + .upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_LOCAL_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const StreamInfo::StreamInfo& stream_info) + -> std::shared_ptr< + const Envoy::Network::Address::Instance> { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo() + .value() + .get() + .upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> std::shared_ptr< + const Envoy::Network::Address::Instance> { + if (stream_info.upstreamInfo() && + stream_info.upstreamInfo()->upstreamHost()) { + return stream_info.upstreamInfo() + ->upstreamHost() + ->address(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) + -> std::shared_ptr< + const Envoy::Network::Address::Instance> { + if (stream_info.upstreamInfo() && + stream_info.upstreamInfo()->upstreamHost()) { + return stream_info.upstreamInfo() + ->upstreamHost() + ->address(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const StreamInfo::StreamInfo& stream_info) + -> std::shared_ptr< + const Envoy::Network::Address::Instance> { + if (stream_info.upstreamInfo() && + stream_info.upstreamInfo()->upstreamHost()) { + return stream_info.upstreamInfo() + ->upstreamHost() + ->address(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_REQUEST_ATTEMPT_COUNT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.attemptCount().value_or(0); + }); + }}}, + {"UPSTREAM_TLS_CIPHER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.ciphersuiteString(); + }); + }}}, + {"UPSTREAM_TLS_VERSION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.tlsVersion(); + }); + }}}, + {"UPSTREAM_TLS_SESSION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sessionId(); + }); + }}}, + {"UPSTREAM_PEER_ISSUER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.issuerPeerCertificate(); + }); + }}}, + {"UPSTREAM_PEER_CERT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.urlEncodedPemEncodedPeerCertificate(); + }); + }}}, + {"UPSTREAM_PEER_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_LOCAL_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .localAddress(); + }); + }}}, + {"DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .localAddress(); + }); + }}}, + {"DOWNSTREAM_LOCAL_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .localAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .remoteAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .remoteAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .remoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .directRemoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .directRemoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .directRemoteAddress(); + }); + }}}, + {"CONNECTION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .connectionID() + .value_or(0); + }); + }}}, + {"REQUESTED_SERVER_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamAddressProvider() + .requestedServerName() + .empty()) { + result = + std::string(stream_info.downstreamAddressProvider() + .requestedServerName()); + } + return result; + }); + }}}, + {"ROUTE_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + std::string route_name = stream_info.getRouteName(); + if (!route_name.empty()) { + result = route_name; + } + return result; + }); + }}}, + {"DOWNSTREAM_PEER_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanPeerCertificate(), + ","); + }); + }}}, + {"DOWNSTREAM_PEER_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.dnsSansPeerCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.ipSansPeerCertificate(), + ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.uriSanLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.dnsSansLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.ipSansLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_LOCAL_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectLocalCertificate(); + }); + }}}, + {"DOWNSTREAM_TLS_SESSION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sessionId(); + }); + }}}, + {"DOWNSTREAM_TLS_CIPHER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.ciphersuiteString(); + }); + }}}, + {"DOWNSTREAM_TLS_VERSION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.tlsVersion(); + }); + }}}, + {"DOWNSTREAM_PEER_FINGERPRINT_256", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sha256PeerCertificateDigest(); + }); + }}}, + {"DOWNSTREAM_PEER_FINGERPRINT_1", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sha1PeerCertificateDigest(); + }); + }}}, + {"DOWNSTREAM_PEER_SERIAL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.serialNumberPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_PEER_ISSUER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.issuerPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_PEER_CERT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.urlEncodedPemEncodedPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_TRANSPORT_FAILURE_REASON", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamTransportFailureReason() + .empty()) { + result = absl::StrReplaceAll( + stream_info.downstreamTransportFailureReason(), + {{" ", "_"}}); + } + return result; + }); + }}}, + {"UPSTREAM_TRANSPORT_FAILURE_REASON", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (stream_info.upstreamInfo().has_value() && + !stream_info.upstreamInfo() + .value() + .get() + .upstreamTransportFailureReason() + .empty()) { + result = stream_info.upstreamInfo() + .value() + .get() + .upstreamTransportFailureReason(); + } + if (result) { + std::replace(result->begin(), result->end(), ' ', '_'); + } + return result; + }); + }}}, + {"HOSTNAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + absl::optional hostname = + SubstitutionFormatUtils::getHostname(); + return std::make_unique( + [hostname](const StreamInfo::StreamInfo&) { + return hostname; + }); + }}}, + {"FILTER_CHAIN_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + if (const auto info = stream_info.downstreamAddressProvider() + .filterChainInfo(); + info.has_value()) { + if (!info->name().empty()) { + return std::string(info->name()); + } + } + return absl::nullopt; + }); + }}}, + {"VIRTUAL_CLUSTER_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + return stream_info.virtualClusterName(); + }); + }}}, + {"TLS_JA3_FINGERPRINT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamAddressProvider() + .ja3Hash() + .empty()) { + result = std::string( + stream_info.downstreamAddressProvider().ja3Hash()); + } + return result; + }); + }}}, + {"STREAM_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + auto provider = stream_info.getStreamIdProvider(); + if (!provider.has_value()) { + return {}; + } + auto id = provider->toStringView(); + if (!id.has_value()) { + return {}; + } + return absl::make_optional(id.value()); + }); + }}}, + {"START_TIME", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique( + format, + std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + return stream_info.startTime(); + })); + }}}, + {"EMIT_TIME", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique( + format, + std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + return stream_info.timeSource().systemTime(); + })); + }}}, + {"DYNAMIC_METADATA", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& format, absl::optional max_length) { + std::string filter_namespace; + std::vector path; + + SubstitutionFormatUtils::parseSubcommand(format, ':', + filter_namespace, path); + return std::make_unique( + filter_namespace, path, max_length); + }}}, + + {"CLUSTER_METADATA", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& format, absl::optional max_length) { + std::string filter_namespace; + std::vector path; + + SubstitutionFormatUtils::parseSubcommand(format, ':', + filter_namespace, path); + return std::make_unique( + filter_namespace, path, max_length); + }}}, + {"UPSTREAM_METADATA", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& format, absl::optional max_length) { + std::string filter_namespace; + std::vector path; + + SubstitutionFormatUtils::parseSubcommand(format, ':', + filter_namespace, path); + return std::make_unique( + filter_namespace, path, max_length); + }}}, + {"FILTER_STATE", + {CommandSyntaxChecker::PARAMS_OPTIONAL | + CommandSyntaxChecker::LENGTH_ALLOWED, + [](const std::string& format, absl::optional max_length) { + return FilterStateFormatter::create(format, max_length, false); + }}}, + {"UPSTREAM_FILTER_STATE", + {CommandSyntaxChecker::PARAMS_OPTIONAL | + CommandSyntaxChecker::LENGTH_ALLOWED, + [](const std::string& format, absl::optional max_length) { + return FilterStateFormatter::create(format, max_length, true); + }}}, + {"DOWNSTREAM_PEER_CERT_V_START", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"DOWNSTREAM_PEER_CERT_V_END", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"UPSTREAM_PEER_CERT_V_START", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"UPSTREAM_PEER_CERT_V_END", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"UPSTREAM_PEER_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanPeerCertificate(), + ","); + }); + }}}, + {"UPSTREAM_PEER_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.dnsSansPeerCertificate(), ","); + }); + }}}, + {"UPSTREAM_PEER_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.ipSansPeerCertificate(), + ","); + }); + }}}, + {"UPSTREAM_LOCAL_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.uriSanLocalCertificate(), ","); + }); + }}}, + {"UPSTREAM_LOCAL_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.dnsSansLocalCertificate(), ","); + }); + }}}, + {"UPSTREAM_LOCAL_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.ipSansLocalCertificate(), ","); + }); + }}}, + {"ENVIRONMENT", + {CommandSyntaxChecker::PARAMS_REQUIRED | + CommandSyntaxChecker::LENGTH_ALLOWED, + [](const std::string& key, absl::optional max_length) { + return std::make_unique(key, max_length); + }}}, + {"UPSTREAM_CONNECTION_POOL_READY_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, const absl::optional&) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + if (auto upstream_info = stream_info.upstreamInfo(); + upstream_info.has_value()) { + if (auto connection_pool_callback_latency = + upstream_info.value() + .get() + .upstreamTiming() + .connectionPoolCallbackLatency(); + connection_pool_callback_latency.has_value()) { + return connection_pool_callback_latency; + } + } + return absl::nullopt; + }); + }}}, + }); } } // namespace Formatter diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index 4cf12768727f5..85536e4eec8cf 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -1142,7 +1142,6 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } - { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_PEER_DNS_SAN"); @@ -1183,7 +1182,6 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } - { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_PEER_IP_SAN"); @@ -1212,7 +1210,6 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } - { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_LOCAL_URI_SAN"); @@ -1330,7 +1327,6 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } - { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_LOCAL_SUBJECT"); @@ -1894,6 +1890,203 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + { + // Use a local stream info for these tests as as setSslConnection can only be called once. + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_DNS_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san"}; + EXPECT_CALL(*connection_info, dnsSansPeerCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san"))); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_DNS_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san1", "san2"}; + EXPECT_CALL(*connection_info, dnsSansPeerCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_DNS_SAN"); + auto connection_info = std::make_shared(); + EXPECT_CALL(*connection_info, dnsSansPeerCertificate()) + .WillRepeatedly(Return(std::vector())); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); + StreamInfoFormatter upstream_format("UPSTREAM_PEER_DNS_SAN"); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + // Use a local stream info for these tests as as setSslConnection can only be called once. + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_IP_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san"}; + EXPECT_CALL(*connection_info, ipSansPeerCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san"))); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_IP_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san1", "san2"}; + EXPECT_CALL(*connection_info, ipSansPeerCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_PEER_IP_SAN"); + auto connection_info = std::make_shared(); + EXPECT_CALL(*connection_info, ipSansPeerCertificate()) + .WillRepeatedly(Return(std::vector())); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); + StreamInfoFormatter upstream_format("UPSTREAM_PEER_IP_SAN"); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_DNS_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san"}; + EXPECT_CALL(*connection_info, dnsSansLocalCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san"))); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_DNS_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san1", "san2"}; + EXPECT_CALL(*connection_info, dnsSansLocalCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_DNS_SAN"); + auto connection_info = std::make_shared(); + EXPECT_CALL(*connection_info, dnsSansLocalCertificate()) + .WillRepeatedly(Return(std::vector())); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_DNS_SAN"); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_URI_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san"}; + EXPECT_CALL(*connection_info, uriSanLocalCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san"))); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_URI_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san1", "san2"}; + EXPECT_CALL(*connection_info, uriSanLocalCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_URI_SAN"); + auto connection_info = std::make_shared(); + EXPECT_CALL(*connection_info, uriSanLocalCertificate()) + .WillRepeatedly(Return(std::vector())); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_URI_SAN"); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_IP_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san"}; + EXPECT_CALL(*connection_info, ipSansLocalCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san"))); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_IP_SAN"); + auto connection_info = std::make_shared(); + const std::vector sans{"san1", "san2"}; + EXPECT_CALL(*connection_info, ipSansLocalCertificate()).WillRepeatedly(Return(sans)); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + } + { + NiceMock stream_info; + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_IP_SAN"); + auto connection_info = std::make_shared(); + EXPECT_CALL(*connection_info, ipSansLocalCertificate()) + .WillRepeatedly(Return(std::vector())); + stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } + { + NiceMock stream_info; + stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); + StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_IP_SAN"); + EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::nullValue())); + } { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_SUBJECT"); From d3e0eb0a3196ddd543f0617fb5dd1bf1e5ce772c Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Mon, 13 May 2024 18:58:42 +0000 Subject: [PATCH 3/6] Fix broken tests Signed-off-by: Keith Mattix II --- .../formatter/substitution_formatter_test.cc | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index 85536e4eec8cf..e236a810fcbde 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -1857,7 +1857,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san"}; EXPECT_CALL(*connection_info, uriSanPeerCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); @@ -1868,7 +1868,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, uriSanPeerCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); } { @@ -1877,7 +1877,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, uriSanPeerCertificate()) .WillRepeatedly(Return(std::vector())); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); @@ -1897,7 +1897,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san"}; EXPECT_CALL(*connection_info, dnsSansPeerCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); @@ -1908,7 +1908,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, dnsSansPeerCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); } { @@ -1917,7 +1917,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, dnsSansPeerCertificate()) .WillRepeatedly(Return(std::vector())); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); @@ -1937,7 +1937,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san"}; EXPECT_CALL(*connection_info, ipSansPeerCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); @@ -1948,7 +1948,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, ipSansPeerCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); } { @@ -1957,7 +1957,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, ipSansPeerCertificate()) .WillRepeatedly(Return(std::vector())); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); @@ -1976,7 +1976,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san"}; EXPECT_CALL(*connection_info, dnsSansLocalCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); @@ -1987,7 +1987,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, dnsSansLocalCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); } { @@ -1996,7 +1996,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, dnsSansLocalCertificate()) .WillRepeatedly(Return(std::vector())); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); @@ -2015,7 +2015,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san"}; EXPECT_CALL(*connection_info, uriSanLocalCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); @@ -2026,7 +2026,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, uriSanLocalCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); } { @@ -2035,7 +2035,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, uriSanLocalCertificate()) .WillRepeatedly(Return(std::vector())); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); @@ -2054,7 +2054,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san"}; EXPECT_CALL(*connection_info, ipSansLocalCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san", upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); @@ -2065,7 +2065,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, ipSansLocalCertificate()).WillRepeatedly(Return(sans)); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); } { @@ -2074,7 +2074,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, ipSansLocalCertificate()) .WillRepeatedly(Return(std::vector())); - stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); + stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); From 1a965fd5b92ccef3049c22562beac459f590e13e Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Wed, 15 May 2024 15:53:58 +0000 Subject: [PATCH 4/6] Fix format Signed-off-by: Keith Mattix II --- .../common/formatter/stream_info_formatter.cc | 1551 +++++++++-------- 1 file changed, 817 insertions(+), 734 deletions(-) diff --git a/source/common/formatter/stream_info_formatter.cc b/source/common/formatter/stream_info_formatter.cc index b5c585eedf6d5..162e35bd470b3 100644 --- a/source/common/formatter/stream_info_formatter.cc +++ b/source/common/formatter/stream_info_formatter.cc @@ -862,740 +862,823 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide result = downstream.value() - upstream.value(); } - return result; - }); - }}}, - {"DOWNSTREAM_HANDSHAKE_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.downstreamHandshakeComplete(); - }); - }}}, - {"ROUNDTRIP_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.lastDownstreamAckReceived(); - }); - }}}, - {"BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesReceived(); - }); - }}}, - {"BYTES_RETRANSMITTED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesRetransmitted(); - }); - }}}, - {"PACKETS_RETRANSMITTED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.packetsRetransmitted(); - }); - }}}, - {"UPSTREAM_WIRE_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesReceived() : 0; - }); - }}}, - {"UPSTREAM_HEADER_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesReceived() : 0; - }); - }}}, - {"DOWNSTREAM_WIRE_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesReceived() : 0; - }); - }}}, - {"DOWNSTREAM_HEADER_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesReceived() : 0; - }); - }}}, - {"PROTOCOL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return SubstitutionFormatUtils::protocolToString(stream_info.protocol()); - }); - }}}, - {"UPSTREAM_PROTOCOL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.upstreamInfo() - ? SubstitutionFormatUtils::protocolToString( - stream_info.upstreamInfo()->upstreamProtocol()) - : absl::nullopt; - }); - }}}, - {"RESPONSE_CODE", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.responseCode().value_or(0); - }); - }}}, - {"RESPONSE_CODE_DETAILS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.responseCodeDetails(); - }); - }}}, - {"CONNECTION_TERMINATION_DETAILS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.connectionTerminationDetails(); - }); - }}}, - {"BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesSent(); - }); - }}}, - {"UPSTREAM_WIRE_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesSent() : 0; - }); - }}}, - {"UPSTREAM_HEADER_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesSent() : 0; - }); - }}}, - {"DOWNSTREAM_WIRE_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesSent() : 0; - }); - }}}, - {"DOWNSTREAM_HEADER_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesSent() : 0; - }); - }}}, - {"DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.currentDuration(); - }); - }}}, - {"COMMON_DURATION", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& sub_command, absl::optional) { - return CommonDurationFormatter::create(sub_command); - }}}, - {"RESPONSE_FLAGS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return StreamInfo::ResponseFlagUtils::toShortString(stream_info); - }); - }}}, - {"RESPONSE_FLAGS_LONG", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return StreamInfo::ResponseFlagUtils::toString(stream_info); - }); - }}}, - {"UPSTREAM_HOST_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - const auto opt_ref = stream_info.upstreamInfo(); - if (!opt_ref.has_value()) { - return absl::nullopt; - } - const auto host = opt_ref->upstreamHost(); - if (host == nullptr) { - return absl::nullopt; - } - std::string host_name = host->hostname(); - if (host_name.empty()) { - // If no hostname is available, the main address is used. - return host->address()->asString(); - } - return absl::make_optional(std::move(host_name)); - }); - }}}, - {"UPSTREAM_HOST", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - const auto opt_ref = stream_info.upstreamInfo(); - if (!opt_ref.has_value()) { - return nullptr; - } - const auto host = opt_ref->upstreamHost(); - if (host == nullptr) { - return nullptr; - } - return host->address(); - }); - }}}, - {"UPSTREAM_CONNECTION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - uint64_t upstream_connection_id = 0; - if (stream_info.upstreamInfo().has_value()) { - upstream_connection_id = - stream_info.upstreamInfo()->upstreamConnectionId().value_or(0); - } - return upstream_connection_id; - }); - }}}, - {"UPSTREAM_CLUSTER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - std::string upstream_cluster_name; - if (stream_info.upstreamClusterInfo().has_value() && - stream_info.upstreamClusterInfo().value() != nullptr) { - upstream_cluster_name = - stream_info.upstreamClusterInfo().value()->observabilityName(); - } - - return upstream_cluster_name.empty() - ? absl::nullopt - : absl::make_optional(upstream_cluster_name); - }); - }}}, - {"UPSTREAM_LOCAL_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_LOCAL_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - return getUpstreamRemoteAddress(stream_info); - }); - }}}, - {"UPSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - return getUpstreamRemoteAddress(stream_info); - }); - }}}, - {"UPSTREAM_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - return getUpstreamRemoteAddress(stream_info); - }); - }}}, - {"UPSTREAM_REQUEST_ATTEMPT_COUNT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.attemptCount().value_or(0); - }); - }}}, - {"UPSTREAM_TLS_CIPHER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.ciphersuiteString(); - }); - }}}, - {"UPSTREAM_TLS_VERSION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.tlsVersion(); - }); - }}}, - {"UPSTREAM_TLS_SESSION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sessionId(); - }); - }}}, - {"UPSTREAM_PEER_ISSUER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.issuerPeerCertificate(); - }); - }}}, - {"UPSTREAM_PEER_CERT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.urlEncodedPemEncodedPeerCertificate(); - }); - }}}, - {"UPSTREAM_PEER_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_LOCAL_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().localAddress(); - }); - }}}, - {"DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().localAddress(); - }); - }}}, - {"DOWNSTREAM_LOCAL_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().localAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().remoteAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().remoteAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().remoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().directRemoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().directRemoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().directRemoteAddress(); - }); - }}}, - {"CONNECTION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider().connectionID().value_or(0); - }); - }}}, - {"REQUESTED_SERVER_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamAddressProvider().requestedServerName().empty()) { - result = std::string( - stream_info.downstreamAddressProvider().requestedServerName()); - } - return result; - }); - }}}, - {"ROUTE_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - std::string route_name = stream_info.getRouteName(); - if (!route_name.empty()) { - result = route_name; - } - return result; - }); - }}}, - {"DOWNSTREAM_PEER_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.uriSanPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.dnsSansPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.ipSansPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.uriSanLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.dnsSansLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.ipSansLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_LOCAL_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectLocalCertificate(); - }); - }}}, - {"DOWNSTREAM_TLS_SESSION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sessionId(); - }); - }}}, - {"DOWNSTREAM_TLS_CIPHER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.ciphersuiteString(); - }); - }}}, - {"DOWNSTREAM_TLS_VERSION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.tlsVersion(); - }); - }}}, - {"DOWNSTREAM_PEER_FINGERPRINT_256", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sha256PeerCertificateDigest(); - }); - }}}, - {"DOWNSTREAM_PEER_FINGERPRINT_1", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sha1PeerCertificateDigest(); - }); - }}}, - {"DOWNSTREAM_PEER_SERIAL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.serialNumberPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_PEER_ISSUER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.issuerPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_PEER_CERT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.urlEncodedPemEncodedPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_TRANSPORT_FAILURE_REASON", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamTransportFailureReason().empty()) { - result = absl::StrReplaceAll(stream_info.downstreamTransportFailureReason(), - {{" ", "_"}}); - } - return result; - }); - }}}, - {"UPSTREAM_TRANSPORT_FAILURE_REASON", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (stream_info.upstreamInfo().has_value() && - !stream_info.upstreamInfo() - .value() - .get() - .upstreamTransportFailureReason() - .empty()) { - result = - stream_info.upstreamInfo().value().get().upstreamTransportFailureReason(); - } - if (result) { - std::replace(result->begin(), result->end(), ' ', '_'); - } - return result; - }); - }}}, - {"HOSTNAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - absl::optional hostname = SubstitutionFormatUtils::getHostname(); - return std::make_unique( - [hostname](const StreamInfo::StreamInfo&) { return hostname; }); - }}}, - {"FILTER_CHAIN_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - if (const auto info = stream_info.downstreamAddressProvider().filterChainInfo(); - info.has_value()) { - if (!info->name().empty()) { - return std::string(info->name()); - } - } - return absl::nullopt; - }); - }}}, - {"VIRTUAL_CLUSTER_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - return stream_info.virtualClusterName(); - }); - }}}, - {"TLS_JA3_FINGERPRINT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamAddressProvider().ja3Hash().empty()) { - result = std::string(stream_info.downstreamAddressProvider().ja3Hash()); - } - return result; - }); - }}}, - {"STREAM_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - auto provider = stream_info.getStreamIdProvider(); - if (!provider.has_value()) { - return {}; - } - auto id = provider->toStringView(); - if (!id.has_value()) { - return {}; - } - return absl::make_optional(id.value()); - }); - }}}, - {"START_TIME", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique( - format, - std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - return stream_info.startTime(); - })); - }}}, - {"EMIT_TIME", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique( - format, - std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { - return stream_info.timeSource().systemTime(); - })); - }}}, - {"DYNAMIC_METADATA", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& format, absl::optional max_length) { - std::string filter_namespace; - std::vector path; + return result; + }); + }}}, + {"DOWNSTREAM_HANDSHAKE_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.downstreamHandshakeComplete(); + }); + }}}, + {"ROUNDTRIP_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.lastDownstreamAckReceived(); + }); + }}}, + {"BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesReceived(); + }); + }}}, + {"BYTES_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesRetransmitted(); + }); + }}}, + {"PACKETS_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.packetsRetransmitted(); + }); + }}}, + {"UPSTREAM_WIRE_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesReceived() : 0; + }); + }}}, + {"UPSTREAM_HEADER_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesReceived() : 0; + }); + }}}, + {"DOWNSTREAM_WIRE_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesReceived() : 0; + }); + }}}, + {"DOWNSTREAM_HEADER_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesReceived() : 0; + }); + }}}, + {"PROTOCOL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return SubstitutionFormatUtils::protocolToString( + stream_info.protocol()); + }); + }}}, + {"UPSTREAM_PROTOCOL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.upstreamInfo() + ? SubstitutionFormatUtils::protocolToString( + stream_info.upstreamInfo() + ->upstreamProtocol()) + : absl::nullopt; + }); + }}}, + {"RESPONSE_CODE", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.responseCode().value_or(0); + }); + }}}, + {"RESPONSE_CODE_DETAILS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.responseCodeDetails(); + }); + }}}, + {"CONNECTION_TERMINATION_DETAILS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.connectionTerminationDetails(); + }); + }}}, + {"BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesSent(); + }); + }}}, + {"UPSTREAM_WIRE_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesSent() : 0; + }); + }}}, + {"UPSTREAM_HEADER_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesSent() : 0; + }); + }}}, + {"DOWNSTREAM_WIRE_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesSent() : 0; + }); + }}}, + {"DOWNSTREAM_HEADER_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = + stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesSent() : 0; + }); + }}}, + {"DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.currentDuration(); + }); + }}}, + {"COMMON_DURATION", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& sub_command, absl::optional) { + return CommonDurationFormatter::create(sub_command); + }}}, + {"RESPONSE_FLAGS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return StreamInfo::ResponseFlagUtils::toShortString( + stream_info); + }); + }}}, + {"RESPONSE_FLAGS_LONG", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return StreamInfo::ResponseFlagUtils::toString(stream_info); + }); + }}}, + {"UPSTREAM_HOST_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + const auto opt_ref = stream_info.upstreamInfo(); + if (!opt_ref.has_value()) { + return absl::nullopt; + } + const auto host = opt_ref->upstreamHost(); + if (host == nullptr) { + return absl::nullopt; + } + std::string host_name = host->hostname(); + if (host_name.empty()) { + // If no hostname is available, the main address is used. + return host->address()->asString(); + } + return absl::make_optional( + std::move(host_name)); + }); + }}}, + {"UPSTREAM_HOST", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + const auto opt_ref = stream_info.upstreamInfo(); + if (!opt_ref.has_value()) { + return nullptr; + } + const auto host = opt_ref->upstreamHost(); + if (host == nullptr) { + return nullptr; + } + return host->address(); + }); + }}}, + {"UPSTREAM_CONNECTION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + uint64_t upstream_connection_id = 0; + if (stream_info.upstreamInfo().has_value()) { + upstream_connection_id = stream_info.upstreamInfo() + ->upstreamConnectionId() + .value_or(0); + } + return upstream_connection_id; + }); + }}}, + {"UPSTREAM_CLUSTER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + std::string upstream_cluster_name; + if (stream_info.upstreamClusterInfo().has_value() && + stream_info.upstreamClusterInfo().value() != nullptr) { + upstream_cluster_name = stream_info.upstreamClusterInfo() + .value() + ->observabilityName(); + } + + return upstream_cluster_name.empty() + ? absl::nullopt + : absl::make_optional( + upstream_cluster_name); + }); + }}}, + {"UPSTREAM_LOCAL_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo() + .value() + .get() + .upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo() + .value() + .get() + .upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_LOCAL_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo() + .value() + .get() + .upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + return getUpstreamRemoteAddress(stream_info); + }); + }}}, + {"UPSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + return getUpstreamRemoteAddress(stream_info); + }); + }}}, + {"UPSTREAM_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + return getUpstreamRemoteAddress(stream_info); + }); + }}}, + {"UPSTREAM_REQUEST_ATTEMPT_COUNT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.attemptCount().value_or(0); + }); + }}}, + {"UPSTREAM_TLS_CIPHER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.ciphersuiteString(); + }); + }}}, + {"UPSTREAM_TLS_VERSION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.tlsVersion(); + }); + }}}, + {"UPSTREAM_TLS_SESSION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sessionId(); + }); + }}}, + {"UPSTREAM_PEER_ISSUER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.issuerPeerCertificate(); + }); + }}}, + {"UPSTREAM_PEER_CERT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.urlEncodedPemEncodedPeerCertificate(); + }); + }}}, + {"UPSTREAM_PEER_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoUpstreamSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_LOCAL_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .localAddress(); + }); + }}}, + {"DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .localAddress(); + }); + }}}, + {"DOWNSTREAM_LOCAL_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .localAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .remoteAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .remoteAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .remoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .directRemoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .directRemoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .directRemoteAddress(); + }); + }}}, + {"CONNECTION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider() + .connectionID() + .value_or(0); + }); + }}}, + {"REQUESTED_SERVER_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamAddressProvider() + .requestedServerName() + .empty()) { + result = + std::string(stream_info.downstreamAddressProvider() + .requestedServerName()); + } + return result; + }); + }}}, + {"ROUTE_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + std::string route_name = stream_info.getRouteName(); + if (!route_name.empty()) { + result = route_name; + } + return result; + }); + }}}, + {"DOWNSTREAM_PEER_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanPeerCertificate(), + ","); + }); + }}}, + {"DOWNSTREAM_PEER_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.dnsSansPeerCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.ipSansPeerCertificate(), + ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.uriSanLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.dnsSansLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin( + connection_info.ipSansLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_LOCAL_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectLocalCertificate(); + }); + }}}, + {"DOWNSTREAM_TLS_SESSION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sessionId(); + }); + }}}, + {"DOWNSTREAM_TLS_CIPHER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.ciphersuiteString(); + }); + }}}, + {"DOWNSTREAM_TLS_VERSION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.tlsVersion(); + }); + }}}, + {"DOWNSTREAM_PEER_FINGERPRINT_256", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sha256PeerCertificateDigest(); + }); + }}}, + {"DOWNSTREAM_PEER_FINGERPRINT_1", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sha1PeerCertificateDigest(); + }); + }}}, + {"DOWNSTREAM_PEER_SERIAL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.serialNumberPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_PEER_ISSUER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.issuerPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_PEER_CERT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique< + StreamInfoSslConnectionInfoFormatterProvider>( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.urlEncodedPemEncodedPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_TRANSPORT_FAILURE_REASON", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamTransportFailureReason() + .empty()) { + result = absl::StrReplaceAll( + stream_info.downstreamTransportFailureReason(), + {{" ", "_"}}); + } + return result; + }); + }}}, + {"UPSTREAM_TRANSPORT_FAILURE_REASON", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (stream_info.upstreamInfo().has_value() && + !stream_info.upstreamInfo() + .value() + .get() + .upstreamTransportFailureReason() + .empty()) { + result = stream_info.upstreamInfo() + .value() + .get() + .upstreamTransportFailureReason(); + } + if (result) { + std::replace(result->begin(), result->end(), ' ', '_'); + } + return result; + }); + }}}, + {"HOSTNAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + absl::optional hostname = + SubstitutionFormatUtils::getHostname(); + return std::make_unique( + [hostname](const StreamInfo::StreamInfo&) { + return hostname; + }); + }}}, + {"FILTER_CHAIN_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + if (const auto info = stream_info.downstreamAddressProvider() + .filterChainInfo(); + info.has_value()) { + if (!info->name().empty()) { + return std::string(info->name()); + } + } + return absl::nullopt; + }); + }}}, + {"VIRTUAL_CLUSTER_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + return stream_info.virtualClusterName(); + }); + }}}, + {"TLS_JA3_FINGERPRINT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamAddressProvider() + .ja3Hash() + .empty()) { + result = std::string( + stream_info.downstreamAddressProvider().ja3Hash()); + } + return result; + }); + }}}, + {"STREAM_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + auto provider = stream_info.getStreamIdProvider(); + if (!provider.has_value()) { + return {}; + } + auto id = provider->toStringView(); + if (!id.has_value()) { + return {}; + } + return absl::make_optional(id.value()); + }); + }}}, + {"START_TIME", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique( + format, + std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + return stream_info.startTime(); + })); + }}}, + {"EMIT_TIME", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique( + format, + std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + return stream_info.timeSource().systemTime(); + })); + }}}, + {"DYNAMIC_METADATA", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& format, absl::optional max_length) { + std::string filter_namespace; + std::vector path; SubstitutionFormatUtils::parseSubcommand(format, ':', filter_namespace, path); From a65e529cf92a0a38cae2ca9c042e0fbc8192a1c0 Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Wed, 15 May 2024 22:28:40 +0000 Subject: [PATCH 5/6] Fix formatting once and for all Signed-off-by: Keith Mattix II --- .../common/formatter/stream_info_formatter.cc | 1914 ++++++++--------- 1 file changed, 906 insertions(+), 1008 deletions(-) diff --git a/source/common/formatter/stream_info_formatter.cc b/source/common/formatter/stream_info_formatter.cc index 162e35bd470b3..e0caa52575dbe 100644 --- a/source/common/formatter/stream_info_formatter.cc +++ b/source/common/formatter/stream_info_formatter.cc @@ -819,1014 +819,912 @@ class StreamInfoUpstreamSslConnectionInfoFormatterProvider : public StreamInfoFo }; const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProviders() { - CONSTRUCT_ON_FIRST_USE(StreamInfoFormatterProviderLookupTable, - { - {"REQUEST_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.lastDownstreamRxByteReceived(); - }); - }}}, - {"REQUEST_TX_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.lastUpstreamTxByteSent(); - }); - }}}, - {"RESPONSE_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.firstUpstreamRxByteReceived(); - }); - }}}, - {"RESPONSE_TX_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - auto downstream = timing.lastDownstreamTxByteSent(); - auto upstream = timing.firstUpstreamRxByteReceived(); - - absl::optional result; - if (downstream && upstream) { - result = downstream.value() - upstream.value(); - } - - return result; - }); - }}}, - {"DOWNSTREAM_HANDSHAKE_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.downstreamHandshakeComplete(); - }); - }}}, - {"ROUNDTRIP_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - StreamInfo::TimingUtility timing(stream_info); - return timing.lastDownstreamAckReceived(); - }); - }}}, - {"BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesReceived(); - }); - }}}, - {"BYTES_RETRANSMITTED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesRetransmitted(); - }); - }}}, - {"PACKETS_RETRANSMITTED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.packetsRetransmitted(); - }); - }}}, - {"UPSTREAM_WIRE_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesReceived() : 0; - }); - }}}, - {"UPSTREAM_HEADER_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesReceived() : 0; - }); - }}}, - {"DOWNSTREAM_WIRE_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesReceived() : 0; - }); - }}}, - {"DOWNSTREAM_HEADER_BYTES_RECEIVED", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesReceived() : 0; - }); - }}}, - {"PROTOCOL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return SubstitutionFormatUtils::protocolToString( - stream_info.protocol()); - }); - }}}, - {"UPSTREAM_PROTOCOL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.upstreamInfo() - ? SubstitutionFormatUtils::protocolToString( - stream_info.upstreamInfo() - ->upstreamProtocol()) - : absl::nullopt; - }); - }}}, - {"RESPONSE_CODE", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.responseCode().value_or(0); - }); - }}}, - {"RESPONSE_CODE_DETAILS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.responseCodeDetails(); - }); - }}}, - {"CONNECTION_TERMINATION_DETAILS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.connectionTerminationDetails(); - }); - }}}, - {"BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.bytesSent(); - }); - }}}, - {"UPSTREAM_WIRE_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesSent() : 0; - }); - }}}, - {"UPSTREAM_HEADER_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getUpstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesSent() : 0; - }); - }}}, - {"DOWNSTREAM_WIRE_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->wireBytesSent() : 0; - }); - }}}, - {"DOWNSTREAM_HEADER_BYTES_SENT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - const auto& bytes_meter = - stream_info.getDownstreamBytesMeter(); - return bytes_meter ? bytes_meter->headerBytesSent() : 0; - }); - }}}, - {"DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.currentDuration(); - }); - }}}, - {"COMMON_DURATION", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& sub_command, absl::optional) { - return CommonDurationFormatter::create(sub_command); - }}}, - {"RESPONSE_FLAGS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return StreamInfo::ResponseFlagUtils::toShortString( - stream_info); - }); - }}}, - {"RESPONSE_FLAGS_LONG", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return StreamInfo::ResponseFlagUtils::toString(stream_info); - }); - }}}, - {"UPSTREAM_HOST_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - const auto opt_ref = stream_info.upstreamInfo(); - if (!opt_ref.has_value()) { - return absl::nullopt; - } - const auto host = opt_ref->upstreamHost(); - if (host == nullptr) { - return absl::nullopt; - } - std::string host_name = host->hostname(); - if (host_name.empty()) { - // If no hostname is available, the main address is used. - return host->address()->asString(); - } - return absl::make_optional( - std::move(host_name)); - }); - }}}, - {"UPSTREAM_HOST", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - const auto opt_ref = stream_info.upstreamInfo(); - if (!opt_ref.has_value()) { - return nullptr; - } - const auto host = opt_ref->upstreamHost(); - if (host == nullptr) { - return nullptr; - } - return host->address(); - }); - }}}, - {"UPSTREAM_CONNECTION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - uint64_t upstream_connection_id = 0; - if (stream_info.upstreamInfo().has_value()) { - upstream_connection_id = stream_info.upstreamInfo() - ->upstreamConnectionId() - .value_or(0); - } - return upstream_connection_id; - }); - }}}, - {"UPSTREAM_CLUSTER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - std::string upstream_cluster_name; - if (stream_info.upstreamClusterInfo().has_value() && - stream_info.upstreamClusterInfo().value() != nullptr) { - upstream_cluster_name = stream_info.upstreamClusterInfo() - .value() - ->observabilityName(); - } - - return upstream_cluster_name.empty() - ? absl::nullopt - : absl::make_optional( - upstream_cluster_name); - }); - }}}, - {"UPSTREAM_LOCAL_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo() - .value() - .get() - .upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo() - .value() - .get() - .upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_LOCAL_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - if (stream_info.upstreamInfo().has_value()) { - return stream_info.upstreamInfo() - .value() - .get() - .upstreamLocalAddress(); - } - return nullptr; - }); - }}}, - {"UPSTREAM_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - return getUpstreamRemoteAddress(stream_info); - }); - }}}, - {"UPSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - return getUpstreamRemoteAddress(stream_info); - }); - }}}, - {"UPSTREAM_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const StreamInfo::StreamInfo& stream_info) - -> Network::Address::InstanceConstSharedPtr { - return getUpstreamRemoteAddress(stream_info); - }); - }}}, - {"UPSTREAM_REQUEST_ATTEMPT_COUNT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.attemptCount().value_or(0); - }); - }}}, - {"UPSTREAM_TLS_CIPHER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.ciphersuiteString(); - }); - }}}, - {"UPSTREAM_TLS_VERSION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.tlsVersion(); - }); - }}}, - {"UPSTREAM_TLS_SESSION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sessionId(); - }); - }}}, - {"UPSTREAM_PEER_ISSUER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.issuerPeerCertificate(); - }); - }}}, - {"UPSTREAM_PEER_CERT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.urlEncodedPemEncodedPeerCertificate(); - }); - }}}, - {"UPSTREAM_PEER_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_LOCAL_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .localAddress(); - }); - }}}, - {"DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .localAddress(); - }); - }}}, - {"DOWNSTREAM_LOCAL_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .localAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .remoteAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .remoteAddress(); - }); - }}}, - {"DOWNSTREAM_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .remoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .directRemoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS_WITHOUT_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::withoutPort( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .directRemoteAddress(); - }); - }}}, - {"DOWNSTREAM_DIRECT_REMOTE_PORT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return StreamInfoAddressFormatterProvider::justPort( - [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .directRemoteAddress(); - }); - }}}, - {"CONNECTION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - return stream_info.downstreamAddressProvider() - .connectionID() - .value_or(0); - }); - }}}, - {"REQUESTED_SERVER_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamAddressProvider() - .requestedServerName() - .empty()) { - result = - std::string(stream_info.downstreamAddressProvider() - .requestedServerName()); - } - return result; - }); - }}}, - {"ROUTE_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - std::string route_name = stream_info.getRouteName(); - if (!route_name.empty()) { - result = route_name; - } - return result; - }); - }}}, - {"DOWNSTREAM_PEER_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.uriSanPeerCertificate(), - ","); - }); - }}}, - {"DOWNSTREAM_PEER_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.dnsSansPeerCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.ipSansPeerCertificate(), - ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.uriSanLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.dnsSansLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_LOCAL_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.ipSansLocalCertificate(), ","); - }); - }}}, - {"DOWNSTREAM_PEER_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_LOCAL_SUBJECT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.subjectLocalCertificate(); - }); - }}}, - {"DOWNSTREAM_TLS_SESSION_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sessionId(); - }); - }}}, - {"DOWNSTREAM_TLS_CIPHER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.ciphersuiteString(); - }); - }}}, - {"DOWNSTREAM_TLS_VERSION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.tlsVersion(); - }); - }}}, - {"DOWNSTREAM_PEER_FINGERPRINT_256", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sha256PeerCertificateDigest(); - }); - }}}, - {"DOWNSTREAM_PEER_FINGERPRINT_1", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.sha1PeerCertificateDigest(); - }); - }}}, - {"DOWNSTREAM_PEER_SERIAL", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.serialNumberPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_PEER_ISSUER", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.issuerPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_PEER_CERT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return connection_info.urlEncodedPemEncodedPeerCertificate(); - }); - }}}, - {"DOWNSTREAM_TRANSPORT_FAILURE_REASON", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamTransportFailureReason() - .empty()) { - result = absl::StrReplaceAll( - stream_info.downstreamTransportFailureReason(), - {{" ", "_"}}); - } - return result; - }); - }}}, - {"UPSTREAM_TRANSPORT_FAILURE_REASON", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (stream_info.upstreamInfo().has_value() && - !stream_info.upstreamInfo() - .value() - .get() - .upstreamTransportFailureReason() - .empty()) { - result = stream_info.upstreamInfo() - .value() - .get() - .upstreamTransportFailureReason(); - } - if (result) { - std::replace(result->begin(), result->end(), ' ', '_'); - } - return result; - }); - }}}, - {"HOSTNAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - absl::optional hostname = - SubstitutionFormatUtils::getHostname(); - return std::make_unique( - [hostname](const StreamInfo::StreamInfo&) { - return hostname; - }); - }}}, - {"FILTER_CHAIN_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - if (const auto info = stream_info.downstreamAddressProvider() - .filterChainInfo(); - info.has_value()) { - if (!info->name().empty()) { - return std::string(info->name()); - } - } - return absl::nullopt; - }); - }}}, - {"VIRTUAL_CLUSTER_NAME", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - return stream_info.virtualClusterName(); - }); - }}}, - {"TLS_JA3_FINGERPRINT", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) { - absl::optional result; - if (!stream_info.downstreamAddressProvider() - .ja3Hash() - .empty()) { - result = std::string( - stream_info.downstreamAddressProvider().ja3Hash()); - } - return result; - }); - }}}, - {"STREAM_ID", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - auto provider = stream_info.getStreamIdProvider(); - if (!provider.has_value()) { - return {}; - } - auto id = provider->toStringView(); - if (!id.has_value()) { - return {}; - } - return absl::make_optional(id.value()); - }); - }}}, - {"START_TIME", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique( - format, - std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - return stream_info.startTime(); - })); - }}}, - {"EMIT_TIME", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique( - format, - std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - return stream_info.timeSource().systemTime(); - })); - }}}, - {"DYNAMIC_METADATA", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& format, absl::optional max_length) { - std::string filter_namespace; - std::vector path; - - SubstitutionFormatUtils::parseSubcommand(format, ':', - filter_namespace, path); - return std::make_unique( - filter_namespace, path, max_length); - }}}, - - {"CLUSTER_METADATA", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& format, absl::optional max_length) { - std::string filter_namespace; - std::vector path; - - SubstitutionFormatUtils::parseSubcommand(format, ':', - filter_namespace, path); - return std::make_unique( - filter_namespace, path, max_length); - }}}, - {"UPSTREAM_METADATA", - {CommandSyntaxChecker::PARAMS_REQUIRED, - [](const std::string& format, absl::optional max_length) { - std::string filter_namespace; - std::vector path; - - SubstitutionFormatUtils::parseSubcommand(format, ':', - filter_namespace, path); - return std::make_unique( - filter_namespace, path, max_length); - }}}, - {"FILTER_STATE", - {CommandSyntaxChecker::PARAMS_OPTIONAL | - CommandSyntaxChecker::LENGTH_ALLOWED, - [](const std::string& format, absl::optional max_length) { - return FilterStateFormatter::create(format, max_length, false); - }}}, - {"UPSTREAM_FILTER_STATE", - {CommandSyntaxChecker::PARAMS_OPTIONAL | - CommandSyntaxChecker::LENGTH_ALLOWED, - [](const std::string& format, absl::optional max_length) { - return FilterStateFormatter::create(format, max_length, true); - }}}, - {"DOWNSTREAM_PEER_CERT_V_START", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"DOWNSTREAM_PEER_CERT_V_END", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"UPSTREAM_PEER_CERT_V_START", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"UPSTREAM_PEER_CERT_V_END", - {CommandSyntaxChecker::PARAMS_OPTIONAL, - [](const std::string& format, absl::optional) { - return std::make_unique(format); - }}}, - {"UPSTREAM_PEER_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.uriSanPeerCertificate(), - ","); - }); - }}}, - {"UPSTREAM_PEER_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.dnsSansPeerCertificate(), ","); - }); - }}}, - {"UPSTREAM_PEER_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin(connection_info.ipSansPeerCertificate(), - ","); - }); - }}}, - {"UPSTREAM_LOCAL_URI_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.uriSanLocalCertificate(), ","); - }); - }}}, - {"UPSTREAM_LOCAL_DNS_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.dnsSansLocalCertificate(), ","); - }); - }}}, - {"UPSTREAM_LOCAL_IP_SAN", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, absl::optional) { - return std::make_unique< - StreamInfoUpstreamSslConnectionInfoFormatterProvider>( - [](const Ssl::ConnectionInfo& connection_info) { - return absl::StrJoin( - connection_info.ipSansLocalCertificate(), ","); - }); - }}}, - {"ENVIRONMENT", - {CommandSyntaxChecker::PARAMS_REQUIRED | - CommandSyntaxChecker::LENGTH_ALLOWED, - [](const std::string& key, absl::optional max_length) { - return std::make_unique(key, max_length); - }}}, - {"UPSTREAM_CONNECTION_POOL_READY_DURATION", - {CommandSyntaxChecker::COMMAND_ONLY, - [](const std::string&, const absl::optional&) { - return std::make_unique( - [](const StreamInfo::StreamInfo& stream_info) - -> absl::optional { - if (auto upstream_info = stream_info.upstreamInfo(); - upstream_info.has_value()) { - if (auto connection_pool_callback_latency = - upstream_info.value() - .get() - .upstreamTiming() - .connectionPoolCallbackLatency(); - connection_pool_callback_latency.has_value()) { - return connection_pool_callback_latency; - } - } - return absl::nullopt; - }); - }}}, - }); + CONSTRUCT_ON_FIRST_USE( + StreamInfoFormatterProviderLookupTable, + { + {"REQUEST_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.lastDownstreamRxByteReceived(); + }); + }}}, + {"REQUEST_TX_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.lastUpstreamTxByteSent(); + }); + }}}, + {"RESPONSE_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.firstUpstreamRxByteReceived(); + }); + }}}, + {"RESPONSE_TX_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + auto downstream = timing.lastDownstreamTxByteSent(); + auto upstream = timing.firstUpstreamRxByteReceived(); + + absl::optional result; + if (downstream && upstream) { + result = downstream.value() - upstream.value(); + } + + return result; + }); + }}}, + {"DOWNSTREAM_HANDSHAKE_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.downstreamHandshakeComplete(); + }); + }}}, + {"ROUNDTRIP_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + StreamInfo::TimingUtility timing(stream_info); + return timing.lastDownstreamAckReceived(); + }); + }}}, + {"BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesReceived(); + }); + }}}, + {"BYTES_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesRetransmitted(); + }); + }}}, + {"PACKETS_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.packetsRetransmitted(); + }); + }}}, + {"UPSTREAM_WIRE_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesReceived() : 0; + }); + }}}, + {"UPSTREAM_HEADER_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesReceived() : 0; + }); + }}}, + {"DOWNSTREAM_WIRE_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesReceived() : 0; + }); + }}}, + {"DOWNSTREAM_HEADER_BYTES_RECEIVED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesReceived() : 0; + }); + }}}, + {"PROTOCOL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return SubstitutionFormatUtils::protocolToString(stream_info.protocol()); + }); + }}}, + {"UPSTREAM_PROTOCOL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.upstreamInfo() + ? SubstitutionFormatUtils::protocolToString( + stream_info.upstreamInfo()->upstreamProtocol()) + : absl::nullopt; + }); + }}}, + {"RESPONSE_CODE", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.responseCode().value_or(0); + }); + }}}, + {"RESPONSE_CODE_DETAILS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.responseCodeDetails(); + }); + }}}, + {"CONNECTION_TERMINATION_DETAILS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.connectionTerminationDetails(); + }); + }}}, + {"BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesSent(); + }); + }}}, + {"UPSTREAM_WIRE_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesSent() : 0; + }); + }}}, + {"UPSTREAM_HEADER_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesSent() : 0; + }); + }}}, + {"DOWNSTREAM_WIRE_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->wireBytesSent() : 0; + }); + }}}, + {"DOWNSTREAM_HEADER_BYTES_SENT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); + return bytes_meter ? bytes_meter->headerBytesSent() : 0; + }); + }}}, + {"DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.currentDuration(); + }); + }}}, + {"COMMON_DURATION", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& sub_command, absl::optional) { + return CommonDurationFormatter::create(sub_command); + }}}, + {"RESPONSE_FLAGS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return StreamInfo::ResponseFlagUtils::toShortString(stream_info); + }); + }}}, + {"RESPONSE_FLAGS_LONG", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return StreamInfo::ResponseFlagUtils::toString(stream_info); + }); + }}}, + {"UPSTREAM_HOST_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { + const auto opt_ref = stream_info.upstreamInfo(); + if (!opt_ref.has_value()) { + return absl::nullopt; + } + const auto host = opt_ref->upstreamHost(); + if (host == nullptr) { + return absl::nullopt; + } + std::string host_name = host->hostname(); + if (host_name.empty()) { + // If no hostname is available, the main address is used. + return host->address()->asString(); + } + return absl::make_optional(std::move(host_name)); + }); + }}}, + {"UPSTREAM_HOST", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + const auto opt_ref = stream_info.upstreamInfo(); + if (!opt_ref.has_value()) { + return nullptr; + } + const auto host = opt_ref->upstreamHost(); + if (host == nullptr) { + return nullptr; + } + return host->address(); + }); + }}}, + {"UPSTREAM_CONNECTION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + uint64_t upstream_connection_id = 0; + if (stream_info.upstreamInfo().has_value()) { + upstream_connection_id = + stream_info.upstreamInfo()->upstreamConnectionId().value_or(0); + } + return upstream_connection_id; + }); + }}}, + {"UPSTREAM_CLUSTER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + std::string upstream_cluster_name; + if (stream_info.upstreamClusterInfo().has_value() && + stream_info.upstreamClusterInfo().value() != nullptr) { + upstream_cluster_name = + stream_info.upstreamClusterInfo().value()->observabilityName(); + } + + return upstream_cluster_name.empty() + ? absl::nullopt + : absl::make_optional(upstream_cluster_name); + }); + }}}, + {"UPSTREAM_LOCAL_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_LOCAL_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + if (stream_info.upstreamInfo().has_value()) { + return stream_info.upstreamInfo().value().get().upstreamLocalAddress(); + } + return nullptr; + }); + }}}, + {"UPSTREAM_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + return getUpstreamRemoteAddress(stream_info); + }); + }}}, + {"UPSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + return getUpstreamRemoteAddress(stream_info); + }); + }}}, + {"UPSTREAM_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const StreamInfo::StreamInfo& stream_info) + -> Network::Address::InstanceConstSharedPtr { + return getUpstreamRemoteAddress(stream_info); + }); + }}}, + {"UPSTREAM_REQUEST_ATTEMPT_COUNT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.attemptCount().value_or(0); + }); + }}}, + {"UPSTREAM_TLS_CIPHER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.ciphersuiteString(); + }); + }}}, + {"UPSTREAM_TLS_VERSION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.tlsVersion(); + }); + }}}, + {"UPSTREAM_TLS_SESSION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sessionId(); + }); + }}}, + {"UPSTREAM_PEER_ISSUER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.issuerPeerCertificate(); + }); + }}}, + {"UPSTREAM_PEER_CERT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.urlEncodedPemEncodedPeerCertificate(); + }); + }}}, + {"UPSTREAM_PEER_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_LOCAL_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().localAddress(); + }); + }}}, + {"DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().localAddress(); + }); + }}}, + {"DOWNSTREAM_LOCAL_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().localAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().remoteAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().remoteAddress(); + }); + }}}, + {"DOWNSTREAM_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().remoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().directRemoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_ADDRESS_WITHOUT_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::withoutPort( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().directRemoteAddress(); + }); + }}}, + {"DOWNSTREAM_DIRECT_REMOTE_PORT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return StreamInfoAddressFormatterProvider::justPort( + [](const Envoy::StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().directRemoteAddress(); + }); + }}}, + {"CONNECTION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.downstreamAddressProvider().connectionID().value_or(0); + }); + }}}, + {"REQUESTED_SERVER_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamAddressProvider().requestedServerName().empty()) { + result = std::string( + stream_info.downstreamAddressProvider().requestedServerName()); + } + return result; + }); + }}}, + {"ROUTE_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + std::string route_name = stream_info.getRouteName(); + if (!route_name.empty()) { + result = route_name; + } + return result; + }); + }}}, + {"UPSTREAM_PEER_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanPeerCertificate(), ","); + }); + }}}, + {"UPSTREAM_PEER_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.dnsSansPeerCertificate(), ","); + }); + }}}, + {"UPSTREAM_PEER_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.ipSansPeerCertificate(), ","); + }); + }}}, + {"UPSTREAM_LOCAL_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanLocalCertificate(), ","); + }); + }}}, + {"UPSTREAM_LOCAL_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.dnsSansLocalCertificate(), ","); + }); + }}}, + {"UPSTREAM_LOCAL_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.ipSansLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanPeerCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.dnsSansPeerCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.ipSansPeerCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_URI_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.uriSanLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_DNS_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.dnsSansLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_LOCAL_IP_SAN", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return absl::StrJoin(connection_info.ipSansLocalCertificate(), ","); + }); + }}}, + {"DOWNSTREAM_PEER_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_LOCAL_SUBJECT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.subjectLocalCertificate(); + }); + }}}, + {"DOWNSTREAM_TLS_SESSION_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sessionId(); + }); + }}}, + {"DOWNSTREAM_TLS_CIPHER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.ciphersuiteString(); + }); + }}}, + {"DOWNSTREAM_TLS_VERSION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.tlsVersion(); + }); + }}}, + {"DOWNSTREAM_PEER_FINGERPRINT_256", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sha256PeerCertificateDigest(); + }); + }}}, + {"DOWNSTREAM_PEER_FINGERPRINT_1", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.sha1PeerCertificateDigest(); + }); + }}}, + {"DOWNSTREAM_PEER_SERIAL", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.serialNumberPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_PEER_ISSUER", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.issuerPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_PEER_CERT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const Ssl::ConnectionInfo& connection_info) { + return connection_info.urlEncodedPemEncodedPeerCertificate(); + }); + }}}, + {"DOWNSTREAM_TRANSPORT_FAILURE_REASON", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamTransportFailureReason().empty()) { + result = absl::StrReplaceAll(stream_info.downstreamTransportFailureReason(), + {{" ", "_"}}); + } + return result; + }); + }}}, + {"UPSTREAM_TRANSPORT_FAILURE_REASON", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (stream_info.upstreamInfo().has_value() && + !stream_info.upstreamInfo() + .value() + .get() + .upstreamTransportFailureReason() + .empty()) { + result = + stream_info.upstreamInfo().value().get().upstreamTransportFailureReason(); + } + if (result) { + std::replace(result->begin(), result->end(), ' ', '_'); + } + return result; + }); + }}}, + {"HOSTNAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + absl::optional hostname = SubstitutionFormatUtils::getHostname(); + return std::make_unique( + [hostname](const StreamInfo::StreamInfo&) { return hostname; }); + }}}, + {"FILTER_CHAIN_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { + if (const auto info = stream_info.downstreamAddressProvider().filterChainInfo(); + info.has_value()) { + if (!info->name().empty()) { + return std::string(info->name()); + } + } + return absl::nullopt; + }); + }}}, + {"VIRTUAL_CLUSTER_NAME", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { + return stream_info.virtualClusterName(); + }); + }}}, + {"TLS_JA3_FINGERPRINT", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + absl::optional result; + if (!stream_info.downstreamAddressProvider().ja3Hash().empty()) { + result = std::string(stream_info.downstreamAddressProvider().ja3Hash()); + } + return result; + }); + }}}, + {"STREAM_ID", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, absl::optional) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { + auto provider = stream_info.getStreamIdProvider(); + if (!provider.has_value()) { + return {}; + } + auto id = provider->toStringView(); + if (!id.has_value()) { + return {}; + } + return absl::make_optional(id.value()); + }); + }}}, + {"START_TIME", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique( + format, + std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { + return stream_info.startTime(); + })); + }}}, + {"EMIT_TIME", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique( + format, + std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) -> absl::optional { + return stream_info.timeSource().systemTime(); + })); + }}}, + {"DYNAMIC_METADATA", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& format, absl::optional max_length) { + std::string filter_namespace; + std::vector path; + + SubstitutionFormatUtils::parseSubcommand(format, ':', filter_namespace, path); + return std::make_unique(filter_namespace, path, max_length); + }}}, + + {"CLUSTER_METADATA", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& format, absl::optional max_length) { + std::string filter_namespace; + std::vector path; + + SubstitutionFormatUtils::parseSubcommand(format, ':', filter_namespace, path); + return std::make_unique(filter_namespace, path, max_length); + }}}, + {"UPSTREAM_METADATA", + {CommandSyntaxChecker::PARAMS_REQUIRED, + [](const std::string& format, absl::optional max_length) { + std::string filter_namespace; + std::vector path; + + SubstitutionFormatUtils::parseSubcommand(format, ':', filter_namespace, path); + return std::make_unique(filter_namespace, path, + max_length); + }}}, + {"FILTER_STATE", + {CommandSyntaxChecker::PARAMS_OPTIONAL | CommandSyntaxChecker::LENGTH_ALLOWED, + [](const std::string& format, absl::optional max_length) { + return FilterStateFormatter::create(format, max_length, false); + }}}, + {"UPSTREAM_FILTER_STATE", + {CommandSyntaxChecker::PARAMS_OPTIONAL | CommandSyntaxChecker::LENGTH_ALLOWED, + [](const std::string& format, absl::optional max_length) { + return FilterStateFormatter::create(format, max_length, true); + }}}, + {"DOWNSTREAM_PEER_CERT_V_START", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"DOWNSTREAM_PEER_CERT_V_END", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"UPSTREAM_PEER_CERT_V_START", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"UPSTREAM_PEER_CERT_V_END", + {CommandSyntaxChecker::PARAMS_OPTIONAL, + [](const std::string& format, absl::optional) { + return std::make_unique(format); + }}}, + {"ENVIRONMENT", + {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, + [](const std::string& key, absl::optional max_length) { + return std::make_unique(key, max_length); + }}}, + {"UPSTREAM_CONNECTION_POOL_READY_DURATION", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, const absl::optional&) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) + -> absl::optional { + if (auto upstream_info = stream_info.upstreamInfo(); + upstream_info.has_value()) { + if (auto connection_pool_callback_latency = + upstream_info.value() + .get() + .upstreamTiming() + .connectionPoolCallbackLatency(); + connection_pool_callback_latency.has_value()) { + return connection_pool_callback_latency; + } + } + return absl::nullopt; + }); + }}}, + }); } } // namespace Formatter From 3aa3e9c96d6ae29bf2173baffb53f5b9dec33698 Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Fri, 17 May 2024 14:59:48 +0000 Subject: [PATCH 6/6] Address PR comments Signed-off-by: Keith Mattix II --- .../observability/access_log/usage.rst | 15 ++++-- .../common/formatter/stream_info_formatter.cc | 1 - .../formatter/substitution_formatter_test.cc | 51 +++++++++++++++---- 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/docs/root/configuration/observability/access_log/usage.rst b/docs/root/configuration/observability/access_log/usage.rst index 1797463dd46f1..78b31fa5e3ff9 100644 --- a/docs/root/configuration/observability/access_log/usage.rst +++ b/docs/root/configuration/observability/access_log/usage.rst @@ -1175,36 +1175,43 @@ UDP UPSTREAM_PEER_CERT_V_END can be customized using a `format string `_. See :ref:`START_TIME ` for additional format specifiers and examples. + %UPSTREAM_PEER_URI_SAN% HTTP/TCP/THRIFT The URIs present in the SAN of the peer certificate used to establish the upstream TLS connection. UDP Not implemented ("-"). + %UPSTREAM_PEER_DNS_SAN% HTTP/TCP/THRIFT The DNS names present in the SAN of the peer certificate used to establish the upstream TLS connection. UDP Not implemented ("-"). + %UPSTREAM_PEER_IP_SAN% HTTP/TCP/THRIFT The ip addresses present in the SAN of the peer certificate used to establish the upstream TLS connection. UDP Not implemented ("-"). + %UPSTREAM_LOCAL_URI_SAN% HTTP/TCP/THRIFT The URIs present in the SAN of the local certificate used to establish the upstream TLS connection. UDP Not implemented ("-"). -%UPSTREAM_LOCAL_IP_SAN% + +%UPSTREAM_LOCAL_DNS_SAN% HTTP/TCP/THRIFT - The ip addresses present in the SAN of the local certificate used to establish the upstream TLS connection. + The DNS names present in the SAN of the local certificate used to establish the upstream TLS connection. UDP Not implemented ("-"). -%UPSTREAM_LOCAL_DNS_SAN% + +%UPSTREAM_LOCAL_IP_SAN% HTTP/TCP/THRIFT - The DNS names present in the SAN of the local certificate used to establish the upstream TLS connection. + The ip addresses present in the SAN of the local certificate used to establish the upstream TLS connection. UDP Not implemented ("-"). + %HOSTNAME% The system hostname. diff --git a/source/common/formatter/stream_info_formatter.cc b/source/common/formatter/stream_info_formatter.cc index e0caa52575dbe..0ce3137452701 100644 --- a/source/common/formatter/stream_info_formatter.cc +++ b/source/common/formatter/stream_info_formatter.cc @@ -9,7 +9,6 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_replace.h" -#include "substitution_format_utility.h" namespace Envoy { namespace Formatter { diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index 1efa6ba79ffcb..97044936efaac 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -1170,6 +1170,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { StreamInfoFormatter upstream_format("VIRTUAL_CLUSTER_NAME"); EXPECT_EQ(absl::nullopt, upstream_format.formatWithContext({}, stream_info)); } + { // Use a local stream info for these tests as as setSslConnection can only be called once. NiceMock stream_info; @@ -1182,6 +1183,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_PEER_URI_SAN"); @@ -1222,6 +1224,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_PEER_DNS_SAN"); @@ -1262,6 +1265,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_PEER_IP_SAN"); @@ -1290,6 +1294,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_LOCAL_URI_SAN"); @@ -1407,6 +1412,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + { NiceMock stream_info; StreamInfoFormatter upstream_format("DOWNSTREAM_LOCAL_SUBJECT"); @@ -1930,8 +1936,8 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue(expected_cert))); } + // Test that the upstream peer uri san is returned by the formatter. { - // Use a local stream info for these tests as as setSslConnection can only be called once. NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_URI_SAN"); auto connection_info = std::make_shared(); @@ -1942,6 +1948,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + // Test that peer URI SAN delimiter is applied correctly { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_URI_SAN"); @@ -1949,8 +1956,10 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, uriSanPeerCertificate()).WillRepeatedly(Return(sans)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san1,san2"))); } + // Test that an empty peer URI SAN list returns a null value { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_URI_SAN"); @@ -1962,6 +1971,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that a null connection returns a null peer URI SAN { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); @@ -1970,8 +1980,8 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that the upstream peer DNS san is returned by the formatter. { - // Use a local stream info for these tests as as setSslConnection can only be called once. NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_DNS_SAN"); auto connection_info = std::make_shared(); @@ -1982,6 +1992,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + // Test that peer DNS SAN delimiter is applied correctly { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_DNS_SAN"); @@ -1989,8 +2000,10 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, dnsSansPeerCertificate()).WillRepeatedly(Return(sans)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san1,san2"))); } + // Test that an empty peer DNS SAN list returns a null value { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_DNS_SAN"); @@ -2002,6 +2015,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that a null connection returns a null peer DNS SAN { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); @@ -2010,8 +2024,8 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that the upstream peer IP san is returned by the formatter. { - // Use a local stream info for these tests as as setSslConnection can only be called once. NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_IP_SAN"); auto connection_info = std::make_shared(); @@ -2022,6 +2036,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + // Test that peer IP SAN delimiter is applied correctly { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_IP_SAN"); @@ -2029,8 +2044,10 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, ipSansPeerCertificate()).WillRepeatedly(Return(sans)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san1,san2"))); } + // Test that an empty peer IP SAN list returns a null value { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_PEER_IP_SAN"); @@ -2042,6 +2059,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that a null connection returns a null peer IP SAN { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); @@ -2050,6 +2068,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that the upstream local DNS san is returned by the formatter. { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_DNS_SAN"); @@ -2061,6 +2080,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + // Test that local DNS SAN delimiter is applied correctly { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_DNS_SAN"); @@ -2068,8 +2088,10 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, dnsSansLocalCertificate()).WillRepeatedly(Return(sans)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san1,san2"))); } + // Test that an empty local DNS SAN list returns a null value { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_DNS_SAN"); @@ -2081,6 +2103,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that a null connection returns a null local DNS SAN { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); @@ -2089,6 +2112,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that the upstream local URI san is returned by the formatter. { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_URI_SAN"); @@ -2100,6 +2124,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + // Test that local URI SAN delimiter is applied correctly { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_URI_SAN"); @@ -2107,8 +2132,10 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, uriSanLocalCertificate()).WillRepeatedly(Return(sans)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san1,san2"))); } + // Test that an empty local URI SAN list returns a null value { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_URI_SAN"); @@ -2120,6 +2147,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that a null connection returns a null local URI SAN { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); @@ -2128,6 +2156,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that the upstream local IP san is returned by the formatter. { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_IP_SAN"); @@ -2139,6 +2168,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::stringValue("san"))); } + // Test that local IP SAN delimiter is applied correctly { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_IP_SAN"); @@ -2146,8 +2176,10 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { const std::vector sans{"san1", "san2"}; EXPECT_CALL(*connection_info, ipSansLocalCertificate()).WillRepeatedly(Return(sans)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("san1,san2", upstream_format.formatWithContext({}, stream_info)); + EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), + ProtoEq(ValueUtil::stringValue("san1,san2"))); } + // Test that an empty local IP SAN list returns a null value { NiceMock stream_info; StreamInfoFormatter upstream_format("UPSTREAM_LOCAL_IP_SAN"); @@ -2159,6 +2191,7 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) { EXPECT_THAT(upstream_format.formatValueWithContext({}, stream_info), ProtoEq(ValueUtil::nullValue())); } + // Test that a null connection returns a null local IP SAN { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr);