Report HTTP pattern and handler function name for functional WebFlux routes. (#1513)

This commit is contained in:
Csaba Kos
2020-01-07 10:07:28 -06:00
committed by Marcin Grzejszczak
parent 06cb4d747d
commit 68f720a2e5
2 changed files with 38 additions and 12 deletions

View File

@@ -278,17 +278,13 @@ public final class TraceWebFilter implements WebFilter, Ordered {
}
private void terminateSpan(@Nullable Throwable t) {
String httpRoute = null;
Object attribute = this.exchange
.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE);
if (attribute instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) attribute;
addClassMethodTag(handlerMethod, this.span);
addClassNameTag(handlerMethod, this.span);
Object pattern = this.exchange
.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
httpRoute = pattern != null ? pattern.toString() : "";
}
addClassMethodTag(attribute, this.span);
addClassNameTag(attribute, this.span);
Object pattern = this.exchange
.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
String httpRoute = pattern != null ? pattern.toString() : "";
addResponseTagsForSpanWithoutParent(this.exchange,
this.exchange.getResponse(), this.span);
DecoratedServerHttpResponse delegate = new DecoratedServerHttpResponse(

View File

@@ -44,6 +44,9 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.assertj.core.api.BDDAssertions.then;
@@ -70,11 +73,17 @@ public class TraceWebFluxTests {
clean(accumulator, controller2);
// when
ClientResponse response = whenRequestIsSent(port);
ClientResponse response = whenRequestIsSent(port, "/api/c2/10");
// then
thenSpanWasReportedWithTags(accumulator, response);
clean(accumulator, controller2);
// when
response = whenRequestIsSent(port, "/api/fn/20");
// then
thenFunctionalSpanWasReportedWithTags(accumulator, response);
accumulator.clear();
// when
ClientResponse nonSampledResponse = whenNonSampledRequestIsSent(port);
// then
@@ -108,6 +117,19 @@ public class TraceWebFluxTests {
.containsEntry("mvc.controller.class", "Controller2");
}
private void thenFunctionalSpanWasReportedWithTags(ArrayListSpanReporter accumulator,
ClientResponse response) {
Awaitility.await()
.untilAsserted(() -> then(response.statusCode().value()).isEqualTo(200));
List<zipkin2.Span> spans = accumulator.getSpans().stream()
.filter(span -> "get /api/fn/{id}".equals(span.name()))
.collect(Collectors.toList());
then(spans).hasSize(1);
then(spans.get(0).name()).isEqualTo("get /api/fn/{id}");
then(spans.get(0).tags()).hasEntrySatisfying("mvc.controller.class",
value -> then(value).startsWith("TraceWebFluxTests$Config$$Lambda$"));
}
private void thenNoSpanWasReported(ArrayListSpanReporter accumulator,
ClientResponse response, Controller2 controller2) {
Awaitility.await().untilAsserted(() -> {
@@ -118,9 +140,9 @@ public class TraceWebFluxTests {
then(controller2.span.context().traceIdString()).isEqualTo(EXPECTED_TRACE_ID);
}
private ClientResponse whenRequestIsSent(int port) {
private ClientResponse whenRequestIsSent(int port, String path) {
Mono<ClientResponse> exchange = WebClient.create().get()
.uri("http://localhost:" + port + "/api/c2/10").exchange();
.uri("http://localhost:" + port + path).exchange();
return exchange.block();
}
@@ -172,6 +194,14 @@ public class TraceWebFluxTests {
return new Controller2(tracer);
}
@Bean
RouterFunction<ServerResponse> route() {
return RouterFunctions.route()
.GET("/api/fn/{id}", serverRequest -> ServerResponse.ok()
.bodyValue(serverRequest.pathVariable("id")))
.build();
}
}
@RestController