Skip to content

Commit 970881a

Browse files
laurittrask
andauthored
Fix SpanKey bridging for unbridgeable span (#12511)
Co-authored-by: Trask Stalnaker <[email protected]>
1 parent 427c8e5 commit 970881a

File tree

2 files changed

+52
-24
lines changed
  • instrumentation/opentelemetry-instrumentation-api/javaagent/src

2 files changed

+52
-24
lines changed

instrumentation/opentelemetry-instrumentation-api/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationapi/SpanKeyInstrumentation.java

+38-24
Original file line numberDiff line numberDiff line change
@@ -41,64 +41,78 @@ public void transform(TypeTransformer transformer) {
4141

4242
@SuppressWarnings("unused")
4343
public static class StoreInContextAdvice {
44-
@Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class)
45-
public static Object onEnter() {
46-
return null;
47-
}
48-
49-
@Advice.OnMethodExit(suppress = Throwable.class)
50-
public static void onExit(
44+
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
45+
public static Context onEnter(
5146
@Advice.This SpanKey applicationSpanKey,
5247
@Advice.Argument(0) Context applicationContext,
53-
@Advice.Argument(1) Span applicationSpan,
54-
@Advice.Return(readOnly = false) Context newApplicationContext) {
48+
@Advice.Argument(1) Span applicationSpan) {
5549

5650
io.opentelemetry.instrumentation.api.internal.SpanKey agentSpanKey =
5751
SpanKeyBridging.toAgentOrNull(applicationSpanKey);
5852
if (agentSpanKey == null) {
59-
return;
53+
return null;
6054
}
6155

6256
io.opentelemetry.context.Context agentContext =
6357
AgentContextStorage.getAgentContext(applicationContext);
6458

6559
io.opentelemetry.api.trace.Span agentSpan = Bridging.toAgentOrNull(applicationSpan);
6660
if (agentSpan == null) {
67-
return;
61+
// if application span can not be bridged to agent span, this could happen when it is not
62+
// created through bridged GlobalOpenTelemetry, we'll let the original method run and
63+
// store the span in context without bridging
64+
return null;
6865
}
6966

7067
io.opentelemetry.context.Context newAgentContext =
7168
agentSpanKey.storeInContext(agentContext, agentSpan);
7269

73-
newApplicationContext = AgentContextStorage.toApplicationContext(newAgentContext);
70+
return AgentContextStorage.toApplicationContext(newAgentContext);
71+
}
72+
73+
@Advice.OnMethodExit(suppress = Throwable.class)
74+
public static void onExit(
75+
@Advice.Enter Context newApplicationContext,
76+
@Advice.Return(readOnly = false) Context result) {
77+
78+
if (newApplicationContext != null) {
79+
result = newApplicationContext;
80+
}
7481
}
7582
}
7683

7784
@SuppressWarnings("unused")
7885
public static class FromContextOrNullAdvice {
79-
@Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class)
80-
public static Object onEnter() {
81-
return null;
82-
}
83-
84-
@Advice.OnMethodExit(suppress = Throwable.class)
85-
public static void onExit(
86-
@Advice.This SpanKey applicationSpanKey,
87-
@Advice.Argument(0) Context applicationContext,
88-
@Advice.Return(readOnly = false) Span applicationSpan) {
86+
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
87+
public static Span onEnter(
88+
@Advice.This SpanKey applicationSpanKey, @Advice.Argument(0) Context applicationContext) {
8989

9090
io.opentelemetry.instrumentation.api.internal.SpanKey agentSpanKey =
9191
SpanKeyBridging.toAgentOrNull(applicationSpanKey);
9292
if (agentSpanKey == null) {
93-
return;
93+
return null;
9494
}
9595

9696
io.opentelemetry.context.Context agentContext =
9797
AgentContextStorage.getAgentContext(applicationContext);
9898

9999
io.opentelemetry.api.trace.Span agentSpan = agentSpanKey.fromContextOrNull(agentContext);
100+
if (agentSpan == null) {
101+
// Bridged agent span was not found. Run the original method, there could be an unbridged
102+
// span stored in the application context.
103+
return null;
104+
}
100105

101-
applicationSpan = agentSpan == null ? null : Bridging.toApplication(agentSpan);
106+
return Bridging.toApplication(agentSpan);
107+
}
108+
109+
@Advice.OnMethodExit(suppress = Throwable.class)
110+
public static void onExit(
111+
@Advice.Enter Span applicationSpan, @Advice.Return(readOnly = false) Span result) {
112+
113+
if (applicationSpan != null) {
114+
result = applicationSpan;
115+
}
102116
}
103117
}
104118
}

instrumentation/opentelemetry-instrumentation-api/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/instrumentationapi/ContextBridgeTest.java

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.opentelemetry.javaagent.instrumentation.instrumentationapi;
77

88
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
9+
import static org.assertj.core.api.Assertions.assertThat;
910
import static org.junit.jupiter.api.Assertions.assertNotNull;
1011

1112
import io.opentelemetry.api.trace.Span;
@@ -18,6 +19,7 @@
1819
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
1920
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
2021
import io.opentelemetry.javaagent.instrumentation.testing.AgentSpanTesting;
22+
import io.opentelemetry.sdk.OpenTelemetrySdk;
2123
import io.opentelemetry.semconv.ErrorAttributes;
2224
import io.opentelemetry.semconv.HttpAttributes;
2325
import java.util.Arrays;
@@ -76,6 +78,18 @@ void testSpanKeyBridge() {
7678
});
7779
}
7880

81+
@Test
82+
void testSpanKeyBridge_UnbridgedSpan() {
83+
OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder().build();
84+
// span is bridged only when it is created though a bridged OpenTelemetry instance obtained
85+
// from GlobalOpenTelemetry
86+
Span span = openTelemetry.getTracer("test").spanBuilder("test").startSpan();
87+
88+
Context context = SpanKey.HTTP_CLIENT.storeInContext(Context.current(), span);
89+
assertThat(context).isNotNull();
90+
assertThat(SpanKey.HTTP_CLIENT.fromContextOrNull(context)).isEqualTo(span);
91+
}
92+
7993
@Test
8094
void testHttpRouteHolder_SameSourceAsServerInstrumentationDoesNotOverrideRoute() {
8195
AgentSpanTesting.runWithHttpServerSpan(

0 commit comments

Comments
 (0)