Skip to content

Commit

Permalink
OpenTelemetryServerFilter - which adds attributes code.namespace and …
Browse files Browse the repository at this point in the history
…code.function
  • Loading branch information
arik-dig committed Jan 2, 2023
1 parent bd66b86 commit 1a8b060
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 0 deletions.
8 changes: 8 additions & 0 deletions extensions/opentelemetry/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-grpc-common-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-spi-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-common-spi</artifactId>
</dependency>

<!-- Test Dependencies -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -112,4 +115,26 @@ VertxOptionsConsumerBuildItem vertxTracingOptions(InstrumentationRecorder record
LIBRARY_AFTER);
}

// RESTEasy and Vert.x web
@BuildStep
void registerResteasyClassicAndOrResteasyReactiveProvider(
Capabilities capabilities,
BuildProducer<ResteasyJaxrsProviderBuildItem> resteasyJaxrsProviderBuildItemBuildProducer,
BuildProducer<ContainerRequestFilterBuildItem> 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());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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));
Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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));
Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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<String> attributeKey, String expectedValue) {
assertEquals(expectedValue, spanData.getAttributes().get(attributeKey), "Attribute Key Named:" + attributeKey.getKey());
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}

0 comments on commit 1a8b060

Please sign in to comment.