diff --git a/extensions/opentelemetry/deployment/pom.xml b/extensions/opentelemetry/deployment/pom.xml
index c042883b380157..4b5932e3dc77ed 100644
--- a/extensions/opentelemetry/deployment/pom.xml
+++ b/extensions/opentelemetry/deployment/pom.xml
@@ -45,6 +45,14 @@
io.quarkus
quarkus-grpc-common-deployment
+
+ io.quarkus
+ quarkus-resteasy-reactive-spi-deployment
+
+
+ io.quarkus
+ quarkus-resteasy-common-spi
+
diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/instrumentation/InstrumentationProcessor.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/instrumentation/InstrumentationProcessor.java
index 16bb2819c906fc..36b7648e37aa15 100644
--- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/instrumentation/InstrumentationProcessor.java
+++ b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/tracing/instrumentation/InstrumentationProcessor.java
@@ -26,6 +26,9 @@
import io.quarkus.opentelemetry.runtime.tracing.intrumentation.grpc.GrpcTracingServerInterceptor;
import io.quarkus.opentelemetry.runtime.tracing.intrumentation.reactivemessaging.ReactiveMessagingTracingDecorator;
import io.quarkus.opentelemetry.runtime.tracing.intrumentation.restclient.OpenTelemetryClientFilter;
+import io.quarkus.opentelemetry.runtime.tracing.intrumentation.resteasy.OpenTelemetryServerFilter;
+import io.quarkus.resteasy.common.spi.ResteasyJaxrsProviderBuildItem;
+import io.quarkus.resteasy.reactive.spi.ContainerRequestFilterBuildItem;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.vertx.core.deployment.VertxOptionsConsumerBuildItem;
import io.vertx.core.VertxOptions;
@@ -112,4 +115,26 @@ VertxOptionsConsumerBuildItem vertxTracingOptions(InstrumentationRecorder record
LIBRARY_AFTER);
}
+ // RESTEasy and Vert.x web
+ @BuildStep
+ void registerResteasyClassicAndOrResteasyReactiveProvider(
+ Capabilities capabilities,
+ BuildProducer resteasyJaxrsProviderBuildItemBuildProducer,
+ BuildProducer containerRequestFilterBuildItemBuildProducer) {
+ boolean isResteasyClassicAvailable = capabilities.isPresent(Capability.RESTEASY);
+ boolean isResteasyReactiveAvailable = capabilities.isPresent(Capability.RESTEASY_REACTIVE);
+
+ if (!isResteasyClassicAvailable && !isResteasyReactiveAvailable) {
+ // if RestEasy is not available then no need to continue
+ return;
+ }
+
+ if (isResteasyClassicAvailable) {
+ resteasyJaxrsProviderBuildItemBuildProducer
+ .produce(new ResteasyJaxrsProviderBuildItem(OpenTelemetryServerFilter.class.getName()));
+ } else {
+ containerRequestFilterBuildItemBuildProducer
+ .produce(new ContainerRequestFilterBuildItem.Builder(OpenTelemetryServerFilter.class.getName()).build());
+ }
+ }
}
diff --git a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDILegacyTest.java b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDILegacyTest.java
index 1e2f344aa40981..00107904f049fd 100644
--- a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDILegacyTest.java
+++ b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDILegacyTest.java
@@ -3,6 +3,7 @@
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
import static io.opentelemetry.api.trace.SpanKind.SERVER;
import static io.quarkus.opentelemetry.deployment.common.TestSpanExporter.getSpanByKindAndParentId;
+import static io.quarkus.opentelemetry.deployment.common.TestUtil.assertStringAttribute;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -22,7 +23,9 @@
import io.opentelemetry.extension.annotations.WithSpan;
import io.opentelemetry.sdk.trace.data.SpanData;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import io.quarkus.opentelemetry.deployment.common.TestSpanExporter;
+import io.quarkus.opentelemetry.deployment.common.TestUtil;
import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;
@@ -31,6 +34,7 @@ public class OpenTelemetryHttpCDILegacyTest {
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(
() -> ShrinkWrap.create(JavaArchive.class)
+ .addClass(TestUtil.class)
.addClass(HelloResource.class)
.addClass(HelloBean.class)
.addClass(TestSpanExporter.class));
@@ -55,6 +59,10 @@ void telemetry() {
SpanData server = getSpanByKindAndParentId(spans, SERVER, "0000000000000000");
assertEquals("/hello", server.getName());
assertEquals(SERVER, server.getKind());
+ // verify that OpenTelemetryServerFilter took place
+ assertStringAttribute(server, SemanticAttributes.CODE_NAMESPACE,
+ "io.quarkus.opentelemetry.deployment.OpenTelemetryHttpCDILegacyTest$HelloResource");
+ assertStringAttribute(server, SemanticAttributes.CODE_FUNCTION, "hello");
SpanData internal = getSpanByKindAndParentId(spans, INTERNAL, server.getSpanId());
assertEquals("HelloBean.hello", internal.getName());
diff --git a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDITest.java b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDITest.java
index c235f703747511..addd1335ef8c31 100644
--- a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDITest.java
+++ b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDITest.java
@@ -3,6 +3,7 @@
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
import static io.opentelemetry.api.trace.SpanKind.SERVER;
import static io.quarkus.opentelemetry.deployment.common.TestSpanExporter.getSpanByKindAndParentId;
+import static io.quarkus.opentelemetry.deployment.common.TestUtil.assertStringAttribute;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -22,7 +23,9 @@
import io.opentelemetry.instrumentation.annotations.WithSpan;
import io.opentelemetry.sdk.trace.data.SpanData;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import io.quarkus.opentelemetry.deployment.common.TestSpanExporter;
+import io.quarkus.opentelemetry.deployment.common.TestUtil;
import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;
@@ -31,6 +34,7 @@ public class OpenTelemetryHttpCDITest {
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(
() -> ShrinkWrap.create(JavaArchive.class)
+ .addClass(TestUtil.class)
.addClass(HelloResource.class)
.addClass(HelloBean.class)
.addClass(TestSpanExporter.class));
@@ -54,6 +58,10 @@ void telemetry() {
final SpanData server = getSpanByKindAndParentId(spans, SERVER, "0000000000000000");
assertEquals("/hello", server.getName());
+ // verify that OpenTelemetryServerFilter took place
+ assertStringAttribute(server, SemanticAttributes.CODE_NAMESPACE,
+ "io.quarkus.opentelemetry.deployment.OpenTelemetryHttpCDITest$HelloResource");
+ assertStringAttribute(server, SemanticAttributes.CODE_FUNCTION, "hello");
final SpanData internalFromBean = getSpanByKindAndParentId(spans, INTERNAL, server.getSpanId());
assertEquals("HelloBean.hello", internalFromBean.getName());
diff --git a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/common/TestUtil.java b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/common/TestUtil.java
index bec058689979a8..c2c4911f50cc79 100644
--- a/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/common/TestUtil.java
+++ b/extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/common/TestUtil.java
@@ -1,15 +1,19 @@
package io.quarkus.opentelemetry.deployment.common;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.TracerProvider;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.IdGenerator;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
+import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.quarkus.arc.Unremovable;
@@ -60,4 +64,8 @@ public static TextMapPropagator[] getTextMapPropagators(OpenTelemetry openTeleme
privatePropagatorsField.setAccessible(true);
return (TextMapPropagator[]) privatePropagatorsField.get(textMapPropagator);
}
+
+ public static void assertStringAttribute(SpanData spanData, AttributeKey attributeKey, String expectedValue) {
+ assertEquals(expectedValue, spanData.getAttributes().get(attributeKey), "Attribute Key Named:" + attributeKey.getKey());
+ }
}
diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/resteasy/OpenTelemetryServerFilter.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/resteasy/OpenTelemetryServerFilter.java
new file mode 100644
index 00000000000000..e7eeb4396963d0
--- /dev/null
+++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/resteasy/OpenTelemetryServerFilter.java
@@ -0,0 +1,31 @@
+package io.quarkus.opentelemetry.runtime.tracing.intrumentation.resteasy;
+
+import java.io.IOException;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Provider;
+
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
+
+/**
+ * Handles both RESTEasy Classic and RESTEasy Reactive (via Vert.x)
+ */
+@Provider
+public class OpenTelemetryServerFilter implements ContainerRequestFilter {
+
+ @Context
+ ResourceInfo resourceInfo;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ Span localRootSpan = LocalRootSpan.current();
+
+ localRootSpan.setAttribute(SemanticAttributes.CODE_NAMESPACE, resourceInfo.getResourceClass().getName());
+ localRootSpan.setAttribute(SemanticAttributes.CODE_FUNCTION, resourceInfo.getResourceMethod().getName());
+ }
+}