-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Azure SDK instrumentation (open-telemetry#5467)
* Add Azure SDK instrumentation * Add to supported libraries table * Keep suppression for 1.19
- Loading branch information
Showing
18 changed files
with
530 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
instrumentation/azure-core/azure-core-1.14/javaagent/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
plugins { | ||
id("otel.javaagent-instrumentation") | ||
} | ||
|
||
muzzle { | ||
pass { | ||
group.set("com.azure") | ||
module.set("azure-core") | ||
versions.set("[1.14.0,1.19.0)") | ||
assertInverse.set(true) | ||
} | ||
} | ||
|
||
sourceSets { | ||
main { | ||
val shadedDep = project(":instrumentation:azure-core:azure-core-1.14:library-instrumentation-shaded") | ||
output.dir(shadedDep.file("build/extracted/shadow"), "builtBy" to ":instrumentation:azure-core:azure-core-1.14:library-instrumentation-shaded:extractShadowJar") | ||
} | ||
} | ||
|
||
dependencies { | ||
compileOnly(project(path = ":instrumentation:azure-core:azure-core-1.14:library-instrumentation-shaded", configuration = "shadow")) | ||
|
||
library("com.azure:azure-core:1.14.0") | ||
|
||
// Ensure no cross interference | ||
testInstrumentation(project(":instrumentation:azure-core:azure-core-1.19:javaagent")) | ||
} |
46 changes: 46 additions & 0 deletions
46
...entelemetry/javaagent/instrumentation/azurecore/v1_14/AzureHttpClientInstrumentation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.azurecore.v1_14; | ||
|
||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; | ||
import static net.bytebuddy.matcher.ElementMatchers.isMethod; | ||
import static net.bytebuddy.matcher.ElementMatchers.isPublic; | ||
import static net.bytebuddy.matcher.ElementMatchers.named; | ||
import static net.bytebuddy.matcher.ElementMatchers.returns; | ||
|
||
import com.azure.core.http.HttpResponse; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||
import net.bytebuddy.asm.Advice; | ||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.matcher.ElementMatcher; | ||
import reactor.core.publisher.Mono; | ||
|
||
public class AzureHttpClientInstrumentation implements TypeInstrumentation { | ||
|
||
@Override | ||
public ElementMatcher<TypeDescription> typeMatcher() { | ||
return implementsInterface(named("com.azure.core.http.HttpClient")); | ||
} | ||
|
||
@Override | ||
public void transform(TypeTransformer transformer) { | ||
transformer.applyAdviceToMethod( | ||
isMethod() | ||
.and(isPublic()) | ||
.and(named("send")) | ||
.and(returns(named("reactor.core.publisher.Mono"))), | ||
this.getClass().getName() + "$SuppressNestedClientAdvice"); | ||
} | ||
|
||
public static class SuppressNestedClientAdvice { | ||
|
||
@Advice.OnMethodExit(suppress = Throwable.class) | ||
public static void methodExit(@Advice.Return(readOnly = false) Mono<HttpResponse> mono) { | ||
mono = new SuppressNestedClientMono<>(mono); | ||
} | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
...pentelemetry/javaagent/instrumentation/azurecore/v1_14/AzureSdkInstrumentationModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.azurecore.v1_14; | ||
|
||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; | ||
import static java.util.Arrays.asList; | ||
import static net.bytebuddy.matcher.ElementMatchers.named; | ||
import static net.bytebuddy.matcher.ElementMatchers.not; | ||
|
||
import com.google.auto.service.AutoService; | ||
import io.opentelemetry.javaagent.extension.instrumentation.HelperResourceBuilder; | ||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||
import java.util.List; | ||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.matcher.ElementMatcher; | ||
|
||
@AutoService(InstrumentationModule.class) | ||
public class AzureSdkInstrumentationModule extends InstrumentationModule { | ||
public AzureSdkInstrumentationModule() { | ||
super("azure-core", "azure-core-1.14"); | ||
} | ||
|
||
@Override | ||
public void registerHelperResources(HelperResourceBuilder helperResourceBuilder) { | ||
helperResourceBuilder.register( | ||
"META-INF/services/com.azure.core.http.policy.AfterRetryPolicyProvider", | ||
"azure-core-1.14/META-INF/services/com.azure.core.http.policy.AfterRetryPolicyProvider"); | ||
helperResourceBuilder.register( | ||
"META-INF/services/com.azure.core.util.tracing.Tracer", | ||
"azure-core-1.14/META-INF/services/com.azure.core.util.tracing.Tracer"); | ||
} | ||
|
||
@Override | ||
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() { | ||
return hasClassesNamed("com.azure.core.util.tracing.Tracer") | ||
// this is needed to prevent this instrumentation from being applied to azure-core 1.19+ | ||
.and(not(hasClassesNamed("com.azure.core.util.tracing.StartSpanOptions"))) | ||
.and(not(hasClassesNamed("com.azure.core.tracing.opentelemetry.OpenTelemetryTracer"))); | ||
} | ||
|
||
@Override | ||
public List<TypeInstrumentation> typeInstrumentations() { | ||
return asList(new EmptyTypeInstrumentation(), new AzureHttpClientInstrumentation()); | ||
} | ||
|
||
public static class EmptyTypeInstrumentation implements TypeInstrumentation { | ||
@Override | ||
public ElementMatcher<TypeDescription> typeMatcher() { | ||
// we cannot use com.azure.core.http.policy.AfterRetryPolicyProvider | ||
// or com.azure.core.util.tracing.Tracer here because we inject classes that implement these | ||
// interfaces, causing the first one of these interfaces to be transformed to cause itself to | ||
// be loaded (again), which leads to duplicate class definition error after the interface is | ||
// transformed and the triggering class loader tries to load it. | ||
// | ||
// this is a list of all classes that call one of these: | ||
// * ServiceLoader.load(AfterRetryPolicyProvider.class) | ||
// * ServiceLoader.load(Tracer.class) | ||
return named("com.azure.core.http.policy.HttpPolicyProviders") | ||
.or(named("com.azure.core.util.tracing.TracerProxy")) | ||
.or(named("com.azure.cosmos.CosmosAsyncClient")) | ||
.or(named("com.azure.messaging.eventhubs.EventHubClientBuilder")) | ||
.or(named("com.azure.messaging.eventhubs.EventProcessorClientBuilder")) | ||
.or(named("com.azure.messaging.servicebus.ServiceBusClientBuilder")); | ||
} | ||
|
||
@Override | ||
public void transform(TypeTransformer transformer) { | ||
// Nothing to instrument, no methods to match | ||
} | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
.../io/opentelemetry/javaagent/instrumentation/azurecore/v1_14/SuppressNestedClientMono.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.azurecore.v1_14; | ||
|
||
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; | ||
|
||
import io.opentelemetry.api.trace.Span; | ||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.context.Scope; | ||
import io.opentelemetry.instrumentation.api.internal.SpanKey; | ||
import reactor.core.CoreSubscriber; | ||
import reactor.core.publisher.Mono; | ||
|
||
public class SuppressNestedClientMono<T> extends Mono<T> { | ||
|
||
private final Mono<T> delegate; | ||
|
||
public SuppressNestedClientMono(Mono<T> delegate) { | ||
this.delegate = delegate; | ||
} | ||
|
||
@Override | ||
public void subscribe(CoreSubscriber<? super T> actual) { | ||
Context parentContext = currentContext(); | ||
if (SpanKey.HTTP_CLIENT.fromContextOrNull(parentContext) == null) { | ||
try (Scope ignored = | ||
SpanKey.HTTP_CLIENT.storeInContext(parentContext, Span.getInvalid()).makeCurrent()) { | ||
delegate.subscribe(actual); | ||
} | ||
} else { | ||
delegate.subscribe(actual); | ||
} | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...ces/azure-core-1.14/META-INF/services/com.azure.core.http.policy.AfterRetryPolicyProvider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
io.opentelemetry.javaagent.instrumentation.azurecore.v1_14.shaded.com.azure.core.tracing.opentelemetry.OpenTelemetryHttpPolicy |
1 change: 1 addition & 0 deletions
1
...t/src/main/resources/azure-core-1.14/META-INF/services/com.azure.core.util.tracing.Tracer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
io.opentelemetry.javaagent.instrumentation.azurecore.v1_14.shaded.com.azure.core.tracing.opentelemetry.OpenTelemetryTracer |
43 changes: 43 additions & 0 deletions
43
instrumentation/azure-core/azure-core-1.14/javaagent/src/test/groovy/AzureSdkTest.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import com.azure.core.http.policy.HttpPolicyProviders | ||
import com.azure.core.util.Context | ||
import com.azure.core.util.tracing.TracerProxy | ||
import io.opentelemetry.api.trace.StatusCode | ||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification | ||
|
||
class AzureSdkTest extends AgentInstrumentationSpecification { | ||
|
||
def "test helper classes injected"() { | ||
expect: | ||
TracerProxy.isTracingEnabled() | ||
|
||
def list = new ArrayList() | ||
HttpPolicyProviders.addAfterRetryPolicies(list) | ||
|
||
list.size() == 1 | ||
list.get(0).getClass().getName() == "io.opentelemetry.javaagent.instrumentation.azurecore.v1_14.shaded" + | ||
".com.azure.core.tracing.opentelemetry.OpenTelemetryHttpPolicy" | ||
} | ||
|
||
def "test span"() { | ||
when: | ||
Context context = TracerProxy.start("hello", Context.NONE) | ||
TracerProxy.end(200, null, context) | ||
|
||
then: | ||
assertTraces(1) { | ||
trace(0, 1) { | ||
span(0) { | ||
name "hello" | ||
status StatusCode.OK | ||
attributes { | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
instrumentation/azure-core/azure-core-1.14/library-instrumentation-shaded/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
plugins { | ||
id("com.github.johnrengelman.shadow") | ||
|
||
id("otel.java-conventions") | ||
} | ||
|
||
group = "io.opentelemetry.javaagent.instrumentation" | ||
|
||
dependencies { | ||
// this is the latest version that works with azure-core 1.14 | ||
implementation("com.azure:azure-core-tracing-opentelemetry:1.0.0-beta.12") | ||
} | ||
|
||
tasks { | ||
shadowJar { | ||
exclude("META-INF/services/*") | ||
|
||
dependencies { | ||
// including only azure-core-tracing-opentelemetry excludes its transitive dependencies | ||
include(dependency("com.azure:azure-core-tracing-opentelemetry")) | ||
} | ||
relocate("com.azure.core.tracing.opentelemetry", "io.opentelemetry.javaagent.instrumentation.azurecore.v1_14.shaded.com.azure.core.tracing.opentelemetry") | ||
} | ||
|
||
val extractShadowJar by registering(Copy::class) { | ||
dependsOn(shadowJar) | ||
from(zipTree(shadowJar.get().archiveFile)) | ||
into("build/extracted/shadow") | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
instrumentation/azure-core/azure-core-1.19/javaagent/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
plugins { | ||
id("otel.javaagent-instrumentation") | ||
} | ||
|
||
muzzle { | ||
pass { | ||
group.set("com.azure") | ||
module.set("azure-core") | ||
versions.set("[1.19.0,)") | ||
assertInverse.set(true) | ||
} | ||
} | ||
|
||
sourceSets { | ||
main { | ||
val shadedDep = project(":instrumentation:azure-core:azure-core-1.19:library-instrumentation-shaded") | ||
output.dir(shadedDep.file("build/extracted/shadow"), "builtBy" to ":instrumentation:azure-core:azure-core-1.19:library-instrumentation-shaded:extractShadowJar") | ||
} | ||
} | ||
|
||
dependencies { | ||
compileOnly(project(path = ":instrumentation:azure-core:azure-core-1.19:library-instrumentation-shaded", configuration = "shadow")) | ||
|
||
library("com.azure:azure-core:1.19.0") | ||
|
||
// Ensure no cross interference | ||
testInstrumentation(project(":instrumentation:azure-core:azure-core-1.14:javaagent")) | ||
} |
46 changes: 46 additions & 0 deletions
46
...entelemetry/javaagent/instrumentation/azurecore/v1_19/AzureHttpClientInstrumentation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.azurecore.v1_19; | ||
|
||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; | ||
import static net.bytebuddy.matcher.ElementMatchers.isMethod; | ||
import static net.bytebuddy.matcher.ElementMatchers.isPublic; | ||
import static net.bytebuddy.matcher.ElementMatchers.named; | ||
import static net.bytebuddy.matcher.ElementMatchers.returns; | ||
|
||
import com.azure.core.http.HttpResponse; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||
import net.bytebuddy.asm.Advice; | ||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.matcher.ElementMatcher; | ||
import reactor.core.publisher.Mono; | ||
|
||
public class AzureHttpClientInstrumentation implements TypeInstrumentation { | ||
|
||
@Override | ||
public ElementMatcher<TypeDescription> typeMatcher() { | ||
return implementsInterface(named("com.azure.core.http.HttpClient")); | ||
} | ||
|
||
@Override | ||
public void transform(TypeTransformer transformer) { | ||
transformer.applyAdviceToMethod( | ||
isMethod() | ||
.and(isPublic()) | ||
.and(named("send")) | ||
.and(returns(named("reactor.core.publisher.Mono"))), | ||
this.getClass().getName() + "$SuppressNestedClientAdvice"); | ||
} | ||
|
||
public static class SuppressNestedClientAdvice { | ||
|
||
@Advice.OnMethodExit(suppress = Throwable.class) | ||
public static void methodExit(@Advice.Return(readOnly = false) Mono<HttpResponse> mono) { | ||
mono = new SuppressNestedClientMono<>(mono); | ||
} | ||
} | ||
} |
Oops, something went wrong.