I try to propagate the trace Id between micro service calls. It does not seem the RestTemplate propagates the traceId, even though I am using RestTemplateBuilder and have actuator and a tracing bridge in the classpath.
I am running on Spring Boot 3.3.3 and Java 17. here the pom.xml:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.test</groupId><artifactId>tracepropagation</artifactId><version>0.0.1-SNAPSHOT</version><name>tracepropagation</name><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing-bridge-otel</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
This is my RestTemplate config
@Configuration@EnableConfigurationProperties(AppProperties.class)public class AppConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); }}
I test with a simple request forward to the same service using the rest template:
@RestController@AllArgsConstructor@Slf4jpublic class AppController { private final RestTemplate restTemplate; private final AppProperties props; @GetMapping(path = "/forward") public String forward() { log.info("forward endpoint entered"); return this.restTemplate.getForObject("http://localhost:" + props.getPort() +"/hello", String.class); } @GetMapping(path = "/hello") public String hello(){ log.info("hello endpoint entered"); return "hello"; }}
I wrote a test case, which expects the same trace Id in the log from the /forward endpoint and the log in the /hello endpoint:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)class TracepropagationApplicationTests { @LocalServerPort private int port; @Autowired private AppProperties props; @Autowired private TestRestTemplate restTemplate; @Captor ArgumentCaptor<ILoggingEvent> logCaptor; @Mock private Appender<ILoggingEvent> mockAppender; @BeforeEach void beforeEach(){ final Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); when(this.mockAppender.getName()).thenReturn("MOCK"); root.addAppender(this.mockAppender); root.setLevel(Level.INFO); doNothing().when(mockAppender).doAppend(logCaptor.capture()); } @Test void testTraceIdPropagation() { props.setPort(port); assertThat(restTemplate.getForObject("http://localhost:" + port +"/forward", String.class)).isEqualTo("hello"); String firstLogTraceId = this.getLogTraceId("forward endpoint entered"); String secondLogTraceId = this.getLogTraceId("hello endpoint entered"); assertThat(firstLogTraceId).isEqualTo(secondLogTraceId); } private String getLogTraceId(String logMessage) { var traceOptional = logCaptor.getAllValues().stream().filter(e -> e.getFormattedMessage().contains(logMessage)) .findAny() .map(ILoggingEvent::getMDCPropertyMap) .map(m -> m.get("traceId")); assertThat(traceOptional).isPresent(); return traceOptional.get(); }}
However, this test case fails. From what I read in the documentation, the auto configuration should work, if I use the RestTemplateBuilder autowired from Spring Boot.
It does not seem to propagate the trace Id though.
thx in advance!
Here also the AppProperties class just to be complete:
@ConfigurationProperties(prefix = "com.test")@Datapublic class AppProperties { private int port;}