Skip to content

Commit 5b8331d

Browse files
authored
network_ext_proc: add more counters and tests (envoyproxy#39265)
Risk Level: low Testing: unit & integration tests Docs Changes: Release Notes: Platform Specific Features: --------- Signed-off-by: Boteng Yao <[email protected]>
1 parent 7e8f7fa commit 5b8331d

File tree

7 files changed

+281
-21
lines changed

7 files changed

+281
-21
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
3434
//
3535
// By using the filter's processing mode, you can selectively choose which data
3636
// directions to process (read, write or both), allowing for efficient processing.
37+
// [#next-free-field: 6]
3738
message NetworkExternalProcessor {
3839
// The gRPC service that will process network traffic.
3940
// This service must implement the NetworkExternalProcessor service
@@ -61,6 +62,8 @@ message NetworkExternalProcessor {
6162
lte {seconds: 3600}
6263
gte {}
6364
}];
65+
66+
string stat_prefix = 5 [(validate.rules).string = {min_len: 1}];
6467
}
6568

6669
// Options for controlling processing behavior.

source/extensions/filters/network/ext_proc/config.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ Network::FilterFactoryCb NetworkExtProcConfigFactory::createFilterFactoryFromPro
4242
if (!result.ok()) {
4343
throw EnvoyException(std::string(result.message()));
4444
}
45-
46-
ConfigConstSharedPtr ext_proc_config = std::make_shared<const Config>(proto_config);
45+
ConfigConstSharedPtr ext_proc_config =
46+
std::make_shared<const Config>(proto_config, context.scope());
4747

