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

Propagate TraceNotFound error from grpc storage plugins #2455

Merged
merged 5 commits into from
Sep 7, 2020

Conversation

joe-elliott
Copy link
Member

@joe-elliott joe-elliott commented Sep 3, 2020

A previous attempt to fix this was made here: #1814
Original issue: #1741

However, this is currently not working b/c on this line ok is set to true which skips the code that checks to see if the string equals "trace not found".

if e, ok := status.FromError(err); !ok {

Tracking it down:
RecvMsg
https://github.com/grpc/grpc-go/blob/8630cac324bf02ea0edfba758c2b2f3344af7bf7/stream.go#L749
recvMsg
https://github.com/grpc/grpc-go/blob/master/stream.go#L886
toRPCErr
https://github.com/grpc/grpc-go/blob/8630cac324bf02ea0edfba758c2b2f3344af7bf7/rpc_util.go#L775

toRPCErr calls status.FromError which wraps the error in a GRPCStatus. This causes the FromError in grpc_client.go to recognize the error as GRPCStatus and return true.

Fix:

  • Remove the status.FromError check and test the error directly.
  • Compare the error message to a GRPCStatus wrapped spanstore.ErrTraceNotFound

I have confirmed this works manually by building jaeger-query with a custom GRPC plugin.

@joe-elliott joe-elliott requested a review from a team as a code owner September 3, 2020 20:42
return nil, spanstore.ErrTraceNotFound
}
traceNotFoundStatus, _ := status.FromError(spanstore.ErrTraceNotFound)
if err.Error() == traceNotFoundStatus.Err().Error() {
Copy link
Member

Choose a reason for hiding this comment

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

traceNotFoundStatus.Err().Error() prints as:

rpc error: code = Unknown desc = trace not found

I wonder if there's a better way than comparing strings. Especially suspicious is code = Unknown.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree, pushed something that i like better. It's still string comparison, but it is now comparing directly "trace not found".

The original error was created in a different process so I don't think there's any clean way to compare error equality. I believe string comparison is as good as it gets here.

withGRPCClient(func(r *grpcClientTest) {
traceClient := new(grpcMocks.SpanReaderPlugin_GetTraceClient)
traceClient.On("Recv").Return(nil, spanstore.ErrTraceNotFound)
traceClient.On("Recv").Return(nil, s.Err())
Copy link
Member

Choose a reason for hiding this comment

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

I think we should write a test that goes through client and server, not just mocking the client.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree. I can't say I have time right now to knock it out. Perhaps if i find some time in the next week or two I'll dig into it.

@codecov
Copy link

codecov bot commented Sep 3, 2020

Codecov Report

Merging #2455 into master will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2455   +/-   ##
=======================================
  Coverage   95.56%   95.56%           
=======================================
  Files         208      208           
  Lines       10690    10690           
=======================================
  Hits        10216    10216           
  Misses        401      401           
  Partials       73       73           
Impacted Files Coverage Δ
plugin/storage/grpc/shared/grpc_client.go 85.96% <100.00%> (ø)
cmd/query/app/server.go 91.11% <0.00%> (-2.23%) ⬇️
...lugin/sampling/strategystore/adaptive/processor.go 99.20% <0.00%> (-0.80%) ⬇️
plugin/storage/integration/integration.go 80.86% <0.00%> (+0.47%) ⬆️
cmd/query/app/static_handler.go 84.16% <0.00%> (+2.50%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9dad32f...82bd25c. Read the comment docs.

Signed-off-by: Joe Elliott <[email protected]>
@@ -77,10 +77,9 @@ func (c *grpcClient) GetTrace(ctx context.Context, traceID model.TraceID) (*mode
trace := model.Trace{}
for received, err := stream.Recv(); err != io.EOF; received, err = stream.Recv() {
if err != nil {
if e, ok := status.FromError(err); !ok {
Copy link
Member

Choose a reason for hiding this comment

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

wasn't this if statement mostly correct, except the condition should be ok instead of !ok?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, that's true. I prefer what I have pushed b/c it doesn't matter if err is an error or a status.Status if the message is "trace not found" then it will return the correct error.

We can do the minimal change if it's preferred though.

Copy link
Member

Choose a reason for hiding this comment

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

the original version (aside from !ok) seems better, because your version is ignoring the error, so s may be undefined.

Copy link
Member Author

Choose a reason for hiding this comment

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

good point. I am relying on status.FromError to return a non-nil status. I think this would the best construction

if s, _ := status.FromError(err); s != nil {
  // check if s is a trace not found error.
}

ok just indicates if FromError had to create a new status.Status or if it was able to retrieve one using the GRPCStatus() method. For our purposes we don't care, we're just going to compare s.Message() to "trace not found" either way.

@yurishkuro yurishkuro merged commit 5508165 into jaegertracing:master Sep 7, 2020
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.

2 participants