Correctly connect Spring Webflux with Otel and Zipkin

311 Views Asked by At

I have a problem with connecting Zipkin calls between 2 services.

enter image description here

These 2 should be presented as one because order-service call product-service to make a reservation.

My current settings: order-service pom.xml

<!--Tracing-->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-tracing</artifactId>
    </dependency>
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-tracing-bridge-otel</artifactId>
    </dependency>
    <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-exporter-zipkin</artifactId>
    </dependency>

settings:

spring.main.web-application-type=reactive
management.tracing.sampling.probability=1.0
management.tracing.enabled=true
zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans
logging.pattern.level='%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]'

call to product-service:

@Override
public Mono<String> reserveItems(String orderNumber, List<OrderItemRequestDto> orderItems) {
    return webClientBuilder.build().post()
            .uri("http://product-service/api/product/items/reserve")
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON)
            .headers(headers -> headers.setBasicAuth("user", "password"))
            .body(BodyInserters.fromValue(buildBody(orderNumber, orderItems)))
            .retrieve()
            .onStatus(httpStatusCode -> BAD_REQUEST == httpStatusCode, response -> response.bodyToMono(ErrorHandlerResponse.class)
                    .flatMap(errorResponse -> Mono.error(new ApiCallException(errorResponse.getErrorMessage()))))
            .bodyToMono(String.class);
}

configuration of webclient:

@Configuration
public class WebClientConfig {

@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
    return WebClient.builder();
}
}

Product service configuration has the same settings and dependencies as in order-service.

1

There are 1 best solutions below

0
Jonatan Ivanov On

You need to create a WebClient instance from the builder that Spring creates for you, see the docs: https://docs.spring.io/spring-framework/reference/integration/observability.html#observability.http-client.webclient

@Bean
WebClient webClient(WebClient.Builder builder, @Value("${url") String url) {
    return builder.baseUrl(url).build();
}

This also helps for context propagation in the first line of your main method:

Hooks.enableAutomaticContextPropagation();