4848
return [ext_proc_config, &context](Network::FilterManager& filter_manager) -> void {
4949
auto client = createExternalProcessorClient(

source/extensions/filters/network/ext_proc/ext_proc.cc

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ namespace ExtProc {
77

88
NetworkExtProcFilter::NetworkExtProcFilter(ConfigConstSharedPtr config,
99
ExternalProcessorClientPtr&& client)
10-
: config_(config), client_(std::move(client)), config_with_hash_key_(config_->grpcService()),
11-
downstream_callbacks_(*this) {}
10+
: config_(config), stats_(config->stats()), client_(std::move(client)),
11+
config_with_hash_key_(config_->grpcService()), downstream_callbacks_(*this) {}
1212

1313
NetworkExtProcFilter::~NetworkExtProcFilter() { closeStream(); }
1414

@@ -81,6 +81,7 @@ Network::FilterStatus NetworkExtProcFilter::handleStreamError() {
8181

8282
if (config_->failureModeAllow()) {
8383
// In failure allow mode, continue processing despite stream errors
84+
stats_.failure_mode_allowed_.inc();
8485
return Network::FilterStatus::Continue;
8586
} else {
8687
// In strict mode, close the connection and stop processing
@@ -140,10 +141,12 @@ NetworkExtProcFilter::StreamOpenState NetworkExtProcFilter::openStream() {
140141
if (stream_object == nullptr) {
141142
ENVOY_CONN_LOG(error, "Failed to create gRPC stream to external processor",
142143
read_callbacks_->connection());
144+
stats_.stream_open_failures_.inc();
143145
return StreamOpenState::Error;
144146
}
145147

146148
stream_ = std::move(stream_object);
149+
stats_.streams_started_.inc();
147150
return StreamOpenState::Ok;
148151
}
149152

@@ -166,14 +169,17 @@ void NetworkExtProcFilter::sendRequest(Buffer::Instance& data, bool end_stream,
166169
auto* read_data = request.mutable_read_data();
167170
read_data->set_data(data.toString());
168171
read_data->set_end_of_stream(end_stream);
172+
stats_.read_data_sent_.inc();
169173
} else {
170174
auto* write_data = request.mutable_write_data();
171175
write_data->set_data(data.toString());
172176
write_data->set_end_of_stream(end_stream);
177+
stats_.write_data_sent_.inc();
173178
}
174179

175180
// Send to external processor
176181
stream_->send(std::move(request), false);
182+
stats_.stream_msgs_sent_.inc();
177183

178184
// Clear data buffer after sending
179185
data.drain(data.length());
@@ -183,11 +189,13 @@ void NetworkExtProcFilter::onReceiveMessage(std::unique_ptr<ProcessingResponse>&
183189
if (processing_complete_) {
184190
ENVOY_CONN_LOG(debug, "Ignoring response message: processing already completed",
185191
read_callbacks_->connection());
192+
stats_.spurious_msgs_received_.inc();
186193
return;
187194
}
188195

189196
auto response = std::move(res);
190197
ENVOY_CONN_LOG(debug, "Received response from external processor", read_callbacks_->connection());
198+
stats_.stream_msgs_received_.inc();
191199

192200
if (response->has_read_data()) {
193201
const auto& data = response->read_data();
@@ -197,15 +205,18 @@ void NetworkExtProcFilter::onReceiveMessage(std::unique_ptr<ProcessingResponse>&
197205
Buffer::OwnedImpl buffer(data.data());
198206
read_callbacks_->injectReadDataToFilterChain(buffer, data.end_of_stream());
199207
updateCloseCallbackStatus(false, true);
208+
stats_.read_data_injected_.inc();
200209
} else if (response->has_write_data()) {
201210
const auto& data = response->write_data();
202211
ENVOY_CONN_LOG(trace, "Processing WRITE data response: {} bytes, end_stream={}",
203212
read_callbacks_->connection(), data.data().size(), data.end_of_stream());
204213
Buffer::OwnedImpl buffer(data.data());
205214
write_callbacks_->injectWriteDataToFilterChain(buffer, data.end_of_stream());
206215
updateCloseCallbackStatus(false, false);
216+
stats_.write_data_injected_.inc();
207217
} else {
208218
ENVOY_CONN_LOG(debug, "Response contained no data, continuing", read_callbacks_->connection());
219+
stats_.empty_response_received_.inc();
209220
}
210221
}
211222

@@ -216,6 +227,7 @@ void NetworkExtProcFilter::onGrpcError(Grpc::Status::GrpcStatus status,
216227
// Mark processing as complete to avoid further gRPC calls
217228
processing_complete_ = true;
218229
closeStream();
230+
stats_.streams_grpc_error_.inc();
219231

220232
// If failure mode is not to allow, close the connection
221233
if (!config_->failureModeAllow()) {
@@ -224,11 +236,14 @@ void NetworkExtProcFilter::onGrpcError(Grpc::Status::GrpcStatus status,
224236
closeConnection("ext_proc_grpc_error");
225237
return;
226238
}
239+
240+
stats_.failure_mode_allowed_.inc();
227241
}
228242

229243
void NetworkExtProcFilter::onGrpcClose() {
230244
ENVOY_CONN_LOG(debug, "gRPC stream closed by peer", read_callbacks_->connection());
231245
processing_complete_ = true;
246+
stats_.streams_grpc_close_.inc();
232247
closeStream();
233248
}
234249

@@ -238,6 +253,9 @@ void NetworkExtProcFilter::closeStream() {
238253
}
239254

240255
bool closed = stream_->close();
256+
if (closed) {
257+
stats_.streams_closed_.inc();
258+
}
241259
ENVOY_CONN_LOG(debug, "Stream closed: {}", read_callbacks_->connection(), closed);
242260
stream_ = nullptr;
243261
}
@@ -249,6 +267,7 @@ void NetworkExtProcFilter::closeConnection(const std::string& reason) {
249267
read_callbacks_->disableClose(false);
250268
write_callbacks_->disableClose(false);
251269
read_callbacks_->connection().close(Network::ConnectionCloseType::FlushWrite, reason);
270+
stats_.connections_closed_.inc();
252271
}
253272

254273
} // namespace ExtProc

source/extensions/filters/network/ext_proc/ext_proc.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,37 @@ namespace Extensions {
1919
namespace NetworkFilters {
2020
namespace ExtProc {
2121

22+
#define ALL_NETWORK_EXT_PROC_FILTER_STATS(COUNTER) \
23+
COUNTER(streams_started) \
24+
COUNTER(stream_msgs_sent) \
25+
COUNTER(stream_msgs_received) \
26+
COUNTER(read_data_sent) \
27+
COUNTER(write_data_sent) \
28+
COUNTER(read_data_injected) \
29+
COUNTER(write_data_injected) \
30+
COUNTER(empty_response_received) \
31+
COUNTER(spurious_msgs_received) \
32+
COUNTER(streams_closed) \
33+
COUNTER(streams_grpc_error) \
34+
COUNTER(streams_grpc_close) \
35+
COUNTER(connections_closed) \
36+
COUNTER(failure_mode_allowed) \
37+
COUNTER(stream_open_failures)
38+
39+
struct NetworkExtProcStats {
40+
ALL_NETWORK_EXT_PROC_FILTER_STATS(GENERATE_COUNTER_STRUCT)
41+
};
42+
2243
/**
2344
* Global configuration for Network ExtProc filter.
2445
*/
2546
class Config {
2647
public:
27-
Config(const envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor& config)
48+
Config(const envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor& config,
49+
Stats::Scope& scope)
2850
: failure_mode_allow_(config.failure_mode_allow()),
29-
processing_mode_(config.processing_mode()), grpc_service_(config.grpc_service()) {};
51+
processing_mode_(config.processing_mode()), grpc_service_(config.grpc_service()),
52+
stats_(generateStats(config.stat_prefix(), scope)) {};
3053

3154
bool failureModeAllow() const { return failure_mode_allow_; }
3255

@@ -36,10 +59,18 @@ class Config {
3659

3760
const envoy::config::core::v3::GrpcService& grpcService() const { return grpc_service_; }
3861

62+
const NetworkExtProcStats& stats() const { return stats_; }
63+
3964
private:
65+
NetworkExtProcStats generateStats(const std::string& prefix, Stats::Scope& scope) {
66+
const std::string final_prefix = absl::StrCat("network_ext_proc.", prefix);
67+
return {ALL_NETWORK_EXT_PROC_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix))};
68+
}
69+
4070
const bool failure_mode_allow_;
4171
const envoy::extensions::filters::network::ext_proc::v3::ProcessingMode processing_mode_;
4272
const envoy::config::core::v3::GrpcService grpc_service_;
73+
NetworkExtProcStats stats_;
4374
};
4475

4576
using ConfigConstSharedPtr = std::shared_ptr<const Config>;
@@ -114,6 +145,7 @@ class NetworkExtProcFilter : public Envoy::Network::Filter,
114145
Envoy::Network::WriteFilterCallbacks* write_callbacks_{nullptr};
115146

116147
const ConfigConstSharedPtr config_;
148+
const NetworkExtProcStats& stats_;
117149
ExternalProcessorClientPtr client_;
118150
ExternalProcessorStreamPtr stream_;
119151
const Envoy::Grpc::GrpcServiceConfigWithHashKey config_with_hash_key_;

test/extensions/filters/network/ext_proc/config_test.cc

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,17 @@ namespace NetworkFilters {
1313
namespace ExtProc {
1414
namespace {
1515

16+
class ConfigTest : public testing::Test {
17+
public:
18+
ConfigTest() {}
19+
20+
protected:
21+
NiceMock<Stats::MockIsolatedStatsStore> store_;
22+
Stats::Scope& scope_{*store_.rootScope()};
23+
};
24+
1625
// Test the basic config setter and getter.
17-
TEST(ConfigTest, BasicConfigTest) {
26+
TEST_F(ConfigTest, BasicConfigTest) {
1827
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
1928
proto_config.set_failure_mode_allow(true);
2029

@@ -24,7 +33,7 @@ TEST(ConfigTest, BasicConfigTest) {
2433
processing_mode->set_process_write(
2534
envoy::extensions::filters::network::ext_proc::v3::ProcessingMode::STREAMED);
2635

27-
Config config(proto_config);
36+
Config config(proto_config, scope_);
2837

2938
EXPECT_TRUE(config.failureModeAllow());
3039

@@ -35,10 +44,10 @@ TEST(ConfigTest, BasicConfigTest) {
3544
envoy::extensions::filters::network::ext_proc::v3::ProcessingMode::STREAMED);
3645
}
3746

38-
TEST(ConfigTest, DefaultValues) {
47+
TEST_F(ConfigTest, DefaultValues) {
3948
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
4049

41-
Config config(proto_config);
50+
Config config(proto_config, scope_);
4251

4352
// Test the default value for failureModeAllow (should be false by default in protobuf)
4453
EXPECT_FALSE(config.failureModeAllow());
@@ -52,7 +61,7 @@ TEST(ConfigTest, DefaultValues) {
5261
}
5362

5463
// Test when both read and write are set to SKIP
55-
TEST(ConfigTest, BothSkipMode) {
64+
TEST_F(ConfigTest, BothSkipMode) {
5665
// Create a protobuf config with both read and write set to SKIP
5766
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
5867

@@ -62,7 +71,7 @@ TEST(ConfigTest, BothSkipMode) {
6271
processing_mode->set_process_write(
6372
envoy::extensions::filters::network::ext_proc::v3::ProcessingMode::SKIP);
6473

65-
Config config(proto_config);
74+
Config config(proto_config, scope_);
6675

6776
const auto& mode = config.processingMode();
6877
EXPECT_EQ(mode.process_read(),
@@ -77,6 +86,7 @@ TEST(NetworkExtProcConfigTest, SimpleConfig) {
7786
grpc_service:
7887
envoy_grpc:
7988
cluster_name: "ext_proc_server"
89+
stat_prefix: "test_ext_proc"
8090
)EOF";
8191

8292
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
@@ -97,6 +107,7 @@ TEST(NetworkExtProcConfigTest, ConfigWithOptions) {
97107
cluster_name: "ext_proc_server"
98108
failure_mode_allow: true
99109
message_timeout: 2s
110+
stat_prefix: "test_ext_proc"
100111
)EOF";
101112

102113
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
@@ -112,6 +123,7 @@ TEST(NetworkExtProcConfigTest, ConfigWithOptions) {
112123
// Test the config without a gRPC service.
113124
TEST(NetworkExtProcConfigFactoryTest, MissingGrpcService) {
114125
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
126+
proto_config.set_stat_prefix("test_ext_proc");
115127

116128
NiceMock<Server::Configuration::MockFactoryContext> context;
117129
NetworkExtProcConfigFactory factory;
@@ -124,6 +136,7 @@ TEST(NetworkExtProcConfigFactoryTest, MissingGrpcService) {
124136
TEST(NetworkExtProcConfigFactoryTest, BothModesSkipped) {
125137
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
126138
proto_config.mutable_grpc_service()->mutable_envoy_grpc()->set_cluster_name("ext_proc_server");
139+
proto_config.set_stat_prefix("test_ext_proc");
127140

128141
auto* processing_mode = proto_config.mutable_processing_mode();
129142
processing_mode->set_process_read(
@@ -143,6 +156,7 @@ TEST(NetworkExtProcConfigFactoryTest, BothModesSkipped) {
143156
TEST(NetworkExtProcConfigFactoryTest, DefaultProcessingMode) {
144157
envoy::extensions::filters::network::ext_proc::v3::NetworkExternalProcessor proto_config;
145158
proto_config.mutable_grpc_service()->mutable_envoy_grpc()->set_cluster_name("ext_proc_server");
159+
proto_config.set_stat_prefix("test_ext_proc");
146160

147161
NiceMock<Server::Configuration::MockFactoryContext> context;
148162
NetworkExtProcConfigFactory factory;

0 commit comments

Comments
 (0)