diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/HandlerCodeAttributesGetter.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/HandlerCodeAttributesGetter.java index 6218a761a896..c1ac972ffc63 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/HandlerCodeAttributesGetter.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/HandlerCodeAttributesGetter.java @@ -7,17 +7,28 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter; import javax.annotation.Nullable; +import org.springframework.web.method.HandlerMethod; public class HandlerCodeAttributesGetter implements CodeAttributesGetter { @Nullable @Override public Class getCodeClass(Object handler) { - return handler.getClass(); + if (handler instanceof HandlerMethod) { + // Special case for requests mapped with annotations + HandlerMethod handlerMethod = (HandlerMethod) handler; + return handlerMethod.getMethod().getDeclaringClass(); + } else { + return handler.getClass(); + } } @Nullable @Override public String getMethodName(Object handler) { + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + return handlerMethod.getMethod().getName(); + } return "handle"; } } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/WebfluxSingletons.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/WebfluxSingletons.java index 5114c530c3a9..5e08e970db70 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/WebfluxSingletons.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/WebfluxSingletons.java @@ -6,11 +6,11 @@ package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteGetter; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.SpringWebfluxConfig; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.pattern.PathPattern; @@ -25,13 +25,11 @@ public final class WebfluxSingletons { Instrumenter.builder( GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, new WebfluxSpanNameExtractor()); - if (SpringWebfluxConfig.captureExperimentalSpanAttributes()) { - builder.addAttributesExtractor(new ExperimentalAttributesExtractor()); - } - INSTRUMENTER = builder .setEnabled(ExperimentalConfig.get().controllerTelemetryEnabled()) + .addAttributesExtractor( + CodeAttributesExtractor.create(new HandlerCodeAttributesGetter())) .buildInstrumenter(); } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java index ed267f43e832..5bff9988e0bb 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java @@ -5,7 +5,6 @@ package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server; -import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; @@ -25,6 +24,8 @@ import static io.opentelemetry.semconv.UrlAttributes.URL_PATH; import static io.opentelemetry.semconv.UrlAttributes.URL_SCHEME; import static io.opentelemetry.semconv.UserAgentAttributes.USER_AGENT_ORIGINAL; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; import static org.junit.jupiter.api.Named.named; import io.opentelemetry.api.trace.SpanKind; @@ -139,7 +140,12 @@ void basicGetTest(Parameter parameter) { .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( satisfies( - stringKey("spring-webflux.handler.type"), + CODE_FUNCTION, + parameter.annotatedMethod == null + ? val -> val.isEqualTo("handle") + : val -> val.isEqualTo(parameter.annotatedMethod)), + satisfies( + CODE_NAMESPACE, parameter.annotatedMethod == null ? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX) : val -> val.isEqualTo(TestController.class.getName()))); @@ -258,7 +264,12 @@ void getAsyncResponseTest(Parameter parameter) { .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( satisfies( - stringKey("spring-webflux.handler.type"), + CODE_FUNCTION, + parameter.annotatedMethod == null + ? val -> val.isEqualTo("handle") + : val -> val.isEqualTo(parameter.annotatedMethod)), + satisfies( + CODE_NAMESPACE, parameter.annotatedMethod == null ? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX) : val -> val.isEqualTo(TestController.class.getName()))); @@ -364,7 +375,12 @@ void createSpanDuringHandlerFunctionTest(Parameter parameter) { .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( satisfies( - stringKey("spring-webflux.handler.type"), + CODE_FUNCTION, + parameter.annotatedMethod == null + ? val -> val.isEqualTo("handle") + : val -> val.isEqualTo(parameter.annotatedMethod)), + satisfies( + CODE_NAMESPACE, parameter.annotatedMethod == null ? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX) : val -> val.isEqualTo(TestController.class.getName()))); @@ -428,8 +444,9 @@ void get404Test() { .hasStatus(StatusData.error()) .hasEventsSatisfyingExactly(SpringWebfluxTest::resource404Exception) .hasAttributesSatisfyingExactly( + equalTo(CODE_FUNCTION, "handle"), equalTo( - stringKey("spring-webflux.handler.type"), + CODE_NAMESPACE, "org.springframework.web.reactive.resource.ResourceWebHandler")))); } @@ -485,9 +502,8 @@ void basicPostTest() { .hasKind(SpanKind.INTERNAL) .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( - satisfies( - stringKey("spring-webflux.handler.type"), - val -> val.contains(EchoHandlerFunction.class.getName()))), + equalTo(CODE_FUNCTION, "handle"), + equalTo(CODE_NAMESPACE, EchoHandlerFunction.class.getName())), span -> span.hasName("echo").hasParent(trace.getSpan(1)).hasTotalAttributeCount(0))); } @@ -545,7 +561,12 @@ void getToBadEndpointTest(Parameter parameter) { val -> val.isInstanceOf(String.class)))) .hasAttributesSatisfyingExactly( satisfies( - stringKey("spring-webflux.handler.type"), + CODE_FUNCTION, + parameter.annotatedMethod == null + ? val -> val.isEqualTo("handle") + : val -> val.isEqualTo(parameter.annotatedMethod)), + satisfies( + CODE_NAMESPACE, parameter.annotatedMethod == null ? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX) : val -> val.isEqualTo(TestController.class.getName()))); @@ -603,8 +624,9 @@ void redirectTest() { .hasKind(SpanKind.INTERNAL) .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( + equalTo(CODE_FUNCTION, "handle"), satisfies( - stringKey("spring-webflux.handler.type"), + CODE_NAMESPACE, val -> val.startsWith("server.RedirectComponent$$Lambda")))), trace -> trace.hasSpansSatisfyingExactly( @@ -631,8 +653,9 @@ void redirectTest() { span.hasKind(SpanKind.INTERNAL) .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( + equalTo(CODE_FUNCTION, "handle"), satisfies( - stringKey("spring-webflux.handler.type"), + CODE_NAMESPACE, val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX))); })); } @@ -689,7 +712,12 @@ void multipleGetsToDelayingRoute(Parameter parameter) { .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( satisfies( - stringKey("spring-webflux.handler.type"), + CODE_FUNCTION, + parameter.annotatedMethod == null + ? val -> val.isEqualTo("handle") + : val -> val.isEqualTo(parameter.annotatedMethod)), + satisfies( + CODE_NAMESPACE, parameter.annotatedMethod == null ? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX) : val -> val.isEqualTo(TestController.class.getName()))); @@ -760,10 +788,11 @@ void cancelRequestTest() throws Exception { .hasKind(SpanKind.INTERNAL) .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( + equalTo(CODE_FUNCTION, "handle"), satisfies( - stringKey("spring-webflux.handler.type"), - value -> - value.startsWith( + CODE_NAMESPACE, + val -> + val.startsWith( "server.SpringWebFluxTestApplication$$Lambda"))))); SpringWebFluxTestApplication.resumeSlowRequest();