Как протестировать распространение traceId с помощью WebTestClient + Micrometer Tracer?
После перехода на Spring Boot 3 и рефакторинга от Sleuth до Micrometer я больше не могу тестировать распространение traceId с помощью WebTestClient + Tracer.
Мой тест здесь состоит в том, чтобы иметь простой @RestController, где я ожидаю, что traceId будет распространяться через Tracer:
@RestController
class MyTraceIdController(@Autowired private val tracer: Tracer) {
@GetMapping("/trace")
fun info(): ResponseEntity<String> {
val traceKey = "x-b3-traceid"
// Using tracer the traceId is retrieved at runtime but not during test
val responseHeaders = HttpHeaders()
responseHeaders.set(traceKey, tracer.currentSpan()?.context()?.traceId().toString())
return ResponseEntity
.ok()
.headers(responseHeaders)
.body("OK")
}
}
И цель — протестировать его благодаря WebTestClient:
@AutoConfigureWebTestClient
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class MyTraceIdTests(@Autowired private val webTestClient: WebTestClient) {
@Test
fun `Assert info endpoint works as expected with webTestClient`() {
val traceKey = "x-b3-traceid"
val traceValue = "463ac35c9f6413ad48485a3953bb6124"
val spanKey = "x-b3-spanid"
val spanValue = "a2fb4a1d1a96d312"
webTestClient.get()
.uri("http://localhost:9080/trace")
.header(traceKey, traceValue)
.header(spanKey, spanValue)
.exchange()
.expectStatus().isOk
.expectHeader().valueEquals(traceKey, traceValue)
.expectBody<String>().isEqualTo("OK")
}
}
В Sleuth при выполнении тестов внедренный BraveTracer отлично справился с заданием по распространению traceId.
С Micrometer я больше не могу вводить один правильный трассировщик для выполнения этой работы.
Чтобы проверить случай, я создал следующий образец:
https://github.com/bvoglette/trace-id-образец
Наблюдаются два поведения:
- Во время выполнения, выполняя bootRun + curl на конечной точке, используется BraveAutoconfiguration и вводится один правильный BraveTracer => Он работает, как и ожидалось.
- Во время тестирования я не могу ввести один правильный компонент BraveTracer => traceId всегда равен нулю
Различные подходы, которые я пробовал безуспешно
- Чтобы использовать SimpleTracer()
- Чтобы реализовать свой собственный компонент Tracer, следуйте документации Micrometer.
- Чтобы использовать BraveAutoconfiguration в моем тесте или создавать экземпляры bean-компонентов на его основе
Ни одна из этих реализаций не смогла создать ни одного bean-компонента, в котором распространяется traceId.
Я ожидаю, что больше людей найдут способ просто внедрить рабочий компонент из BraveAutoconfiguration. Что мне не хватает? Должен ли я сделать свой тест по-другому?
2 ответа
Вам нужно добавить@AutoConfigureObservability
в своем тестовом классе. По умолчанию наблюдаемость отключена в тестах.
Я также переносил свое приложение Spring-Web и Spring-интеграцию с Spring Boot 2 Sleuth на Spring Boot 3 с помощью микрометра и также столкнулся с проблемами. Я хотел настроить трассировку вручную, но у меня не было доступа к актуатору во всех модулях).
Чтобы настроить трассировку вручную, кроме обычных зависимостей микрометра, мне нужно было добавить эти две: micrometer-tracing-test и micrometer-tracing-integration-test (примечание: в большинстве случаев вам, вероятно, понадобится просто micrometer-tracing-test):
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>${micrometer.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>context-propagation</artifactId>
<version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-test</artifactId>
<version>${micrometer.version}</version>
<scope>test</scope> (!)
<exclusions>
<exclusion>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8-standalone</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-integration-test</artifactId>
<version>${micrometer.version}</version>
<scope>test</scope> (!)
<exclusions>
<exclusion>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8-standalone</artifactId>
</exclusion>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
После этого я предоставил bean-компонент SimpleTracer для проверки контекста (который представляет собой реализацию Tracer, предназначенную для тестов) и вручную настроил реестр наблюдений (TestObservationRegistry). Я настроил реестр с обработчиком наблюдения - DefaultTracingObservationHandler, который передает этот тест SimpleTracer:
@Bean
SimpleTracer simpleTracer() {
return new SimpleTracer();
}
@Bean
TestObservationRegistry observationRegistry(SimpleTracer tracer) {
final TestObservationRegistry testObservationRegistry = TestObservationRegistry.create();
testObservationRegistry.observationConfig().observationHandler(new DefaultTracingObservationHandler(tracer));
return testObservationRegistry;
}
ПРИМЕЧАНИЕ. Если в вашем тесте вы получаете исключение, как показано ниже, это значит, что вы не настроили обработчик наблюдения, т. е. ваш реестр наблюдений не содержит обработчик отслеживания наблюдения. В таком случае попробуйте добавить обработчик наблюдения вручную (см. пример выше).
java.lang.IllegalArgumentException: Context does not have an entry for key [class io.micrometer.tracing.handler.TracingObservationHandler$TracingContext]
at io.micrometer.observation.Observation$Context.getRequired(Observation.java:928)
at micrometer.tracing@1.0.2/io.micrometer.tracing.handler.TracingAwareMeterObservationHandler.onStop(TracingAwareMeterObservationHandler.java:79)
at io.micrometer.observation.ObservationHandler$FirstMatchingCompositeObservationHandler.lambda$onStop$7(ObservationHandler.java:173)