-
Notifications
You must be signed in to change notification settings - Fork 926
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
Unframed grpc service support richer error model #4231
Conversation
#4204 has been merged. 😉 |
Codecov Report
@@ Coverage Diff @@
## master #4231 +/- ##
=========================================
Coverage 73.51% 73.52%
- Complexity 17663 17677 +14
=========================================
Files 1504 1505 +1
Lines 66100 66172 +72
Branches 8338 8346 +8
=========================================
+ Hits 48594 48652 +58
- Misses 13292 13297 +5
- Partials 4214 4223 +9
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandlerUtils.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandlerUtils.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandlerUtils.java
Outdated
Show resolved
Hide resolved
grpc/src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandlerUtilsTest.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandlerUtils.java
Outdated
Show resolved
Hide resolved
Gentle ping. @natsumehu |
Will continue working on this feature these two days 🎉 |
@ikhoon I think it's ready for another round. |
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.
Nice work, @natsumehu. I left super minor comments only. 👍
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpcCode.value()) | ||
.build(); | ||
final HttpData content; | ||
try (TemporaryThreadLocals ttl = TemporaryThreadLocals.acquire()) { |
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.
Nice that you already know this trick! 👍
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
grpc/src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandlerTest.java
Show resolved
Hide resolved
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.
Nice work, @natsumehu! 🚀❤️
grpc/src/test/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandlerTest.java
Outdated
Show resolved
Hide resolved
grpc/src/test/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandlerTest.java
Outdated
Show resolved
Hide resolved
…ramedGrpcErrorHandlerTest.java
…ramedGrpcErrorHandlerTest.java
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 overall! I think this will be my last comments 🙏
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
try (OutputStream outputStream = new ByteBufOutputStream(buffer); | ||
JsonGenerator jsonGenerator = mapper.createGenerator(outputStream)) { | ||
jsonGenerator.writeStartObject(); | ||
jsonGenerator.writeFieldName("error"); |
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.
Sorry, one last question.
Should we just return a Status
object instead of wrapping in an error
object?
i.e.
{
"code": ..
"message":..
"stack-trace":...
"details":...
}
instead of
{
"error": {
"code": ..
"message":..
"stack-trace":...
"details":...
}
}
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.
Hi, wrap the status object in an error object is what google's error model does. ❤️
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 😅 I missed this the last time I reviewed, but other open source implementations don't seem to be wrapping in an error
object.
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.
Ah, I see. That's a decision we should make. I guess the purpose of wrapping an error object is making the error handling more extensive and I probably prefer this option.
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.
Sounds reasonable 👍
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.
And also for client developers, when the error is wrapped in a single error object, it seems to be easier and more intuitive to detect the error message instead of having a flat normal response.
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.
Google's API Platform uses error
object for backward compatibiltiy.
https://cloud.google.com/apis/design/errors#http_mapping
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
import io.netty.buffer.ByteBuf; | ||
import io.netty.buffer.ByteBufOutputStream; | ||
|
||
final class DefaultUnframedGrpcErrorHandler { |
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.
How about renaming to UnframedGrpcErrorHandlerUtil
?
because this isn't the default class of UnframedGrpcErrorHandler
but just a util class that has a bunch of static methods?
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.
How about UnframedGrpcErrorHandlers
?
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultUnframedGrpcErrorHandler.java
Outdated
Show resolved
Hide resolved
…ramedGrpcErrorHandler.java Co-authored-by: jrhee17 <[email protected]>
…pcErrorHandler.java Co-authored-by: minux <[email protected]>
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 great! Thanks @natsumehu ! 🙇 👍 🚀
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.
Thanks a lot, @natsumehu!
gRPC users would love this feature.
Thanks, @ikhoon for taking care of the comments. 😉
Motivation: We want to add another Unframed Grpcerrorhandler to support richer grpc error information [google errors](https://grpc.io/docs/guides/error/) Modifications: - add `ofRichJson()` method to `UnframedGrpcErrorHandler`. Result: - You can have a richer error model as described by [google error model](https://cloud.google.com/apis/design/errors#error_model) eg. - if you throw exceptions like ```java final ErrorInfo errorInfo = ErrorInfo.newBuilder() .setDomain("test") .setReason("Unknown Exception").build(); final com.google.rpc.Status status = com.google.rpc.Status.newBuilder() .setCode(Code.UNKNOWN.getNumber()) .setMessage("Unknown Exceptions Test") .addDetails(Any.pack(errorInfo)) .build(); responseObserver.onError(StatusProto.toStatusRuntimeException(status)); ``` You can use this error handler by doing ``` java sb.service(GrpcService.builder() .addService(grpcService) .unframedGrpcErrorHandler(UnframedGrpcErrorHandler.ofRichJson()) .build()); ``` You can get a response ``` { "error": { "code": 500, "status": "UNKNOWN", "message": "Unknown Exceptions Test", "details": [{ "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "Unknown Exception", "domain": "test" }] } } ```
Motivation:
We want to add another Unframed Grpcerrorhandler to support richer grpc error information
google errors
Modifications:
ofRichJson()
method toUnframedGrpcErrorHandler
.Result:
eg.
You can use this error handler by doing
You can get a response