Skip to content
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

Make GrpcErrorsAsFailures more flexible #189

Merged
merged 5 commits into from
Nov 26, 2021

Conversation

davidpdrsn
Copy link
Member

@davidpdrsn davidpdrsn commented Nov 25, 2021

Previously GrpcErrorsAsFailures would only consider Ok as a success. However for servers it might be useful to also consider Not Found or Invalid Arguments as success (or at least not consider them failures) since they're likely caused by the client.

This PR adds GrcpErrorsAsFailures::success_codes which takes a bitmask of the codes that are considered successes.

Example usage:

// Response classifier that doesn't consider `Ok`, `Invalid Argument`, or `Not Found` as
// failures
let classifier = GrpcErrorsAsFailures::new()
    .success_codes(GrpcCodeBitmask::INVALID_ARGUMENT | GrpcCodeBitmask::NOT_FOUND);

let service = ServiceBuilder::new()
    .layer(TraceLayer::new(SharedClassifier::new(classifier)))
    .service(service);

I went with the name GrpcCodeBitmask because I think it communicates quite somewhat clearly what it does. At least to people who know what a bitmask is. At first I considered just calling it GrpcCode but that might be confusing since its used to match multiple codes and doesn't just represent a single code.

Maybe the name GrpcErrorsAsFailures isn't very accurate anymore 🤔 Maybe just GrpcClassifier would be better. Although its more broad.

It does add a new public dependency on bitflags but I'm okay with that. The crate is maintained by people from the Rust team, doesn't have dependencies, and has been 1.0 for over 4 years. axum also has a public dependency on it.

Fixes #126

@davidpdrsn davidpdrsn added the C-enhancement Category: A PR with an enhancement or a proposed on in an issue. label Nov 25, 2021
@davidpdrsn davidpdrsn added this to the 0.2.0 milestone Nov 25, 2021
@davidpdrsn
Copy link
Member Author

@tamuhey you filed the original issue about this. What do you think about this API?

@davidpdrsn davidpdrsn requested a review from hawkw November 25, 2021 16:01
@davidpdrsn
Copy link
Member Author

@hawkw you were quite involved in the original design of tower-http's response classification stuff. Wanna give this a look?

@seanmonstar
Copy link
Collaborator

One option so as to not expose the bitmask is just to keep that internal. Allow people to call .success_code() multiple times with different codes, and build up the flags internally.

I'm a fan of this because I also feel like bit flags aren't the most intuitive thing to use for many programmers. At least I've been confused a few times whether I want to use | or &.

@davidpdrsn
Copy link
Member Author

Yeah thats true 🤔 Although that would require an enum with each variants for each, although that wouldn't be too bad.

I'm personally fine with bitflags but I've also used it a bunch in axum so maybe I'm just used to it.

@seanmonstar
Copy link
Collaborator

No, you could use bit flags internally, just let the user pass in a Code and you can do the bit fiddling internally.

Like for a user:

layer
    .with_success(Code::OK)
    .with_success(Code::CANCELED)

Copy link
Collaborator

@Nehliin Nehliin left a comment

Choose a reason for hiding this comment

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

Nice! I personally think the exposed bitflags actually clearer but that's just me. Actually now that I think about it & would just be a fotgun if the bitflags are exposed since its impossible for a status to match two different codes.

@davidpdrsn
Copy link
Member Author

No, you could use bit flags internally, just let the user pass in a Code and you can do the bit fiddling internally.

Like for a user:

layer
    .with_success(Code::OK)
    .with_success(Code::CANCELED)

Yep that also what I meant. I'll play around with the API a bit today.

@davidpdrsn
Copy link
Member Author

I've changed it and the bitmask is no longer public. API is now:

use tower_http::classify::{GrpcErrorsAsFailures, GrpcCode};

let classifier = GrpcErrorsAsFailures::new()
    .with_success(GrpcCode::InvalidArgument)
    .with_success(GrpcCode::NotFound);

@tamuhey
Copy link

tamuhey commented Nov 26, 2021

@davidpdrsn Looks perfect for me, thanks!

@davidpdrsn davidpdrsn enabled auto-merge (squash) November 26, 2021 10:43
@davidpdrsn davidpdrsn merged commit 56ffdb2 into master Nov 26, 2021
@davidpdrsn davidpdrsn deleted the grpc-classifier-customization branch November 26, 2021 10:53
@davidpdrsn davidpdrsn mentioned this pull request Dec 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: A PR with an enhancement or a proposed on in an issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

more configurable grpc tracer
4 participants