Open ravirajj opened 5 years ago
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?
There is no problem using AtomicBoolean
to save span finished state (See https://github.com/opentracing-contrib/java-grpc/pull/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: https://github.com/grpc/grpc-java/issues/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.
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 https://github.com/opentracing-contrib/java-grpc/pull/36.
The client span needs to be finished in either the
ClientCall.cancel()
orClientCall.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 thatspan.finish()
is only run once.