From 029e8080bd9fe5f254f7783881f619c0cb95ed4c Mon Sep 17 00:00:00 2001 From: Xuyang Tao Date: Wed, 25 Sep 2024 21:46:56 +0000 Subject: [PATCH] cel: add response.backend_latency in CEL attributes (#36292) We will depend on CEL to get those information inside HTTP wasm - unit tests added - doc added Signed-off-by: Xuyang Tao --- docs/root/intro/arch_overview/advanced/attributes.rst | 1 + source/extensions/filters/common/expr/context.cc | 9 +++++++++ source/extensions/filters/common/expr/context.h | 2 ++ test/extensions/filters/common/expr/context_test.cc | 8 ++++++++ 4 files changed, 20 insertions(+) diff --git a/docs/root/intro/arch_overview/advanced/attributes.rst b/docs/root/intro/arch_overview/advanced/attributes.rst index eae665abf3b5..f3f8e6fb84c0 100644 --- a/docs/root/intro/arch_overview/advanced/attributes.rst +++ b/docs/root/intro/arch_overview/advanced/attributes.rst @@ -93,6 +93,7 @@ Response attributes are only available after the request completes. response.trailers, "map", All response trailers indexed by the lower-cased trailer name response.size, int, Size of the response body response.total_size, int, Total size of the response including the approximate uncompressed size of the headers and the trailers + response.backend_latency, duration, Duration between the first byte sent to and the last byte received from the upstream backend Connection attributes --------------------- diff --git a/source/extensions/filters/common/expr/context.cc b/source/extensions/filters/common/expr/context.cc index cc30fb794a95..10438dff4df2 100644 --- a/source/extensions/filters/common/expr/context.cc +++ b/source/extensions/filters/common/expr/context.cc @@ -184,6 +184,15 @@ absl::optional ResponseWrapper::operator[](CelValue key) const { return CelValue::CreateString(&details.value()); } return {}; + } else if (value == BackendLatency) { + Envoy::StreamInfo::TimingUtility timing(info_); + const auto last_upstream_rx_byte_received = timing.lastUpstreamRxByteReceived(); + const auto first_upstream_tx_byte_sent = timing.firstUpstreamTxByteSent(); + if (last_upstream_rx_byte_received.has_value() && first_upstream_tx_byte_sent.has_value()) { + return CelValue::CreateDuration(absl::FromChrono(last_upstream_rx_byte_received.value() - + first_upstream_tx_byte_sent.value())); + } + return {}; } return {}; } diff --git a/source/extensions/filters/common/expr/context.h b/source/extensions/filters/common/expr/context.h index 7e5f5d1defec..867776641ee2 100644 --- a/source/extensions/filters/common/expr/context.h +++ b/source/extensions/filters/common/expr/context.h @@ -8,6 +8,7 @@ #include "source/common/http/headers.h" #include "source/common/runtime/runtime_features.h" #include "source/common/singleton/const_singleton.h" +#include "source/common/stream_info/utility.h" #include "eval/public/cel_value.h" #include "eval/public/containers/container_backed_list_impl.h" @@ -47,6 +48,7 @@ constexpr absl::string_view CodeDetails = "code_details"; constexpr absl::string_view Trailers = "trailers"; constexpr absl::string_view Flags = "flags"; constexpr absl::string_view GrpcStatus = "grpc_status"; +constexpr absl::string_view BackendLatency = "backend_latency"; // Per-request or per-connection metadata constexpr absl::string_view Metadata = "metadata"; diff --git a/test/extensions/filters/common/expr/context_test.cc b/test/extensions/filters/common/expr/context_test.cc index 733c2413ce2c..c766d47e258d 100644 --- a/test/extensions/filters/common/expr/context_test.cc +++ b/test/extensions/filters/common/expr/context_test.cc @@ -411,6 +411,14 @@ TEST(Context, ResponseAttributes) { EXPECT_FALSE(value.has_value()); } + { + info.setUpstreamInfo(std::make_shared()); + StreamInfo::UpstreamTiming& upstream_timing = info.upstreamInfo()->upstreamTiming(); + upstream_timing.onFirstUpstreamTxByteSent(info.timeSource()); + upstream_timing.onLastUpstreamRxByteReceived(info.timeSource()); + EXPECT_TRUE(response[CelValue::CreateStringView(BackendLatency)].has_value()); + } + { Http::TestResponseHeaderMapImpl header_map{{header_name, "a"}, {grpc_status, "7"}}; Http::TestResponseTrailerMapImpl trailer_map{{trailer_name, "b"}};