Skip to content

Commit d6b6213

Browse files
venilnoronhaistio-testing
authored andcommitted
Enable caching of dynamic metadata in mixer filter (#2040)
* Enable caching of dynamic metadata in mixer filter This enables caching of dynamic metadata in the onData call in the mixer filter and returns the same during the GetDynamicFilterState call. Signed-off-by: Venil Noronha <[email protected]> * Update cloning to reflect Mongo format updates This updates the deep cloning logic in the mixer filter to reflect the latest changes in the Mongo proxy filter's dynamic metadata format. Signed-off-by: Venil Noronha <[email protected]>
1 parent 9b91ac6 commit d6b6213

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

src/envoy/tcp/mixer/filter.cc

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "src/envoy/tcp/mixer/filter.h"
1717
#include "common/common/enum_to_int.h"
18+
#include "extensions/filters/network/well_known_names.h"
1819
#include "src/envoy/utils/utils.h"
1920

2021
using ::google::protobuf::util::Status;
@@ -66,6 +67,31 @@ void Filter::callCheck() {
6667
calling_check_ = false;
6768
}
6869

70+
// TODO(venilnoronha): rewrite this to deep-clone dynamic metadata for all
71+
// filters.
72+
void Filter::cacheFilterMetadata(
73+
const ::google::protobuf::Map<std::string, ::google::protobuf::Struct>
74+
&filter_metadata) {
75+
for (auto &filter_pair : filter_metadata) {
76+
if (filter_pair.first ==
77+
Extensions::NetworkFilters::NetworkFilterNames::get().MongoProxy) {
78+
if (cached_filter_metadata_.count(filter_pair.first) == 0) {
79+
ProtobufWkt::Struct dynamic_metadata;
80+
cached_filter_metadata_[filter_pair.first] = dynamic_metadata;
81+
}
82+
83+
auto &cached_fields =
84+
*cached_filter_metadata_[filter_pair.first].mutable_fields();
85+
for (const auto &message_pair : filter_pair.second.fields()) {
86+
cached_fields[message_pair.first].mutable_list_value()->CopyFrom(
87+
message_pair.second.list_value());
88+
}
89+
}
90+
}
91+
}
92+
93+
void Filter::clearCachedFilterMetadata() { cached_filter_metadata_.clear(); }
94+
6995
// Network::ReadFilter
7096
Network::FilterStatus Filter::onData(Buffer::Instance &data, bool) {
7197
if (state_ == State::NotStarted) {
@@ -78,6 +104,17 @@ Network::FilterStatus Filter::onData(Buffer::Instance &data, bool) {
78104
filter_callbacks_->connection(), data.length());
79105
received_bytes_ += data.length();
80106

107+
// Envoy filters like the mongo_proxy filter clear previously set dynamic
108+
// metadata on each onData call. Since the Mixer filter sends metadata based
109+
// on a timer event, it's possible that the previously set metadata is cleared
110+
// off by the time the event is fired. Therefore, we append metadata from each
111+
// onData call to a local cache and send it all at once when the timer event
112+
// occurs. The local cache is cleared after reporting it on the timer event.
113+
cacheFilterMetadata(filter_callbacks_->connection()
114+
.streamInfo()
115+
.dynamicMetadata()
116+
.filter_metadata());
117+
81118
return state_ == State::Calling ? Network::FilterStatus::StopIteration
82119
: Network::FilterStatus::Continue;
83120
}
@@ -150,6 +187,7 @@ bool Filter::GetSourceIpPort(std::string *str_ip, int *port) const {
150187
return Utils::GetIpPort(filter_callbacks_->connection().remoteAddress()->ip(),
151188
str_ip, port);
152189
}
190+
153191
bool Filter::GetPrincipal(bool peer, std::string *user) const {
154192
return Utils::GetPrincipal(&filter_callbacks_->connection(), peer, user);
155193
}
@@ -170,20 +208,20 @@ bool Filter::GetDestinationIpPort(std::string *str_ip, int *port) const {
170208
}
171209
return false;
172210
}
211+
173212
bool Filter::GetDestinationUID(std::string *uid) const {
174213
if (filter_callbacks_->upstreamHost()) {
175214
return Utils::GetDestinationUID(
176215
*filter_callbacks_->upstreamHost()->metadata(), uid);
177216
}
178217
return false;
179218
}
219+
180220
const ::google::protobuf::Map<std::string, ::google::protobuf::Struct>
181221
&Filter::GetDynamicFilterState() const {
182-
return filter_callbacks_->connection()
183-
.streamInfo()
184-
.dynamicMetadata()
185-
.filter_metadata();
222+
return cached_filter_metadata_;
186223
}
224+
187225
void Filter::GetReportInfo(
188226
::istio::control::tcp::ReportData::ReportInfo *data) const {
189227
data->received_bytes = received_bytes_;
@@ -202,6 +240,7 @@ std::string Filter::GetConnectionId() const {
202240

203241
void Filter::OnReportTimer() {
204242
handler_->Report(this, ConnectionEvent::CONTINUE);
243+
clearCachedFilterMetadata();
205244
report_timer_->enableTimer(control_.config().report_interval_ms());
206245
}
207246

src/envoy/tcp/mixer/filter.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ class Filter : public Network::Filter,
6565
::istio::control::tcp::ReportData::ReportInfo *data) const override;
6666
std::string GetConnectionId() const override;
6767

68+
void cacheFilterMetadata(
69+
const ::google::protobuf::Map<std::string, ::google::protobuf::Struct>
70+
&filter_metadata);
71+
void clearCachedFilterMetadata();
72+
6873
private:
6974
enum class State { NotStarted, Calling, Completed, Closed };
7075
// This function is invoked when timer event fires.
@@ -96,6 +101,9 @@ class Filter : public Network::Filter,
96101
uint64_t received_bytes_{};
97102
// send bytes
98103
uint64_t send_bytes_{};
104+
// cached filter metadata
105+
::google::protobuf::Map<std::string, ::google::protobuf::Struct>
106+
cached_filter_metadata_{};
99107

100108
// Timer that periodically sends reports.
101109
Event::TimerPtr report_timer_;

0 commit comments

Comments
 (0)