diff --git a/docs/src/main/asciidoc/howto.adoc b/docs/src/main/asciidoc/howto.adoc index ae3b9c206..ee9b35c13 100644 --- a/docs/src/main/asciidoc/howto.adoc +++ b/docs/src/main/asciidoc/howto.adoc @@ -368,30 +368,46 @@ class MyService { [[how-to-add-headers-to-the-http-server-response]] == How to Add Headers to the HTTP Server Response? -Register a bean of `HttpResponseParser` type whose name is `HttpServerResponseParser.NAME`. +Register an HTTP Filter that ==== [source,java,indent=0] ---- -import org.springframework.cloud.sleuth.http.HttpResponseParser; -import org.springframework.cloud.sleuth.instrument.web.HttpServerResponseParser; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Tracer; + +import javax.servlet.Filter; +import org.springframework.web.server.WebFilter; @Configuration(proxyBeanMethods = false) class MyConfig { - @Bean(name = HttpServerResponseParser.NAME) - HttpResponseParser myHttpResponseParser() { - return (response, context, span) -> { - Object unwrap = response.unwrap(); - if (unwrap instanceof HttpServletResponse) { - HttpServletResponse resp = (HttpServletResponse) unwrap; - resp.addHeader("MyCustom", "Header"); - } - }; - } + // Example of a servlet Filter for non-reactive applications + @Bean + Filter traceIdInResponseFilter(Tracer tracer) { + return (request, response, chain) -> { + Span currentSpan = tracer.currentSpan(); + if (currentSpan != null) { + HttpServletResponse resp = (HttpServletResponse) response; + // putting trace id value in [mytraceid] response header + resp.addHeader("mytraceid", currentSpan.context().traceId()); + } + chain.doFilter(request, response); + }; + } + // Example of a reactive WebFilter for reactive applications + @Bean + WebFilter traceIdInResponseFilter(Tracer tracer) { + return (exchange, chain) -> { + Span currentSpan = tracer.currentSpan(); + if (currentSpan != null) { + // putting trace id value in [mytraceid] response header + exchange.getResponse().getHeaders().add("mytraceid", currentSpan.context().traceId()); + } + return chain.filter(exchange); + }; + } } ---- diff --git a/tests/brave/spring-cloud-sleuth-instrumentation-webflux-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceWebFluxTests.java b/tests/brave/spring-cloud-sleuth-instrumentation-webflux-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceWebFluxTests.java index 294c0e700..8735e8655 100644 --- a/tests/brave/spring-cloud-sleuth-instrumentation-webflux-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceWebFluxTests.java +++ b/tests/brave/spring-cloud-sleuth-instrumentation-webflux-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceWebFluxTests.java @@ -44,6 +44,7 @@ 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 org.springframework.web.server.WebFilter; import static org.assertj.core.api.BDDAssertions.then; @@ -69,6 +70,8 @@ public class TraceWebFluxTests { ClientResponse response = whenRequestIsSent(port, "/api/c2/10"); // then thenSpanWasReportedWithTags(spans, response); + // then #2002 + then(response.headers().header("mytraceid")).isNotEmpty(); clean(spans, controller2); // when @@ -213,6 +216,17 @@ public class TraceWebFluxTests { serverRequest -> ServerResponse.ok().bodyValue(serverRequest.pathVariable("id"))).build(); } + @Bean + WebFilter traceIdInResponseFilter(Tracer tracer) { + return (exchange, chain) -> { + Span currentSpan = tracer.currentSpan(); + if (currentSpan != null) { + exchange.getResponse().getHeaders().add("mytraceid", currentSpan.context().traceIdString()); + } + return chain.filter(exchange); + }; + } + } @RestController diff --git a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpServerParserTests.java b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpServerParserTests.java index 49e5c5abe..239bab872 100644 --- a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpServerParserTests.java +++ b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpServerParserTests.java @@ -19,6 +19,7 @@ package org.springframework.cloud.sleuth.instrument.web; import java.util.Map; import java.util.stream.Collectors; +import javax.servlet.Filter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -40,6 +41,7 @@ import org.springframework.cloud.sleuth.test.TestSpanHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -72,8 +74,11 @@ public abstract class HttpServerParserTests { @Test public void should_set_tags_via_server_parsers() { - BDDAssertions.then(new RestTemplate().getForObject("http://localhost:" + this.port + "/hello", String.class)) - .isEqualTo("hello"); + ResponseEntity entity = new RestTemplate().getForEntity("http://localhost:" + this.port + "/hello", + String.class); + + BDDAssertions.then(entity.getBody()).isEqualTo("hello"); + BDDAssertions.then(entity.getHeaders()).containsKey("mytraceid"); Awaitility.await() .untilAsserted(() -> then(serverSideTags()).containsEntry("ServerRequest", "Tag") @@ -151,6 +156,18 @@ public abstract class HttpServerParserTests { }; } + @Bean + Filter traceIdInResponseFilter(Tracer tracer) { + return (request, response, chain) -> { + Span currentSpan = tracer.currentSpan(); + if (currentSpan != null) { + HttpServletResponse resp = (HttpServletResponse) response; + resp.addHeader("mytraceid", currentSpan.context().traceId()); + } + chain.doFilter(request, response); + }; + } + } // end::server_parser_config[]