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

api, core: add ClientCallTracer APIs for tracing components with capability to expose tracer properties to external frameworks #6081

Closed

Conversation

voidzcy
Copy link
Contributor

@voidzcy voidzcy commented Aug 19, 2019

New API class ClientCallTracer/ClientCallTracer.Factory.

  • ClientCallTracer traces ClientCall events and allow callers to populate tracer properties through ClientCallTracer#getTracerAttributes(...). Those attributes are further populated up to ClientCall interface for external access.

  • Users attach ClientCallTracer.Factory instances to Channel via ManagedChannelBuilder#clientCallTracerFactories(...). , which creates and attach a new ClientCallTracer instance to each new ClientCall it creates.

  • ClientCallImpl invokes callback methods defined in ClientCallTracer at each call events.

Implementation of #6080.

CensusTracingModule is the first usage of this API. It transits from ClientInterceptor to ClientCallTracer to give access to Census SpanId and TraceId to external users/frameworks.

@voidzcy voidzcy force-pushed the feature/add_new_client_call_tracer_api branch from 605a2ba to e7317d5 Compare August 19, 2019 04:58
@@ -279,4 +279,14 @@ public void setMessageCompression(boolean enabled) {
public Attributes getAttributes() {
return Attributes.EMPTY;
}

/**
* Returns tracer specific properties (if any) attached by tracing components.
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a link to ClientCallTracer.
Also say that this is available as soon as the ClientCall is created.

*
* @param builder receiver of tracer information.
*/
public void getTracerAttributes(Attributes.Builder builder) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Define an annotation like in https://github.com/grpc/grpc-java/blob/master/api/src/main/java/io/grpc/EquivalentAddressGroup.java#L142 . Annotate this argument, ClientCall.getTracerAttributes() and the attribute keys with this annotation will allow the user to associate them more easily.


@VisibleForTesting
static final Attributes.Key<TraceId> TRACE_ID_ATTRIBUTES_KEY = Attributes.Key
.create("census-trace-id");
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to expose those keys to our internal framework. If we had moved Census integration to a separate artifact, we would simply expose those keys from a public class in that artifact. For now, we have to keep it internal. Maybe we can add a public CensusInternalAccessor class that exposes these keys.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

io.grpc package does not have Census dependency, where should this accessor class go?

*
* @param status the result of the remote call.
*/
public void callEnded(Status status) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

By looking at these tracking methods, I realize that they essentially overlap with the functionality of ClientInterceptor. I question myself whether it's really necessary to have such a large API.

Alternatively, ClientCallTracer could have only getTracerAttributes(). We don't need the new setter on ManagedChannelBuilder, instead we add withClientCallTracer() on CallOptions (possibly deprecate withStreamTracerFactory(). Keep using ClientInterceptor in CensusTracingModule, and let the interceptor to set ClientCallTracer for new calls, and grab the Span from ClientCall.getTracerAttributes() right after creating the call.

That looks like a much smaller change. Also ClientInterceptor probably has less impact on performance (because you don't iterate on the list of tracers on each callback). Sorry for @voidzcy that I came up this idea only after you made the code changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's ok, no worries.
But, does that solve ordering constraint of ClientInterceptors (assuming in the future we move Census modules out of core and no longer enforce Census interceptors run last)?

Framework interceptor needs to check two places to get the Span. One is from ClientCall#getTracerAttributes() for the case when Census interceptor runs first, and the other is from callOptions passed to ClientInterceptor#interceptCall() for the case when framework interceptor runs first.

Copy link
Contributor

Choose a reason for hiding this comment

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

Framework interceptors would get the Span only from ClientCall#getTracerAttributes(). As soon as the Framework interceptors get a ClientCall from next.newCall(...), it can be sure the ClientCallTracer from the Census interceptor has been passed to the ClientCallImpl, and getTracerAttributes() can be immediately called, no matter which interceptor is run first.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, you are right. next.newCall(...) runs all the way down to ClientCallImpl. The Span will be there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will have a separate PR to make the changes.

@voidzcy
Copy link
Contributor Author

voidzcy commented Aug 22, 2019

Closing in favor of #6090.

@voidzcy voidzcy closed this Aug 22, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Nov 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants