Skip to content

Commit ce2ec18

Browse files
cuichenlitrask
andauthored
Add code attributes to spring webflux controller spans and remove spring-webflux.handler.type (#12887)
Co-authored-by: Trask Stalnaker <[email protected]>
1 parent de6e0ef commit ce2ec18

File tree

3 files changed

+59
-21
lines changed

3 files changed

+59
-21
lines changed

instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/HandlerCodeAttributesGetter.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,28 @@
77

88
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter;
99
import javax.annotation.Nullable;
10+
import org.springframework.web.method.HandlerMethod;
1011

1112
public class HandlerCodeAttributesGetter implements CodeAttributesGetter<Object> {
1213
@Nullable
1314
@Override
1415
public Class<?> getCodeClass(Object handler) {
15-
return handler.getClass();
16+
if (handler instanceof HandlerMethod) {
17+
// Special case for requests mapped with annotations
18+
HandlerMethod handlerMethod = (HandlerMethod) handler;
19+
return handlerMethod.getMethod().getDeclaringClass();
20+
} else {
21+
return handler.getClass();
22+
}
1623
}
1724

1825
@Nullable
1926
@Override
2027
public String getMethodName(Object handler) {
28+
if (handler instanceof HandlerMethod) {
29+
HandlerMethod handlerMethod = (HandlerMethod) handler;
30+
return handlerMethod.getMethod().getName();
31+
}
2132
return "handle";
2233
}
2334
}

instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/WebfluxSingletons.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server;
77

88
import io.opentelemetry.api.GlobalOpenTelemetry;
9+
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor;
910
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
1011
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1112
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteGetter;
1213
import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig;
13-
import io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.SpringWebfluxConfig;
1414
import org.springframework.web.reactive.HandlerMapping;
1515
import org.springframework.web.server.ServerWebExchange;
1616
import org.springframework.web.util.pattern.PathPattern;
@@ -25,13 +25,11 @@ public final class WebfluxSingletons {
2525
Instrumenter.builder(
2626
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, new WebfluxSpanNameExtractor());
2727

28-
if (SpringWebfluxConfig.captureExperimentalSpanAttributes()) {
29-
builder.addAttributesExtractor(new ExperimentalAttributesExtractor());
30-
}
31-
3228
INSTRUMENTER =
3329
builder
3430
.setEnabled(ExperimentalConfig.get().controllerTelemetryEnabled())
31+
.addAttributesExtractor(
32+
CodeAttributesExtractor.create(new HandlerCodeAttributesGetter()))
3533
.buildInstrumenter();
3634
}
3735

instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java

+44-15
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server;
77

8-
import static io.opentelemetry.api.common.AttributeKey.stringKey;
98
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
109
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
1110
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
@@ -25,6 +24,8 @@
2524
import static io.opentelemetry.semconv.UrlAttributes.URL_PATH;
2625
import static io.opentelemetry.semconv.UrlAttributes.URL_SCHEME;
2726
import static io.opentelemetry.semconv.UserAgentAttributes.USER_AGENT_ORIGINAL;
27+
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION;
28+
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE;
2829
import static org.junit.jupiter.api.Named.named;
2930

3031
import io.opentelemetry.api.trace.SpanKind;
@@ -139,7 +140,12 @@ void basicGetTest(Parameter parameter) {
139140
.hasParent(trace.getSpan(0))
140141
.hasAttributesSatisfyingExactly(
141142
satisfies(
142-
stringKey("spring-webflux.handler.type"),
143+
CODE_FUNCTION,
144+
parameter.annotatedMethod == null
145+
? val -> val.isEqualTo("handle")
146+
: val -> val.isEqualTo(parameter.annotatedMethod)),
147+
satisfies(
148+
CODE_NAMESPACE,
143149
parameter.annotatedMethod == null
144150
? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX)
145151
: val -> val.isEqualTo(TestController.class.getName())));
@@ -258,7 +264,12 @@ void getAsyncResponseTest(Parameter parameter) {
258264
.hasParent(trace.getSpan(0))
259265
.hasAttributesSatisfyingExactly(
260266
satisfies(
261-
stringKey("spring-webflux.handler.type"),
267+
CODE_FUNCTION,
268+
parameter.annotatedMethod == null
269+
? val -> val.isEqualTo("handle")
270+
: val -> val.isEqualTo(parameter.annotatedMethod)),
271+
satisfies(
272+
CODE_NAMESPACE,
262273
parameter.annotatedMethod == null
263274
? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX)
264275
: val -> val.isEqualTo(TestController.class.getName())));
@@ -364,7 +375,12 @@ void createSpanDuringHandlerFunctionTest(Parameter parameter) {
364375
.hasParent(trace.getSpan(0))
365376
.hasAttributesSatisfyingExactly(
366377
satisfies(
367-
stringKey("spring-webflux.handler.type"),
378+
CODE_FUNCTION,
379+
parameter.annotatedMethod == null
380+
? val -> val.isEqualTo("handle")
381+
: val -> val.isEqualTo(parameter.annotatedMethod)),
382+
satisfies(
383+
CODE_NAMESPACE,
368384
parameter.annotatedMethod == null
369385
? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX)
370386
: val -> val.isEqualTo(TestController.class.getName())));
@@ -428,8 +444,9 @@ void get404Test() {
428444
.hasStatus(StatusData.error())
429445
.hasEventsSatisfyingExactly(SpringWebfluxTest::resource404Exception)
430446
.hasAttributesSatisfyingExactly(
447+
equalTo(CODE_FUNCTION, "handle"),
431448
equalTo(
432-
stringKey("spring-webflux.handler.type"),
449+
CODE_NAMESPACE,
433450
"org.springframework.web.reactive.resource.ResourceWebHandler"))));
434451
}
435452

