Skip to content

Commit fe89065

Browse files
tyxiapull[bot]
authored andcommitted
api: Add observability mode in ext_proc (envoyproxy#32696)
--------- Signed-off-by: tyxia <tyxia@google.com>
1 parent e2702b3 commit fe89065

4 files changed

Lines changed: 64 additions & 40 deletions

File tree

api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,12 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
9797
// <arch_overview_advanced_filter_state_sharing>` object in a namespace matching the filter
9898
// name.
9999
//
100-
// [#next-free-field: 17]
100+
// [#next-free-field: 18]
101101
message ExternalProcessor {
102+
reserved 4;
103+
104+
reserved "async_mode";
105+
102106
// Configuration for the gRPC service that the filter will communicate with.
103107
// The filter supports both the "Envoy" and "Google" gRPC clients.
104108
config.core.v3.GrpcService grpc_service = 1 [(validate.rules).message = {required: true}];
@@ -116,14 +120,6 @@ message ExternalProcessor {
116120
// sent. See ProcessingMode for details.
117121
ProcessingMode processing_mode = 3;
118122

119-
// [#not-implemented-hide:]
120-
// If true, send each part of the HTTP request or response specified by ProcessingMode
121-
// asynchronously -- in other words, send the message on the gRPC stream and then continue
122-
// filter processing. If false, which is the default, suspend filter execution after
123-
// each message is sent to the remote service and wait up to "message_timeout"
124-
// for a reply.
125-
bool async_mode = 4;
126-
127123
// Envoy provides a number of :ref:`attributes <arch_overview_attributes>`
128124
// for expressive policies. Each attribute name provided in this field will be
129125
// matched against that list and populated in the request_headers message.
@@ -206,6 +202,30 @@ message ExternalProcessor {
206202

207203
// Options related to the sending and receiving of dynamic metadata.
208204
MetadataOptions metadata_options = 16;
205+
206+
// If true, send each part of the HTTP request or response specified by ProcessingMode
207+
// without pausing on filter chain iteration. It is "Send and Go" mode that can be used
208+
// by external processor to observe Envoy data and status. In this mode:
209+
//
210+
// 1. Only STREAMED body processing mode is supported and any other body processing modes will be
211+
// ignored. NONE mode(i.e., skip body processing) will still work as expected.
212+
//
213+
// 2. External processor should not send back processing response, as any responses will be ignored.
214+
// This also means that
215+
// :ref:`message_timeout <envoy_v3_api_field_extensions.filters.http.ext_proc.v3.ExternalProcessor.message_timeout>`
216+
// restriction doesn't apply to this mode.
217+
//
218+
// 3. External processor may still close the stream to indicate that no more messages are needed.
219+
//
220+
// .. warning::
221+
//
222+
// Flow control is necessary mechanism to prevent the fast sender (either downstream client or upstream server)
223+
// from overwhelming the external processor when its processing speed is slower.
224+
// This protective measure is being explored and developed but has not been ready yet, so please use your own
225+
// discretion when enabling this feature.
226+
// This work is currently tracked under https://github.com/envoyproxy/envoy/issues/33319.
227+
//
228+
bool observability_mode = 17;
209229
}
210230

211231
// The MetadataOptions structure defines options for the sending and receiving of

api/envoy/service/ext_proc/v3/external_processor.proto

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,11 @@ service ExternalProcessor {
5757

5858
// This represents the different types of messages that Envoy can send
5959
// to an external processing server.
60-
// [#next-free-field: 10]
60+
// [#next-free-field: 11]
6161
message ProcessingRequest {
62-
// Specify whether the filter that sent this request is running in synchronous
63-
// or asynchronous mode. The choice of synchronous or asynchronous mode
64-
// can be set in the filter configuration, and defaults to false.
65-
//
66-
// * A value of ``false`` indicates that the server must respond
67-
// to this message by either sending back a matching ProcessingResponse message,
68-
// or by closing the stream.
69-
// * A value of ``true`` indicates that the server must not respond to this
70-
// message, although it may still close the stream to indicate that no more messages
71-
// are needed.
72-
//
73-
bool async_mode = 1;
62+
reserved 1;
63+
64+
reserved "async_mode";
7465

7566
// Each request message will include one of the following sub-messages. Which
7667
// ones are set for a particular HTTP request/response depend on the
@@ -79,31 +70,31 @@ message ProcessingRequest {
7970
option (validate.required) = true;
8071

8172
// Information about the HTTP request headers, as well as peer info and additional
82-
// properties. Unless ``async_mode`` is ``true``, the server must send back a
73+
// properties. Unless ``observability_mode`` is ``true``, the server must send back a
8374
// HeaderResponse message, an ImmediateResponse message, or close the stream.
8475
HttpHeaders request_headers = 2;
8576

8677
// Information about the HTTP response headers, as well as peer info and additional
87-
// properties. Unless ``async_mode`` is ``true``, the server must send back a
78+
// properties. Unless ``observability_mode`` is ``true``, the server must send back a
8879
// HeaderResponse message or close the stream.
8980
HttpHeaders response_headers = 3;
9081

91-
// A chunk of the HTTP request body. Unless ``async_mode`` is true, the server must send back
82+
// A chunk of the HTTP request body. Unless ``observability_mode`` is true, the server must send back
9283
// a BodyResponse message, an ImmediateResponse message, or close the stream.
9384
HttpBody request_body = 4;
9485

95-
// A chunk of the HTTP response body. Unless ``async_mode`` is ``true``, the server must send back
86+
// A chunk of the HTTP response body. Unless ``observability_mode`` is ``true``, the server must send back
9687
// a BodyResponse message or close the stream.
9788
HttpBody response_body = 5;
9889

99-
// The HTTP trailers for the request path. Unless ``async_mode`` is ``true``, the server
90+
// The HTTP trailers for the request path. Unless ``observability_mode`` is ``true``, the server
10091
// must send back a TrailerResponse message or close the stream.
10192
//
10293
// This message is only sent if the trailers processing mode is set to ``SEND`` and
10394
// the original downstream request has trailers.
10495
HttpTrailers request_trailers = 6;
10596

106-
// The HTTP trailers for the response path. Unless ``async_mode`` is ``true``, the server
97+
// The HTTP trailers for the response path. Unless ``observability_mode`` is ``true``, the server
10798
// must send back a TrailerResponse message or close the stream.
10899
//
109100
// This message is only sent if the trailers processing mode is set to ``SEND`` and
@@ -119,9 +110,22 @@ message ProcessingRequest {
119110
// in the list is populated from the standard
120111
// :ref:`attributes <arch_overview_attributes>` supported across Envoy.
121112
map<string, google.protobuf.Struct> attributes = 9;
113+
114+
// Specify whether the filter that sent this request is running in :ref:`observability_mode
115+
// <envoy_v3_api_field_extensions.filters.http.ext_proc.v3.ExternalProcessor.observability_mode>`
116+
// and defaults to false.
117+
//
118+
// * A value of ``false`` indicates that the server must respond
119+
// to this message by either sending back a matching ProcessingResponse message,
120+
// or by closing the stream.
121+
// * A value of ``true`` indicates that the server should not respond to this message, as any
122+
// responses will be ignored. However, it may still close the stream to indicate that no more messages
123+
// are needed.
124+
//
125+
bool observability_mode = 10;
122126
}
123127

124-
// For every ProcessingRequest received by the server with the ``async_mode`` field
128+
// For every ProcessingRequest received by the server with the ``observability_mode`` field
125129
// set to false, the server must send back exactly one ProcessingResponse message.
126130
// [#next-free-field: 11]
127131
message ProcessingResponse {

test/extensions/filters/http/ext_proc/filter_test.cc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ class HttpFilterTest : public testing::Test {
261261
bool buffering_data,
262262
absl::optional<std::function<void(const HttpHeaders&, ProcessingResponse&, HeadersResponse&)>>
263263
cb) {
264-
EXPECT_FALSE(last_request_.async_mode());
264+
EXPECT_FALSE(last_request_.observability_mode());
265265
ASSERT_TRUE(last_request_.has_request_headers());
266266
const auto& headers = last_request_.request_headers();
267267
auto response = std::make_unique<ProcessingResponse>();
@@ -281,7 +281,7 @@ class HttpFilterTest : public testing::Test {
281281
bool buffering_data,
282282
absl::optional<std::function<void(const HttpHeaders&, ProcessingResponse&, HeadersResponse&)>>
283283
cb) {
284-
EXPECT_FALSE(last_request_.async_mode());
284+
EXPECT_FALSE(last_request_.observability_mode());
285285
ASSERT_TRUE(last_request_.has_response_headers());
286286
const auto& headers = last_request_.response_headers();
287287
auto response = std::make_unique<ProcessingResponse>();
@@ -301,7 +301,7 @@ class HttpFilterTest : public testing::Test {
301301
absl::optional<std::function<void(const HttpBody&, ProcessingResponse&, BodyResponse&)>> cb,
302302
bool should_continue = true,
303303
const std::chrono::microseconds latency = std::chrono::microseconds(10)) {
304-
EXPECT_FALSE(last_request_.async_mode());
304+
EXPECT_FALSE(last_request_.observability_mode());
305305
ASSERT_TRUE(last_request_.has_request_body());
306306
const auto& body = last_request_.request_body();
307307
auto response = std::make_unique<ProcessingResponse>();
@@ -320,7 +320,7 @@ class HttpFilterTest : public testing::Test {
320320
void processResponseBody(
321321
absl::optional<std::function<void(const HttpBody&, ProcessingResponse&, BodyResponse&)>> cb,
322322
bool should_continue = true) {
323-
EXPECT_FALSE(last_request_.async_mode());
323+
EXPECT_FALSE(last_request_.observability_mode());
324324
ASSERT_TRUE(last_request_.has_response_body());
325325
const auto& body = last_request_.response_body();
326326
auto response = std::make_unique<ProcessingResponse>();
@@ -340,7 +340,7 @@ class HttpFilterTest : public testing::Test {
340340
std::function<void(const HttpTrailers&, ProcessingResponse&, TrailersResponse&)>>
341341
cb,
342342
bool should_continue = true) {
343-
EXPECT_FALSE(last_request_.async_mode());
343+
EXPECT_FALSE(last_request_.observability_mode());
344344
ASSERT_TRUE(last_request_.has_request_trailers());
345345
const auto& trailers = last_request_.request_trailers();
346346
auto response = std::make_unique<ProcessingResponse>();
@@ -360,7 +360,7 @@ class HttpFilterTest : public testing::Test {
360360
std::function<void(const HttpTrailers&, ProcessingResponse&, TrailersResponse&)>>
361361
cb,
362362
bool should_continue = true) {
363-
EXPECT_FALSE(last_request_.async_mode());
363+
EXPECT_FALSE(last_request_.observability_mode());
364364
ASSERT_TRUE(last_request_.has_response_trailers());
365365
const auto& trailers = last_request_.response_trailers();
366366
auto response = std::make_unique<ProcessingResponse>();
@@ -853,7 +853,7 @@ TEST_F(HttpFilterTest, PostAndRespondImmediatelyOnResponse) {
853853

854854
EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_->encodeHeaders(response_headers_, false));
855855

856-
EXPECT_FALSE(last_request_.async_mode());
856+
EXPECT_FALSE(last_request_.observability_mode());
857857
ASSERT_TRUE(last_request_.has_response_headers());
858858

859859
TestResponseHeaderMapImpl immediate_response_headers;
@@ -2332,7 +2332,7 @@ TEST_F(HttpFilterTest, PostAndClose) {
23322332
// Create synthetic HTTP request
23332333
EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers_, false));
23342334

2335-
EXPECT_FALSE(last_request_.async_mode());
2335+
EXPECT_FALSE(last_request_.observability_mode());
23362336
ASSERT_TRUE(last_request_.has_request_headers());
23372337

23382338
// Close the stream, which should tell the filter to keep on going
@@ -2371,7 +2371,7 @@ TEST_F(HttpFilterTest, PostAndDownstreamReset) {
23712371
// Create synthetic HTTP request
23722372
EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers_, false));
23732373

2374-
EXPECT_FALSE(last_request_.async_mode());
2374+
EXPECT_FALSE(last_request_.observability_mode());
23752375
ASSERT_TRUE(last_request_.has_request_headers());
23762376
EXPECT_FALSE(allTimersDisabled());
23772377

@@ -2877,7 +2877,7 @@ TEST_F(HttpFilterTest, OutOfOrder) {
28772877
request_headers_.setMethod("POST");
28782878
EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers_, false));
28792879

2880-
EXPECT_FALSE(last_request_.async_mode());
2880+
EXPECT_FALSE(last_request_.observability_mode());
28812881
ASSERT_TRUE(last_request_.has_request_headers());
28822882

28832883
// Return an out-of-order message. The server should close the stream

test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/clusterfuzz-testcase-minimized-ext_proc_unit_test_fuzz-6492125776445440.fuzz

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)