Skip to content

feat(context): add response.grpc_status#9693

Merged
mattklein123 merged 7 commits intoenvoyproxy:masterfrom
douglas-reid:grpc-status-code
Jan 22, 2020
Merged

feat(context): add response.grpc_status#9693
mattklein123 merged 7 commits intoenvoyproxy:masterfrom
douglas-reid:grpc-status-code

Conversation

@douglas-reid
Copy link
Copy Markdown
Contributor

Description:

This PR allows access to the gRPC status codes via the extensions common filter context. This will make it possible to report gRPC status codes in metrics and logs. This is a part of the work from: https://tinyurl.com/yy2cwmv5. A companion PR that hopes to use this code is istio/proxy#2624.

Risk Level: low
Testing: unit
Docs Changes: Updated RBAC filter attributes doc
Release Notes: none

Signed-off-by: Douglas Reid douglas-reid@users.noreply.github.com

Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
@htuch
Copy link
Copy Markdown
Member

htuch commented Jan 16, 2020

@kyessenov would you have some time to take a first pass at this? Thanks.

@douglas-reid
Copy link
Copy Markdown
Contributor Author

@htuch I believe @kyessenov is on vacation, so it will be a little while until he can take a look.

@mandarjog
Copy link
Copy Markdown
Contributor

@PiotrSikora can you take a look?

PiotrSikora
PiotrSikora previously approved these changes Jan 16, 2020
Copy link
Copy Markdown
Contributor

@PiotrSikora PiotrSikora left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

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.

LGTM with a small test question, thanks.

/wait

return CelValue::CreateInt64(status);
}
}
return {};
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.

Do you have a test case that covers no headers/trailers and/or bad header/trailer values? (Optimally you could use Common::getGrpcStatus but not sure if it's worth it or not.

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.

Thanks for the pointer to the Common:getGrpcStatus bit. I did not know that existed. That led me to look at the access log code that uses it, which ultimately led me to expand the fallbacks.

Now, after looking in trailers and headers, this will attempt to look at http response code and finally return Unknown if not found.

Matching the logging behavior seemed important.

I added a bunch of test cases for this updated behavior to match. Please let me know what you think.

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.

Thanks, is there is any reasonable way to unify this logic and the access log logic so they don't fall out of sync? I agree they should be the same.

/wait-any

Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
if (code.has_value()) {
return CelValue::CreateInt64(Grpc::Utility::httpToGrpcStatus(code.value()));
}
return CelValue::CreateInt64(Grpc::Status::WellKnownGrpcStatus::Unknown);
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 don't think that returning grpc-status: 2 (unknown) when it wasn't present in the response is a correct thing to do.

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.

@PiotrSikora I was trying to match:

bool GrpcStatusFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::HeaderMap&,
const Http::HeaderMap& response_headers,
const Http::HeaderMap& response_trailers) {
// The gRPC specification does not guarantee a gRPC status code will be returned from a gRPC
// request. When it is returned, it will be in the response trailers. With that said, Envoy will
// treat a trailers-only response as a headers-only response, so we have to check the following
// in order:
// 1. response_trailers gRPC status, if it exists.
// 2. response_headers gRPC status, if it exists.
// 3. Inferred from info HTTP status, if it exists.
//
// If none of those options exist, it will default to Grpc::Status::WellKnownGrpcStatus::Unknown.
const std::array<absl::optional<Grpc::Status::GrpcStatus>, 3> optional_statuses = {{
{Grpc::Common::getGrpcStatus(response_trailers)},
{Grpc::Common::getGrpcStatus(response_headers)},
{info.responseCode() ? absl::optional<Grpc::Status::GrpcStatus>(
Grpc::Utility::httpToGrpcStatus(info.responseCode().value()))
: absl::nullopt},
}};
Grpc::Status::GrpcStatus status = Grpc::Status::WellKnownGrpcStatus::Unknown;
for (const auto& optional_status : optional_statuses) {
if (optional_status.has_value()) {
status = optional_status.value();
break;
}
}
const bool found = statuses_.find(status) != statuses_.end();
return exclude_ ? !found : found;
}
.

If not UNKNOWN, what status would you expect as a return value?

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.

@douglas-reid fair point wrt being consistent with the access loggers, but I don't think any status should be returned as a value if there was no status sent on the wire...

Can't the return value by {}, absl::nullopt, or something else in that style?

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.

It can definitely return {}. That was the way I had it originally.

I guess we need to decide on exactly what to do.

BTW, it looks like choosing "Unknown" has some prior art:

https://github.com/grpc/grpc-go/blob/master/internal/transport/http_util.go#L281-L288

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 think it should be {}. There is quite a difference between missing field and grpc-status: 2.

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 think it should be {}. Otherwise, we run the risk of confusing the consumer for a non-gRPC request.

} else if (value == Flags) {
return CelValue::CreateInt64(info_.responseFlags());
} else if (value == GrpcStatus) {
for (const auto wrapper : ((HeadersWrapper[]){trailers_, 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.

I'm not happy about the linear performance here. Maybe add a TODO to cache the computed value?

Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
@douglas-reid
Copy link
Copy Markdown
Contributor Author

@mattklein123 @PiotrSikora @kyessenov please take another look. I've updated the PR to extract the fallback logic to the Common lib. Additionally, this PR should preserve the access_logger Unknown behavior, while not adopting that in the RBAC expr context (returning {} instead). Tests have been updated to match.

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.

Nice, thanks!

@mattklein123 mattklein123 merged commit e9624ce into envoyproxy:master Jan 22, 2020
PiotrSikora pushed a commit to istio/envoy that referenced this pull request Jan 24, 2020
…#377)

Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
@douglas-reid douglas-reid deleted the grpc-status-code branch April 19, 2021 22:55
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.

6 participants