-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Problem Statement
Our current state of obtaining the correct DSC is messy and it's easy to get the logic, when to use the DSC from a span vs. from client data vs. the one on the propagation context wrong.
With #10094 we started moving away from creating a DSC from the transaction but this can only be temporary because the frozen DSC is still on the txn.
But what about Scope.getPropagationContext?
After discussing this extensively, our previous solution to consolidate DSC whenever scope.getPropagationContext is called (as described in #10095) has one fundamental flaw: In Otel/Node, the "active span" is not always the span that's on the current scope from which scope.getPropagationContext would be called. Now, we could, theoretically, just call getActiveSpan() within scope.getPropagationContext but arguably, this destroys the semantics and doesn't make much sense in Node.
Solution Brainstorm
The solution is to decouple DynamicSamplingContext and PropagationContext. To obtain all the necessary tracing data, we'll need to call:
getCurrentScope().getPropagationContext()for traceparent datagetDynamicSamplingContext()for DSC
While it's not one unified call, it's still way easier than conditionally selecting DSC from wherever and it'll allow us to preserve semantics better.
This also has the implication, that we'll remove the dsc field from PropagationContext as it'll no longer be necessary.
Pseudo Code Implementation
credits @mydea
// called from start(inactive)?Span(Manual)?
function afterStartSpan(ctx: TransactionContext): void {
if (ctx.metadata?.dynamicSamplingContext) {
const scope = getCurrentScope();
if (!scope.getFrozenDsc()) {
scope.setFrozenDsc(ctx.metadata.dynamicSamplingContext);
}
}
}
function getDynamicSamplingContext(): DynamicSamplingContext {
const scope = getCurrentScope();
if (scope.getFrozenDsc()) {
return scope.getFrozenDsc();
}
if (getActiveSpan()) {
// set the frozen one if we want to re-introduce freezing:
// getCurrentScope().setFrozenDsc(...);
return getDscFromSpan();
}
return getDscFromClient(scope.getPropagationContext().traceId, getClient(), scope);
}