-
Notifications
You must be signed in to change notification settings - Fork 5.1k
thrift_proxy: introduce MessageMetadata to track message headers and other metadata #3991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
thrift_proxy: introduce MessageMetadata to track message headers and other metadata #3991
Conversation
…other metadata In advance of implementing the header transport and "ttwitter" protocol, refactor the message metadata (method name, message type, sequence id) into a metadata object. The MessageMetadata also tracks the protocol (provided by the header transport) and app exception data for exceptions triggered by the transport before the message begins. *Risk Level*: low *Testing*: existing tests *Docs Changes*: n/a *Release Notes*: n/a Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
@@ -52,13 +51,13 @@ bool BinaryProtocolImpl::readMessageBegin(Buffer::Instance& buffer, std::string& | |||
buffer.drain(8); | |||
|
|||
if (name_len > 0) { | |||
name.assign(std::string(static_cast<char*>(buffer.linearize(name_len)), name_len)); | |||
metadata.setMethodName(std::string(static_cast<char*>(buffer.linearize(name_len)), name_len)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[minor] The cast ideally should be to const char*
rather than char*
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should there be a check for name_len
's max value? Otherwise an ill formed message could trigger big allocations... Or is buffer.length()
checked for max length somewhere else? Even so, should we check for name_len's max here?
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
@brian-pane ptal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. A few questions/nits; general plea for small PRs (and for major cleanups, to make them as mechanical as possible). I know that's not always pragmatic, but where plausible.
proto.writeMessageBegin(buffer, method_name_, ThriftProxy::MessageType::Exception, seq_id_); | ||
void AppException::encode(MessageMetadata& metadata, ThriftProxy::Protocol& proto, | ||
Buffer::Instance& buffer) const { | ||
ASSERT(metadata.hasMethodName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you comment on how this is known to be true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Roughly because of the locations where the class is instantiated, but I'll need it to handle their absence, so I'll just add that.
return; | ||
} catch (const AppException& ex) { | ||
ENVOY_LOG(error, "thrift application exception: {}", ex.what()); | ||
if (!rpcs_.empty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Prefer to invert the logic here.
ENVOY_LOG(debug, "thrift: need more data for {} transport start", transport_->name()); | ||
buffer_underflow = true; | ||
return ThriftFilters::FilterStatus::Continue; | ||
} | ||
ENVOY_LOG(debug, "thrift: {} transport started", transport_->name()); | ||
|
||
if (metadata_->hasProtocol()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a behavioral change; ideally we would split that out from the refactor around metadata that is happening.
} | ||
|
||
for (auto i = headers_.begin(), j = rhs.headers_.begin(); i != headers_.end(); ++i, ++j) { | ||
if (i->key() != j->key() || i->value() != j->value()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the map inherently ordered?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point it is. I'll discuss more in the question about HeaderMap below.
/* | ||
* HeaderMap contains Thrift transport and/or protocol-level headers. | ||
*/ | ||
class HeaderMap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a new HeaderMap abstraction? Could we reuse the existing HTTP one via an adapter or just use a limited surface of its APIs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered using the Http::HeaderMap. I like the idea of reusing LowerCaseString and HeaderEntryImpl and it's memory management. I balked because it seems likely that most of the 70-odd inline headers will never see use in Thrift. (The non-inline headers are stored in a list, as in the local implementation). I suppose using the Http::HeaderMap will make my life easier when I add logging, since that API takes them. I'll have another look at reusing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, at some point I would like to make the inline headers that the HeaderMapImpl supports runtime configurable. I think this is possible with some work. Obviously not suggesting you do that, but I thought I would throw that out there. I think that's potentially interesting when private filters want to add extra inline headers and/or we would like to prune some of the inline headers that might not be used in all installations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be awesome.
@htuch do you mind if I leave this as-is for now and reconsider it when we're actually able to use headers for routing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but if you could either put in a TODO or file an issue to track this it'd be great, whatever you think is appropriate.
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see test/extensions/filters/network/thrift_proxy/tmp
as part of the first commit, did that get in by accident?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you take a look at the merge conflict? I think this looks good to go otherwise based on surface analysis.
/* | ||
* HeaderMap contains Thrift transport and/or protocol-level headers. | ||
*/ | ||
class HeaderMap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but if you could either put in a TODO or file an issue to track this it'd be great, whatever you think is appropriate.
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Added a todo, removed the stray file, and merged master. |
In advance of implementing the header transport and "ttwitter" protocol, refactor
the message metadata (method name, message type, sequence id) into a metadata object.
The MessageMetadata also tracks the protocol (provided by the header transport) and
app exception data for exceptions triggered by the transport before the message begins.
Risk Level: low
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a
Signed-off-by: Stephan Zuercher stephan@turbinelabs.io