Skip to content

Commit 6216821

Browse files
authored
When continuing a span merge it with any non-span context (#8658)
1 parent e3867f0 commit 6216821

File tree

3 files changed

+100
-17
lines changed

3 files changed

+100
-17
lines changed

dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import datadog.trace.api.scopemanager.ScopeListener;
2121
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
2222
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
23+
import datadog.trace.bootstrap.instrumentation.api.AgentTraceCollector;
2324
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
2425
import datadog.trace.bootstrap.instrumentation.api.ProfilerContext;
2526
import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration;
@@ -104,18 +105,21 @@ public AgentScope.Continuation captureActiveSpan() {
104105
if (null != activeScope && activeScope.isAsyncPropagating()) {
105106
AgentSpan span = activeScope.span();
106107
if (span != null) {
107-
return captureSpan(span, activeScope.source());
108+
return captureSpan(activeScope.context, activeScope.source(), span);
108109
}
109110
}
110111
return AgentTracer.noopContinuation();
111112
}
112113

113114
public AgentScope.Continuation captureSpan(final AgentSpan span) {
114-
return captureSpan(span, INSTRUMENTATION);
115+
ContinuableScope top = scopeStack().top;
116+
Context context = top != null ? top.context.with(span) : span;
117+
return captureSpan(context, INSTRUMENTATION, span);
115118
}
116119

117-
private AgentScope.Continuation captureSpan(final AgentSpan span, byte source) {
118-
return new ScopeContinuation(this, span, source).register();
120+
private AgentScope.Continuation captureSpan(Context context, byte source, AgentSpan span) {
121+
AgentTraceCollector traceCollector = span.context().getTraceCollector();
122+
return new ScopeContinuation(this, context, source, traceCollector).register();
119123
}
120124

121125
private AgentScope activate(

dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeContinuation.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.noopScope;
44

5+
import datadog.context.Context;
56
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
67
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
78
import datadog.trace.bootstrap.instrumentation.api.AgentTraceCollector;
@@ -24,7 +25,7 @@ final class ScopeContinuation implements AgentScope.Continuation {
2425
private static final int HELD = (Integer.MAX_VALUE >> 1) + 1;
2526

2627
final ContinuableScopeManager scopeManager;
27-
final AgentSpan spanUnderScope;
28+
final Context context;
2829
final byte source;
2930
final AgentTraceCollector traceCollector;
3031

@@ -51,13 +52,13 @@ final class ScopeContinuation implements AgentScope.Continuation {
5152

5253
ScopeContinuation(
5354
final ContinuableScopeManager scopeManager,
54-
final AgentSpan spanUnderScope,
55-
final byte source) {
55+
final Context context,
56+
final byte source,
57+
final AgentTraceCollector traceCollector) {
5658
this.scopeManager = scopeManager;
57-
this.spanUnderScope = spanUnderScope;
59+
this.context = context;
5860
this.source = source;
59-
60-
this.traceCollector = spanUnderScope.context().getTraceCollector();
61+
this.traceCollector = traceCollector;
6162
}
6263

6364
ScopeContinuation register() {
@@ -77,7 +78,7 @@ public AgentScope.Continuation hold() {
7778
public AgentScope activate() {
7879
if (COUNT.incrementAndGet(this) > 0) {
7980
// speculative update succeeded, continuation can be activated
80-
return scopeManager.continueSpan(this, spanUnderScope, source);
81+
return scopeManager.continueSpan(this, context, source);
8182
} else {
8283
// continuation cancelled or too many activations; rollback count
8384
COUNT.decrementAndGet(this);
@@ -118,15 +119,11 @@ void cancelFromContinuedScopeClose() {
118119

119120
@Override
120121
public AgentSpan span() {
121-
return spanUnderScope;
122+
return AgentSpan.fromContext(context);
122123
}
123124

124125
@Override
125126
public String toString() {
126-
return getClass().getSimpleName()
127-
+ "@"
128-
+ Integer.toHexString(hashCode())
129-
+ "->"
130-
+ spanUnderScope;
127+
return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "->" + context;
131128
}
132129
}

dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,88 @@ class ScopeManagerTest extends DDCoreSpecification {
10751075
scopeManager.activeSpan() == null
10761076
}
10771077

1078+
def "capturing and continuing a span merges it with existing context"() {
1079+
when:
1080+
def span = tracer.buildSpan("test", "test").start()
1081+
def testKey = ContextKey.named("test")
1082+
def context = Context.root().with(testKey, "test-value")
1083+
def contextScope = scopeManager.attach(context)
1084+
1085+
then:
1086+
scopeManager.active() == contextScope
1087+
scopeManager.current() == context
1088+
scopeManager.activeSpan() == null
1089+
scopeManager.current().get(testKey) == "test-value"
1090+
1091+
when:
1092+
def scope = tracer.captureSpan(span).activate()
1093+
1094+
then:
1095+
scopeManager.active() == scope
1096+
scopeManager.current() != context
1097+
scopeManager.activeSpan() == span
1098+
scopeManager.current().get(testKey) == "test-value"
1099+
1100+
when:
1101+
scope.close()
1102+
1103+
then:
1104+
scopeManager.active() == contextScope
1105+
scopeManager.current() == context
1106+
scopeManager.activeSpan() == null
1107+
scopeManager.current().get(testKey) == "test-value"
1108+
1109+
when:
1110+
contextScope.close()
1111+
1112+
then:
1113+
scopeManager.active() == null
1114+
scopeManager.current() == Context.root()
1115+
scopeManager.activeSpan() == null
1116+
}
1117+
1118+
def "capturing and continuing the active span merges it with existing context"() {
1119+
when:
1120+
def span = tracer.buildSpan("test", "test").start()
1121+
def testKey = ContextKey.named("test")
1122+
def context = Context.root().with(testKey, "test-value")
1123+
def contextScope = scopeManager.attach(context)
1124+
1125+
then:
1126+
scopeManager.active() == contextScope
1127+
scopeManager.current() == context
1128+
scopeManager.activeSpan() == null
1129+
scopeManager.current().get(testKey) == "test-value"
1130+
1131+
when:
1132+
def scope = tracer.activateSpan(span).withCloseable {
1133+
tracer.captureActiveSpan().activate()
1134+
}
1135+
1136+
then:
1137+
scopeManager.active() == scope
1138+
scopeManager.current() != context
1139+
scopeManager.activeSpan() == span
1140+
scopeManager.current().get(testKey) == "test-value"
1141+
1142+
when:
1143+
scope.close()
1144+
1145+
then:
1146+
scopeManager.active() == contextScope
1147+
scopeManager.current() == context
1148+
scopeManager.activeSpan() == null
1149+
scopeManager.current().get(testKey) == "test-value"
1150+
1151+
when:
1152+
contextScope.close()
1153+
1154+
then:
1155+
scopeManager.active() == null
1156+
scopeManager.current() == Context.root()
1157+
scopeManager.activeSpan() == null
1158+
}
1159+
10781160
boolean spanFinished(AgentSpan span) {
10791161
return ((DDSpan) span)?.isFinished()
10801162
}

0 commit comments

Comments
 (0)