diff --git a/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/NonAppEndpointsDisabledWithRootPathTest.java b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/NonAppEndpointsDisabledWithRootPathTest.java new file mode 100644 index 0000000000000..a23942bf350cb --- /dev/null +++ b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/NonAppEndpointsDisabledWithRootPathTest.java @@ -0,0 +1,46 @@ +package io.quarkus.opentelemetry.deployment; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; + +import javax.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class NonAppEndpointsDisabledWithRootPathTest { + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClass(TracerRouter.class) + .addClass(TestSpanExporter.class)) + .overrideConfigKey("quarkus.http.root-path", "/app") + .overrideConfigKey("quarkus.http.non-application-root-path", "quarkus"); + + @Inject + TestSpanExporter testSpanExporter; + + @Test + void testHealthEndpointNotTraced() { + RestAssured.when().get("/quarkus/health").then() + .statusCode(200) + .body(containsString("\"status\": \"UP\"")); + + RestAssured.when().get("/quarkus/health/live").then() + .statusCode(200) + .body(containsString("\"status\": \"UP\"")); + + RestAssured.when().get("/quarkus/health/ready").then() + .statusCode(200) + .body(containsString("\"status\": \"UP\"")); + + RestAssured.when().get("/tracer").then() + .statusCode(200) + .body(is("Hello Tracer!")); + + testSpanExporter.assertSpanCount(2); + } +} diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/NonApplicationEndpointSampler.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/NonApplicationEndpointSampler.java index bae2db995d28e..b266296090f77 100644 --- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/NonApplicationEndpointSampler.java +++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/NonApplicationEndpointSampler.java @@ -2,6 +2,8 @@ import java.util.List; +import org.eclipse.microprofile.config.ConfigProvider; + import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; @@ -9,23 +11,38 @@ import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.sdk.trace.samplers.SamplingDecision; import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import io.quarkus.runtime.configuration.NormalizeRootHttpPathConverter; +import io.smallrye.config.SmallRyeConfig; public class NonApplicationEndpointSampler implements Sampler { private static final SamplingResult NEGATIVE_SAMPLING_RESULT = SamplingResult.create(SamplingDecision.DROP); - private final Sampler root; + private final Sampler sampler; + private final String namePattern; + + public NonApplicationEndpointSampler(Sampler sampler) { + this.sampler = sampler; - public NonApplicationEndpointSampler(Sampler root) { - this.root = root; + // We don't use the HttpBuildTimeConfig because we don't want to add a dependency to vertx-http and vertx-http + // may not even be available. + SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class); + if (config.isPropertyPresent("quarkus.http.root-path")) { + String rootPath = config.getValue("quarkus.http.root-path", new NormalizeRootHttpPathConverter()); + String nonApplicationRootPath = config.getRawValue("quarkus.http.non-application-root-path"); + // span names don't include the leading slash + this.namePattern = rootPath.substring(1) + nonApplicationRootPath; + } else { + this.namePattern = null; + } } @Override public SamplingResult shouldSample(Context parentContext, String traceId, String name, SpanKind spanKind, Attributes attributes, List parentLinks) { - if (name.startsWith("q/") && spanKind == SpanKind.SERVER) { + if (namePattern != null && name.startsWith(namePattern) && spanKind == SpanKind.SERVER) { return NEGATIVE_SAMPLING_RESULT; } - return root.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); + return sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); } @Override