Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Add io.opentracing.Span.isFinished() method #342

Open
ravirajj opened this issue Apr 10, 2019 · 2 comments
Open

Add io.opentracing.Span.isFinished() method #342

ravirajj opened this issue Apr 10, 2019 · 2 comments

Comments

@ravirajj
Copy link

ravirajj commented Apr 10, 2019

To implement the GRPC tracing client interceptor we need to be able to discern if the span has finished or not. Currently, a volatile variable external to the span is used to track this state. See opentracing-contrib/java-grpc#36.

The client span needs to be finished in either the ClientCall.cancel() or ClientCall.Listener.onClose() method. These methods are the last to run in the outbound and inbound threads, respectively. Depending on whether the client call succeeds or fails, either or both methods may be executed in any order. See https://github.com/grpc/grpc-java/blob/master/core/src/main/java/io/grpc/ClientCall.java#L47-L50.

By using io.opentracing.Span.isFinished(), each method can check if the span has not already been closed by the other, thus ensuring that span.finish() is only run once.

@yurishkuro
Copy link
Member

Currently, a volatile variable external to the span is used to track this state.

What's the problem with that?

Overall, I don't think is the best approach to keep changing OpenTracing API to compensate for the deficiencies of instrumented framework. What about asking gRPC to provide a callback method that is reliably called at the end of the operation such that you don't have to guess where to finish the span?

@ravirajj
Copy link
Author

ravirajj commented Apr 11, 2019

There is no problem using AtomicBoolean to save span finished state (See opentracing-contrib/java-grpc#36). The Span.isFinished() API would be a convenience, but then again access to the finished state would need to be synchronized for this use case and that is OpenTracing API implementation dependent.

I have also filed a bug with grpc-java to ensure the onClose() is always called as it is expected: grpc/grpc-java#5576, so we only call span.finish() in the onClose() method.

As per GRPC expected behaviour, ClientCall.Listener.onClose() is the last method to be called in the ingress client thread and, if there is a client error, the ClientCall.cancel() is the last method to be called in the egress client thread. Since they run in different threads and cancel() may run after onClose(), we would still need to check that the span is not already finished, before adding logs/tags to the span in the cancel() method.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants