-
Notifications
You must be signed in to change notification settings - Fork 179
Can Scopes be extended to carry other context besides Span? #114
Description
Background
Correct in-process context propagation is one of the hardest problems for distributed tracing. The new Scope/ScopeManager APIs aim to solve that, but they only propagate the Span object. Users often want to propagate other request-scoped data which is only relevant within the process. For example, a microservice might want to propagate a deadline from inbound to outbound calls.
Problem
The requirements for correct propagation of request scoped data in-process are exactly the same as for the Span, but nothing but the Span is supported by the Scope/ScopeManager APIs.
Proposal
What if Scope was allowed to carry additional context that would be automatically passed through to child scopes? Something like:
try (Scope scope = tracer.buildSpan("ha").startActive(true).withValue("deadline", someDeadline)) {
// somewhere deep in the call stack
Long deadline = (Long) tracer.scopeManager().active().getValue("deadline");
}When using finishOnClose=false mode, the usage pattern is to take the current span, pass it to another thread, and activate() it. This is not sufficient to propagate the values. One possible way to address this is to support a notion of ScopeContext, which is somewhat similar to SpanContext in that it can be passed around explicitly. Instead of passing the span to another thread we can pass the scope context:
try (Scope scope = tracer.buildSpan("ha").startActive(false).withValue("deadline", someDeadline)) {
ScopeContext ctx = scope.context();
executorPool.execute(new Runnable() {
public void run() {
tracer.scopeManager.activate(ctx);
Long deadline = (Long) tracer.scopeManager().active().getValue("deadline");
}
});
}Questions to address
- Can we ensure that values in the scope are inherited into child scopes?
- Perhaps the Span itself can be used as a carrier for the in-process context values.