8000 Migrate OtelContext wrapper to new Context API · DataDog/dd-trace-java@591efc8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 591efc8

Browse files
committed
Migrate OtelContext wrapper to new Context API
1 parent 2512090 commit 591efc8

File tree

8 files changed

+73
-142
lines changed

8 files changed

+73
-142
lines changed
Lines changed: 54 additions & 118 deletions
F438
Original file line numberDiff line numberDiff line change
@@ -1,170 +1,106 @@
11
package datadog.opentelemetry.shim.context;
22

33
import datadog.opentelemetry.shim.trace.OtelSpan;
4-
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
54
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
6-
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
75
import datadog.trace.bootstrap.instrumentation.api.AttachableWrapper;
8-
import io.opentelemetry.api.trace.Span;
96
import io.opentelemetry.context.Context;
107
import io.opentelemetry.context.ContextKey;
118
import io.opentelemetry.context.Scope;
12-
import java.util.Arrays;
9+
import java.util.Map;
10+
import java.util.concurrent.ConcurrentHashMap;
1311
import javax.annotation.Nullable;
1412
import javax.annotation.ParametersAreNonnullByDefault;
1513

14+
@SuppressWarnings({"rawtypes", "unchecked"})
1615
@ParametersAreNonnullByDefault
1716
public class OtelContext implements Context {
18-
private static final Object[] NO_ENTRIES = {};
1917

2018
/** Overridden root context. */
21-
public static final Context ROOT = new OtelContext(OtelSpan.invalid(), OtelSpan.invalid());
19+
public static final Context ROOT = new OtelContext(datadog.context.Context.root());
2220

2321
private static final String OTEL_CONTEXT_SPAN_KEY = "opentelemetry-trace-span-key";
2422
private static final String OTEL_CONTEXT_ROOT_SPAN_KEY = "opentelemetry-traces-local-root-span";
2523

26-
/** Keep track of propagated context that has not been captured on the scope stack. */
27-
private static final ThreadLocal<OtelContext> lastPropagated = new ThreadLocal<>();
24+
private static final Map<ContextKey<?>, datadog.context.ContextKey<?>> CONTEXT_KEYS =
25+
new ConcurrentHashMap<>();
2826

29-
private final Span currentSpan;
30-
private final Span rootSpan;
27+
private final datadog.context.Context delegate;
3128

32-
private final Object[] entries;
29+
public OtelContext(datadog.context.Context delegate) {
30+
this.delegate = delegate;
31+
}
3332

34-
public OtelContext(Span currentSpan, Span rootSpan) {
35-
this(currentSpan, rootSpan, NO_ENTRIES);
33+
public static Context current() {
34+
return new OtelContext(datadog.context.Context.current());
3635
}
3736

38-
public OtelContext(Span currentSpan, Span rootSpan, Object[] entries) {
39-
this.currentSpan = currentSpan;
40-
this.rootSpan = rootSpan;
41-
this.entries = entries;
37+
@Override
38+
public Scope makeCurrent() {
39+
return new OtelScope(Context.super.makeCurrent(), delegate.attach());
4240
}
4341

4442
@Nullable
4543
@Override
46-
@SuppressWarnings("unchecked")
4744
public <V> V get(ContextKey<V> key) {
4845
if (OTEL_CONTEXT_SPAN_KEY.equals(key.toString())) {
49-
return (V) this.currentSpan;
50-
} else if (OTEL_CONTEXT_ROOT_SPAN_KEY.equals(key.toString())) {
51-
return (V) this.rootSpan;
46+
AgentSpan span = AgentSpan.fromContext(delegate);
47+
if (span != null) {
48+
return (V) toOtelSpan(span);
49+
}
5250
}
53-
for (int i = 0; i < this.entries.length; i += 2) {
54-
if (this.entries[i] == key) {
55-
return (V) this.entries[i + 1];
51+
if (OTEL_CONTEXT_ROOT_SPAN_KEY.equals(key.toString())) {
52+
AgentSpan span = AgentSpan.fromContext(delegate);
53+
if (span != null) {
54+
return (V) toOtelSpan(span.getLocalRootSpan());
5655
}
5756
}
58-
return null;
57+
return (V) delegate.get(datadogKey(key));
5958
}
6059

6160
@Override
6261
public <V> Context with(ContextKey<V> key, V value) {
6362
if (OTEL_CONTEXT_SPAN_KEY.equals(key.toString())) {
64-
return new OtelContext((Span) value, this.rootSpan, this.entries);
65-
} else if (OTEL_CONTEXT_ROOT_SPAN_KEY.equals(key.toString())) {
66-
return new OtelContext(this.currentSpan, (Span) value, this.entries);
67-
}
68-
Object[] newEntries = null;
69-
int oldEntriesLength = this.entries.length;
70-
for (int i = 0; i < oldEntriesLength; i += 2) {
71-
if (this.entries[i] == key) {
72-
if (this.entries[i + 1] == value) {
73-
return this;
74-
}
75-
newEntries = this.entries.clone();
76-
newEntries[i + 1] = value;
77-
break;
63+
if (value instanceof OtelSpan) {
64+
AgentSpan span = ((OtelSpan) value).asAgentSpan();
65+
return new OtelContext(delegate.with(span));
7866
}
7967
}
80-
if (null == newEntries) {
81-
newEntries = Arrays.copyOf(this.entries, oldEntriesLength + 2);
82-
newEntries[oldEntriesLength] = key;
83-
newEntries[oldEntriesLength + 1] = value;
84-
}
85-
return new OtelContext(this.currentSpan, this.rootSpan, newEntries);
68+
return new OtelContext(delegate.with(datadogKey(key), value));
8669
}
8770

8871
@Override
89-
public Scope makeCurrent() {
90-
final Scope scope = Context.super.makeCurrent();
91-
if (this.currentSpan instanceof OtelSpan) {
92-
// only keep propagated context until next span activation
93-
lastPropagated.remove();
94-
AgentScope agentScope = ((OtelSpan) this.currentSpan).activate();
95-
return new OtelScope(scope, agentScope, this.entries);
96-
} else {
97-
// propagated context not on the scope stack, capture it here
98-
lastPropagated.set(this);
99-
return new Scope() {
100-
@Override
101-
public void close() {
102-
lastPropagated.remove();
103-
scope.close();
104-
}
105-
};
106-
}
107-
}
108-
109-
public static Context current() {
110-
// Check for propagated context not on the scope stack
111-
Context context = lastPropagated.get();
112-
if (null != context) {
113-
return context;
114-
}
115-
// Check empty context
116-
AgentScope agentCurrentScope = AgentTracer.activeScope();
117-
if (null == agentCurrentScope) {
118-
return OtelContext.ROOT;
119-
}
120-
// Get OTel current span
121-
Span otelCurrentSpan = null;
122-
AgentSpan agentCurrentSpan = agentCurrentScope.span();
123-
if (agentCurrentSpan instanceof AttachableWrapper) {
124-
Object wrapper = ((AttachableWrapper) agentCurrentSpan).getWrapper();
125-
if (wrapper instanceof OtelSpan) {
126-
otelCurrentSpan = (OtelSpan) wrapper;
127-
}
128-
}
129-
if (otelCurrentSpan == null) {
130-
otelCurrentSpan = new OtelSpan(agentCurrentSpan);
72+
public boolean equals(Object o) {
73+
if (o == null || getClass() != o.getClass()) {
74+
return false;
13175
}
132-
// Get OTel root span
133-
Span otelRootSpan = null;
134-
AgentSpan agentRootSpan = agentCurrentSpan.getLocalRootSpan();
135-
if (agentRootSpan instanceof AttachableWrapper) {
136-
Object wrapper = ((AttachableWrapper) agentRootSpan).getWrapper();
137-
if (wrapper instanceof OtelSpan) {
138-
otelRootSpan = (OtelSpan) wrapper;
139-
}
140-
}
141-
if (otelRootSpan == null) {
142-
otelRootSpan = new OtelSpan(agentRootSpan);
143-
}
144-
// Get OTel custom context entries
145-
Object[] contextEntries = NO_ENTRIES;
146-
if (agentCurrentScope instanceof AttachableWrapper) {
147-
Object wrapper = ((AttachableWrapper) agentCurrentScope).getWrapper();
148-
if (wrapper instanceof OtelScope) {
149-
contextEntries = ((OtelScope) wrapper).contextEntries();
150-
}
151-
}
152-
return new OtelContext(otelCurrentSpan, otelRootSpan, contextEntries);
76+
return delegate.equals(((OtelContext) o).delegate);
15377
}
15478

155-
/** Last propagated context not on the scope stack; {@code null} if there's no such context. */
156-
@Nullable
157-
public static Context lastPropagated() {
158-
return lastPropagated.get();
79+
@Override
80+
public int hashCode() {
81+
return delegate.hashCode();
15982
}
16083

16184
@Override
16285
public String toString() {
163-
return "OtelContext{"
164-
+ "currentSpan="
165-
+ this.currentSpan.getSpanContext()
166-
+ ", rootSpan="
167-
+ this.rootSpan.getSpanContext()
168-
+ '}';
86+
return "OtelContext{" + "delegate=" + delegate + '}';
87+
}
88+
89+
static datadog.context.ContextKey datadogKey(ContextKey key) {
90+
return CONTEXT_KEYS.computeIfAbsent(key, OtelContext::mapKeyByName);
91+
}
92+
93+
private static datadog.context.ContextKey mapKeyByName(ContextKey key) {
94+
return datadog.context.ContextKey.named(key.toString());
95+
}
96+
97+
private static OtelSpan toOtelSpan(AgentSpan span) {
98+
if (span instanceof AttachableWrapper) {
99+
Object wrapper = ((AttachableWrapper) span).getWrapper();
100+
if (wrapper instanceof OtelSpan) {
101+
return (OtelSpan) wrapper;
102+
}
103+
}
104+
return new OtelSpan(span);
169105
}
170106
}
Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,20 @@
11
package datadog.opentelemetry.shim.context;
22

3-
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
4-
import datadog.trace.bootstrap.instrumentation.api.AttachableWrapper;
3+
import datadog.context.ContextScope;
54
import io.opentelemetry.context.Scope;
65

76
public class OtelScope implements Scope {
87
private final Scope scope;
9-
private final AgentScope delegate;
10-
private final Object[] contextEntries;
8+
private final ContextScope delegate;
119

12-
public OtelScope(Scope scope, AgentScope delegate, Object[] contextEntries) {
10+
public OtelScope(Scope scope, ContextScope delegate) {
1311
this.scope = scope;
1412
this.delegate = delegate;
15-
this.contextEntries = contextEntries;
16-
if (delegate instanceof AttachableWrapper) {
17-
((AttachableWrapper) delegate).attachWrapper(this);
18-
}
19-
}
20-
21-
/** Conte 10000 xt entries from {@link OtelContext}, captured when the context was made current. */
22-
Object[] contextEntries() {
23-
return contextEntries;
2413
}
2514

2615
@Override
2716
public void close() {
28-
this.delegate.close();
29-
this.scope.close();
17+
delegate.close();
18+
scope.close();
3019
}
3120
}

dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/context/propagation/AgentTextMapPropagator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import datadog.opentelemetry.shim.context.OtelContext;
99
import datadog.opentelemetry.shim.trace.OtelExtractedContext;
10-
import datadog.opentelemetry.shim.trace.OtelSpan;
1110
import datadog.trace.api.TracePropagationStyle;
1211
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
1312
import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext;
@@ -59,7 +58,7 @@ public <C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C
5958
} else {
6059
TraceState traceState = extractTraceState(extracted, carrier, getter);
6160
SpanContext spanContext = fromRemote(extracted, traceState);
62-
return new OtelContext(Span.wrap(spanContext), OtelSpan.invalid());
61+
return Span.wrap(spanContext).storeInContext(OtelContext.ROOT);
6362
}
6463
}
6564

dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/trace/OtelSpanBuilder.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import static java.lang.Boolean.parseBoolean;
1212
import static java.util.Locale.ROOT;
1313

14-
import datadog.opentelemetry.shim.context.OtelContext;
1514
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
1615
import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext;
1716
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
@@ -202,8 +201,7 @@ public Span startSpan() {
202201
setSpanKind(INTERNAL);
203202
}
204203
if (!this.ignoreActiveSpan) {
205-
// support automatic parenting from propagated context not on the scope stack
206-
Context context = OtelContext.lastPropagated();
204+
Context context = Context.current();
207205
if (null != context) {
208206
setParent(context);
209207
}

dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/main/java/datadog/trace/instrumentation/opentelemetry14/OpenTelemetryInstrumentation.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ public boolean onlyMatchKnownTypes() {
5858
public String[] helperClassNames() {
5959
return new String[] {
6060
"datadog.opentelemetry.shim.context.OtelContext",
61-
"datadog.opentelemetry.shim.context.OtelContext$1",
6261
"datadog.opentelemetry.shim.context.OtelScope",
6362
"datadog.opentelemetry.shim.context.propagation.AgentTextMapPropagator",
6463
"datadog.opentelemetry.shim.context.propagation.OtelContextPropagators",

dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/main/java/datadog/trace/instrumentation/opentelemetry14/context/OpenTelemetryContextInstrumentation.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ public boolean onlyMatchKnownTypes() {
5555
public String[] helperClassNames() {
5656
return new String[] {
5757
"datadog.opentelemetry.shim.context.OtelContext",
58-
"datadog.opentelemetry.shim.context.OtelContext$1",
5958
"datadog.opentelemetry.shim.context.OtelScope",
6059
"datadog.opentelemetry.shim.trace.OtelExtractedContext",
6160
"datadog.opentelemetry.shim.trace.OtelConventions",

dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/main/java/datadog/trace/instrumentation/opentelemetry14/context/OpenTelemetryContextStorageInstrumentation.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ public boolean onlyMatchKnownTypes() {
5656
public String[] helperClassNames() {
5757
return new String[] {
5858
"datadog.opentelemetry.shim.context.OtelContext",
59-
"datadog.opentelemetry.shim.context.OtelContext$1",
6059
"datadog.opentelemetry.shim.context.OtelScope",
6160
"datadog.opentelemetry.shim.trace.OtelExtractedContext",
6261
"datadog.opentelemetry.shim.trace.OtelConventions",

dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ class ContextTest extends AgentTestRunner {
170170
then:
171171
currentSpan != null
172172
!currentSpan.spanContext.isValid()
173+
174+
cleanup:
175+
ddScope.close()
176+
ddSpan.finish()
173177
}
174178

175179
def "test clearing context"() {
@@ -239,6 +243,14 @@ class ContextTest extends AgentTestRunner {
239243
}
240244
}
241245
}
246+
247+
cleanup:
248+
otelGrandChildScope?.close()
249+
otelGrandChildSpan?.end()
250+
ddChildScope?.close()
251+
ddChildSpan?.finish()
252+
otelParentScope.close()
253+
otelParentSpan.end()
242254
}
243255

244256
def "test context spans retrieval"() {

0 commit comments

Comments
 (0)
0