@@ -485,9 +502,8 @@ void basicPostTest() {
485502
.hasKind(SpanKind.INTERNAL)
486503
.hasParent(trace.getSpan(0))
487504
.hasAttributesSatisfyingExactly(
488-
satisfies(
489-
stringKey("spring-webflux.handler.type"),
490-
val -> val.contains(EchoHandlerFunction.class.getName()))),
505+
equalTo(CODE_FUNCTION, "handle"),
506+
equalTo(CODE_NAMESPACE, EchoHandlerFunction.class.getName())),
491507
span ->
492508
span.hasName("echo").hasParent(trace.getSpan(1)).hasTotalAttributeCount(0)));
493509
}
@@ -545,7 +561,12 @@ void getToBadEndpointTest(Parameter parameter) {
545561
val -> val.isInstanceOf(String.class))))
546562
.hasAttributesSatisfyingExactly(
547563
satisfies(
548-
stringKey("spring-webflux.handler.type"),
564+
CODE_FUNCTION,
565+
parameter.annotatedMethod == null
566+
? val -> val.isEqualTo("handle")
567+
: val -> val.isEqualTo(parameter.annotatedMethod)),
568+
satisfies(
569+
CODE_NAMESPACE,
549570
parameter.annotatedMethod == null
550571
? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX)
551572
: val -> val.isEqualTo(TestController.class.getName())));
@@ -603,8 +624,9 @@ void redirectTest() {
603624
.hasKind(SpanKind.INTERNAL)
604625
.hasParent(trace.getSpan(0))
605626
.hasAttributesSatisfyingExactly(
627+
equalTo(CODE_FUNCTION, "handle"),
606628
satisfies(
607-
stringKey("spring-webflux.handler.type"),
629+
CODE_NAMESPACE,
608630
val -> val.startsWith("server.RedirectComponent$$Lambda")))),
609631
trace ->
610632
trace.hasSpansSatisfyingExactly(
@@ -631,8 +653,9 @@ void redirectTest() {
631653
span.hasKind(SpanKind.INTERNAL)
632654
.hasParent(trace.getSpan(0))
633655
.hasAttributesSatisfyingExactly(
656+
equalTo(CODE_FUNCTION, "handle"),
634657
satisfies(
635-
stringKey("spring-webflux.handler.type"),
658+
CODE_NAMESPACE,
636659
val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX)));
637660
}));
638661
}
@@ -689,7 +712,12 @@ void multipleGetsToDelayingRoute(Parameter parameter) {
689712
.hasParent(trace.getSpan(0))
690713
.hasAttributesSatisfyingExactly(
691714
satisfies(
692-
stringKey("spring-webflux.handler.type"),
715+
CODE_FUNCTION,
716+
parameter.annotatedMethod == null
717+
? val -> val.isEqualTo("handle")
718+
: val -> val.isEqualTo(parameter.annotatedMethod)),
719+
satisfies(
720+
CODE_NAMESPACE,
693721
parameter.annotatedMethod == null
694722
? val -> val.contains(INNER_HANDLER_FUNCTION_CLASS_TAG_PREFIX)
695723
: val -> val.isEqualTo(TestController.class.getName())));
@@ -760,10 +788,11 @@ void cancelRequestTest() throws Exception {
760788
.hasKind(SpanKind.INTERNAL)
761789
.hasParent(trace.getSpan(0))
762790
.hasAttributesSatisfyingExactly(
791+
equalTo(CODE_FUNCTION, "handle"),
763792
satisfies(
764-
stringKey("spring-webflux.handler.type"),
765-
value ->
766-
value.startsWith(
793+
CODE_NAMESPACE,
794+
val ->
795+
val.startsWith(
767796
"server.SpringWebFluxTestApplication$$Lambda")))));
768797

769798
SpringWebFluxTestApplication.resumeSlowRequest();

0 commit comments

Comments
 (0)