Skip to content

HTTP: Associate Response crashes with the corresponding Request.#15029

Merged
mattklein123 merged 32 commits intoenvoyproxy:mainfrom
KBaichoo:associateReq
Mar 4, 2021
Merged

HTTP: Associate Response crashes with the corresponding Request.#15029
mattklein123 merged 32 commits intoenvoyproxy:mainfrom
KBaichoo:associateReq

Conversation

@KBaichoo
Copy link
Copy Markdown
Contributor

@KBaichoo KBaichoo commented Feb 11, 2021

Commit Message: Implement dumping corresponding request for upstream response crashes.
Additional Description: We now track the stream that's being processed for H2 at the first callback that nghttp2 invokes and on crash for client stream we dump state of the responseDecoder which is an UpstreamRequest to dump the originating Request. Handles the case for H2 and H1.
Risk Level: Medium
Testing: Unit tests
Docs Changes: N/A
Release Notes: Included
Platform Specific Features: N/A
Related Issue #14249

Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@KBaichoo
Copy link
Copy Markdown
Contributor Author

/assign @antoniovicente

@KBaichoo KBaichoo changed the title Associate req HTTP2: Associate Response crashes with the corresponding Request. Feb 11, 2021
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@KBaichoo
Copy link
Copy Markdown
Contributor Author

Tests are failing due to another PR #14924 which I'll need to merge in.

Copy link
Copy Markdown
Contributor

@antoniovicente antoniovicente left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. Just some things about RTTI use.

if (stream->stream_id_ == current_stream_id_.value()) {
ClientStreamImpl* client_stream = static_cast<ClientStreamImpl*>(stream.get());
Router::UpstreamToDownstream* upstream_to_downstream =
dynamic_cast<Router::UpstreamToDownstream*>(&client_stream->response_decoder_);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider adding a dumpState method to Http::ResponseDecoder that can be implemented by Router::UpstreamToDownstream instead of doing this dynamic cast? Google style avoids this kind of use of rtti.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's a good idea. I'll have Http::ResponseDecoder have such a method.

os << spaces << "Dumping corresponding downstream request for upstream stream "
<< current_stream_id_.value() << ":\n";

for (auto& stream : active_streams_) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider ConnectionImpl::getStream instead.

I can see iterating over active_streams_ being lower dependency and thus preferable when running from a crash handler.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good suggestion.

I'm a bit torn how to go on this, given that LL are terrible performance wise, and we're iterating over streams when we can just grab the one we want from the map.

Given that the max # of concurrent streams is configurable, and a reasonable number is likely 100, iterating over 100 streams isn't too bad. If this increases significantly though, then I think getStream would become more of a clear winner.

Given the expected size of say ~100 and fewer dependencies (i.e. doesn't depend on nghttp2's map), I think iterating is worth the trade-off. Will add a TODO here perhaps consider switching to getStream if we have 1000s of active streams in a connection.

Thoughts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use getStream.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

const auto addressProvider = upstream_to_downstream->connection().addressProviderSharedPtr();
const Http::RequestHeaderMap* request_headers = upstream_to_downstream->downstreamHeaders();
DUMP_DETAILS(addressProvider);
DUMP_DETAILS(request_headers);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to have ResponseDecoder dumpState dump these details.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% agree. Will do.

Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Copy link
Copy Markdown
Contributor Author

@KBaichoo KBaichoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback @antoniovicente.

Made the changes discussed below, and will open a PR with just these changes now that #14923 is in.

os << spaces << "Dumping corresponding downstream request for upstream stream "
<< current_stream_id_.value() << ":\n";

for (auto& stream : active_streams_) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good suggestion.

I'm a bit torn how to go on this, given that LL are terrible performance wise, and we're iterating over streams when we can just grab the one we want from the map.

Given that the max # of concurrent streams is configurable, and a reasonable number is likely 100, iterating over 100 streams isn't too bad. If this increases significantly though, then I think getStream would become more of a clear winner.

Given the expected size of say ~100 and fewer dependencies (i.e. doesn't depend on nghttp2's map), I think iterating is worth the trade-off. Will add a TODO here perhaps consider switching to getStream if we have 1000s of active streams in a connection.

Thoughts?

const auto addressProvider = upstream_to_downstream->connection().addressProviderSharedPtr();
const Http::RequestHeaderMap* request_headers = upstream_to_downstream->downstreamHeaders();
DUMP_DETAILS(addressProvider);
DUMP_DETAILS(request_headers);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% agree. Will do.

if (stream->stream_id_ == current_stream_id_.value()) {
ClientStreamImpl* client_stream = static_cast<ClientStreamImpl*>(stream.get());
Router::UpstreamToDownstream* upstream_to_downstream =
dynamic_cast<Router::UpstreamToDownstream*>(&client_stream->response_decoder_);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's a good idea. I'll have Http::ResponseDecoder have such a method.

@antoniovicente
Copy link
Copy Markdown
Contributor

Thanks for the feedback @antoniovicente.

Made the changes discussed below, and will open a PR with just these changes now that #14923 is in.

Just do a main merge, we shouldn't need to start a new PR from scratch.

Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@KBaichoo KBaichoo marked this pull request as ready for review February 17, 2021 20:28
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@snowp snowp added the waiting label Mar 2, 2021
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@KBaichoo
Copy link
Copy Markdown
Contributor Author

KBaichoo commented Mar 2, 2021

Merged, thanks @snowp !

snowp
snowp previously approved these changes Mar 2, 2021
@KBaichoo
Copy link
Copy Markdown
Contributor Author

KBaichoo commented Mar 2, 2021

/retest

macos timed out

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #15029 (comment) was created by @KBaichoo.

see: more, trace.

@KBaichoo
Copy link
Copy Markdown
Contributor Author

KBaichoo commented Mar 2, 2021

/retest

macos was cancelled again

Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think needs a release notes fix, thank you.

/wait

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #15029 (comment) was created by @KBaichoo.

see: more, trace.

@mattklein123 mattklein123 self-assigned this Mar 2, 2021
Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@mattklein123
Copy link
Copy Markdown
Member

Can you merge main also? It will likely fix OSX CI and we can make sure the release notes look good.

Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@KBaichoo
Copy link
Copy Markdown
Contributor Author

KBaichoo commented Mar 2, 2021

Merged

* grpc_json_transcoder: added :ref:`request_validation_options <envoy_v3_api_field_extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder.request_validation_options>` to reject invalid requests early.
* grpc_json_transcoder: filter can now be configured on per-route/per-vhost level as well. Leaving empty list of services in the filter configuration disables transcoding on the specific route.
* http: added support for `Envoy::ScopeTrackedObject` for HTTP/1 and HTTP/2 dispatching. Crashes while inside the dispatching loop should dump debug information.
* http: added an option to not add content-length: 0 for requests which should not have bodies. This behavior can be enabled by setting `envoy.reloadable_features.dont_add_content_length_for_bodiless_requests` true.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you still have a merge issue? Why is this being added?

/wait

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it was originally in new features but got moved to minor behavior changes on line 45.

Signed-off-by: Kevin Baichoo <kbaichoo@google.com>
@KBaichoo
Copy link
Copy Markdown
Contributor Author

KBaichoo commented Mar 3, 2021

/retest

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #15029 (comment) was created by @KBaichoo.

see: more, trace.

@KBaichoo
Copy link
Copy Markdown
Contributor Author

KBaichoo commented Mar 3, 2021

/retest

N-th times the charm mac os? 🤞

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #15029 (comment) was created by @KBaichoo.

see: more, trace.

Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@mattklein123 mattklein123 merged commit 15f6b7a into envoyproxy:main Mar 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants