Skip to content

Commit d8a6655

Browse files
author
Liudmila Molkova
committed
Address feedback, add tests, update changelog, lint
1 parent 7892f02 commit d8a6655

File tree

10 files changed

+127
-6
lines changed

10 files changed

+127
-6
lines changed

CHANGELOG.md

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

33
## Unreleased
44

5+
- Update azure-core-tracing-opentelemetry version and improve HTTP suppression to back off
6+
when Azure SDK tracing was disabled.
7+
([#12489](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/12489))
8+
59
## Version 2.9.0 (2024-10-17)
610

711
### 📈 Enhancements

instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/AzureHttpClientInstrumentation.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ public void transform(TypeTransformer transformer) {
5151
@SuppressWarnings("unused")
5252
public static class SuppressNestedClientMonoAdvice {
5353
@Advice.OnMethodExit(suppress = Throwable.class)
54-
public static void asyncSendExit(@Advice.Argument(1) com.azure.core.util.Context azContext, @Advice.Return(readOnly = false) Mono<HttpResponse> mono) {
54+
public static void asyncSendExit(
55+
@Advice.Argument(1) com.azure.core.util.Context azContext,
56+
@Advice.Return(readOnly = false) Mono<HttpResponse> mono) {
5557
mono = disallowNestedClientSpanMono(mono, azContext);
5658
}
5759
}
@@ -60,7 +62,9 @@ public static void asyncSendExit(@Advice.Argument(1) com.azure.core.util.Context
6062
public static class SuppressNestedClientSyncAdvice {
6163

6264
@Advice.OnMethodEnter(suppress = Throwable.class)
63-
public static void syncSendEnter(@Advice.Argument(1) com.azure.core.util.Context azContext, @Advice.Local("otelScope") Scope scope) {
65+
public static void syncSendEnter(
66+
@Advice.Argument(1) com.azure.core.util.Context azContext,
67+
@Advice.Local("otelScope") Scope scope) {
6468
scope = disallowNestedClientSpanSync(azContext);
6569
}
6670

instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/AzureSdkInstrumentationModule.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
5858
// this class was introduced in azure-core 1.36
5959
return hasClassesNamed("com.azure.core.util.tracing.TracerProvider")
6060
.and(not(hasClassesNamed("com.azure.core.tracing.opentelemetry.OpenTelemetryTracer")))
61+
// this class was introduced in azure-core 1.53
6162
.and(not(hasClassesNamed("com.azure.core.util.LibraryTelemetryOptions")));
6263
}
6364

instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/SuppressNestedClientHelper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public static Scope disallowNestedClientSpanSync(com.azure.core.util.Context azC
2525
return null;
2626
}
2727

28-
public static <T> Mono<T> disallowNestedClientSpanMono(Mono<T> delegate, com.azure.core.util.Context azContext) {
28+
public static <T> Mono<T> disallowNestedClientSpanMono(
29+
Mono<T> delegate, com.azure.core.util.Context azContext) {
2930
return new Mono<T>() {
3031
@Override
3132
public void subscribe(CoreSubscriber<? super T> coreSubscriber) {

instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66
group = "io.opentelemetry.javaagent.instrumentation"
77

88
dependencies {
9+
// this is the latest version that works with azure-core 1.36
910
implementation("com.azure:azure-core-tracing-opentelemetry:1.0.0-beta.49")
1011
}
1112

instrumentation/azure-core/azure-core-1.53/javaagent/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ testing {
4242
dependencies {
4343
if (latestDepTest) {
4444
implementation("com.azure:azure-core:+")
45+
implementation("com.azure:azure-core-test:+")
4546
} else {
4647
implementation("com.azure:azure-core:1.53.0")
48+
implementation("com.azure:azure-core-test:1.26.2")
4749
}
4850
}
4951
}

instrumentation/azure-core/azure-core-1.53/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_53/AzureHttpClientInstrumentation.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ public void transform(TypeTransformer transformer) {
5151
@SuppressWarnings("unused")
5252
public static class SuppressNestedClientMonoAdvice {
5353
@Advice.OnMethodExit(suppress = Throwable.class)
54-
public static void asyncSendExit(@Advice.Argument(1) com.azure.core.util.Context azContext, @Advice.Return(readOnly = false) Mono<HttpResponse> mono) {
54+
public static void asyncSendExit(
55+
@Advice.Argument(1) com.azure.core.util.Context azContext,
56+
@Advice.Return(readOnly = false) Mono<HttpResponse> mono) {
5557
mono = disallowNestedClientSpanMono(mono, azContext);
5658
}
5759
}
@@ -60,7 +62,9 @@ public static void asyncSendExit(@Advice.Argument(1) com.azure.core.util.Context
6062
public static class SuppressNestedClientSyncAdvice {
6163

6264
@Advice.OnMethodEnter(suppress = Throwable.class)
63-
public static void syncSendEnter(@Advice.Argument(1) com.azure.core.util.Context azContext, @Advice.Local("otelScope") Scope scope) {
65+
public static void syncSendEnter(
66+
@Advice.Argument(1) com.azure.core.util.Context azContext,
67+
@Advice.Local("otelScope") Scope scope) {
6468
scope = disallowNestedClientSpanSync(azContext);
6569
}
6670

instrumentation/azure-core/azure-core-1.53/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_53/SuppressNestedClientHelper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public static Scope disallowNestedClientSpanSync(com.azure.core.util.Context azC
2525
return null;
2626
}
2727

28-
public static <T> Mono<T> disallowNestedClientSpanMono(Mono<T> delegate, com.azure.core.util.Context azContext) {
28+
public static <T> Mono<T> disallowNestedClientSpanMono(
29+
Mono<T> delegate, com.azure.core.util.Context azContext) {
2930
return new Mono<T>() {
3031
@Override
3132
public void subscribe(CoreSubscriber<? super T> coreSubscriber) {

instrumentation/azure-core/azure-core-1.53/javaagent/src/testAzure/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_53/AzureSdkTest.java

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,34 @@
77

88
import static org.assertj.core.api.Assertions.assertThat;
99

10+
import com.azure.core.annotation.ExpectedResponses;
11+
import com.azure.core.annotation.Get;
12+
import com.azure.core.annotation.Host;
13+
import com.azure.core.annotation.ServiceInterface;
14+
import com.azure.core.http.HttpClient;
15+
import com.azure.core.http.HttpPipeline;
16+
import com.azure.core.http.HttpPipelineBuilder;
17+
import com.azure.core.http.policy.HttpPipelinePolicy;
18+
import com.azure.core.http.policy.HttpPolicyProviders;
19+
import com.azure.core.http.rest.Response;
20+
import com.azure.core.http.rest.RestProxy;
21+
import com.azure.core.test.http.MockHttpResponse;
22+
import com.azure.core.util.ClientOptions;
1023
import com.azure.core.util.Context;
24+
import com.azure.core.util.TracingOptions;
1125
import io.opentelemetry.api.common.Attributes;
1226
import io.opentelemetry.api.trace.SpanKind;
27+
import io.opentelemetry.instrumentation.api.internal.SpanKey;
1328
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
1429
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
1530
import io.opentelemetry.sdk.trace.data.StatusData;
31+
import java.util.ArrayList;
32+
import java.util.List;
33+
import java.util.concurrent.atomic.AtomicBoolean;
1634
import org.junit.jupiter.api.Test;
1735
import org.junit.jupiter.api.extension.RegisterExtension;
36+
import reactor.core.publisher.Mono;
37+
import reactor.test.StepVerifier;
1838

1939
class AzureSdkTest {
2040

@@ -48,9 +68,91 @@ void testSpan() {
4868
.hasAttributesSatisfying(Attributes::isEmpty)));
4969
}
5070

71+
@Test
72+
void testPipelineAndSuppression() {
73+
AtomicBoolean hasClientAndHttpKeys = new AtomicBoolean(false);
74+
75+
HttpClient mockClient =
76+
request ->
77+
Mono.defer(
78+
() -> {
79+
// check if suppression is working
80+
hasClientAndHttpKeys.set(hasClientAndHttpSpans());
81+
return Mono.just(new MockHttpResponse(request, 200));
82+
});
83+
84+
StepVerifier.create(createService(mockClient, true).testMethod())
85+
.expectNextCount(1)
86+
.expectComplete()
87+
.verify();
88+
89+
assertThat(hasClientAndHttpKeys.get()).isTrue();
90+
testing.waitAndAssertTracesWithoutScopeVersionVerification(
91+
trace ->
92+
trace.hasSpansSatisfyingExactly(
93+
span ->
94+
span.hasName("myService.testMethod")
95+
.hasKind(SpanKind.INTERNAL)
96+
.hasStatus(StatusData.unset())
97+
.hasAttributesSatisfying(Attributes::isEmpty),
98+
span ->
99+
span.hasName("GET").hasKind(SpanKind.CLIENT).hasStatus(StatusData.unset())));
100+
}
101+
102+
@Test
103+
void testDisabledTracingNoSuppression() {
104+
AtomicBoolean hasClientAndHttpKeys = new AtomicBoolean(false);
105+
106+
HttpClient mockClient =
107+
request ->
108+
Mono.defer(
109+
() -> {
110+
// check if suppression is working
111+
hasClientAndHttpKeys.set(hasClientAndHttpSpans());
112+
return Mono.just(new MockHttpResponse(request, 200));
113+
});
114+
115+
StepVerifier.create(createService(mockClient, false).testMethod())
116+
.expectNextCount(1)
117+
.expectComplete()
118+
.verify();
119+
120+
assertThat(hasClientAndHttpKeys.get()).isFalse();
121+
}
122+
51123
private static com.azure.core.util.tracing.Tracer createAzTracer() {
52124
com.azure.core.util.tracing.TracerProvider azProvider =
53125
com.azure.core.util.tracing.TracerProvider.getDefaultProvider();
54126
return azProvider.createTracer("test-lib", "test-version", "otel.tests", null);
55127
}
128+
129+
private static TestInterface createService(HttpClient httpClient, boolean tracingEnabled) {
130+
List<HttpPipelinePolicy> policies = new ArrayList<>();
131+
HttpPolicyProviders.addAfterRetryPolicies(policies);
132+
133+
ClientOptions clientOptions =
134+
new ClientOptions().setTracingOptions(new TracingOptions().setEnabled(tracingEnabled));
135+
HttpPipeline pipeline =
136+
new HttpPipelineBuilder()
137+
.policies(policies.toArray(new HttpPipelinePolicy[0]))
138+
.httpClient(httpClient)
139+
.clientOptions(clientOptions)
140+
.build();
141+
142+
return RestProxy.create(TestInterface.class, pipeline);
143+
}
144+
145+
private static boolean hasClientAndHttpSpans() {
146+
io.opentelemetry.context.Context ctx = io.opentelemetry.context.Context.current();
147+
return SpanKey.KIND_CLIENT.fromContextOrNull(ctx) != null
148+
&& SpanKey.HTTP_CLIENT.fromContextOrNull(ctx) != null;
149+
}
150+
151+
@Host("https://azure.com")
152+
@ServiceInterface(name = "myService")
153+
interface TestInterface {
154+
@Get("path")
155+
@ExpectedResponses({200})
156+
Mono<Response<Void>> testMethod();
157+
}
56158
}

instrumentation/azure-core/azure-core-1.53/library-instrumentation-shaded/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66
group = "io.opentelemetry.javaagent.instrumentation"
77

88
dependencies {
9+
// this is the latest version that works with azure-core 1.53
910
implementation("com.azure:azure-core-tracing-opentelemetry:1.0.0-beta.50")
1011
}
1112

0 commit comments

Comments
 (0)