Search code examples
spring-bootspring-cloud-sleuthmicrometerspring-micrometermicrometer-tracing

Replacing WebFluxSleuthOperators when updating from sleuth to micrometer - Spring boot 3 upgrading


I am inexperienced with Sleuth, so maybe my question is actually pretty self-evident.

We are updating Spring Boot from 2 to 3 and Sleuth does not work with Spring Boot 3. The problem is that we use this class WebFluxSleuthOperators several times and it seems there are no evident candidate for an easy replacement in micrometer library.

Here's my code:

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.cloud.sleuth.CurrentTraceContext
import org.springframework.cloud.sleuth.Tracer
import org.springframework.cloud.sleuth.instrument.web.WebFluxSleuthOperators
import org.springframework.core.Ordered
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebFilter
import org.springframework.web.server.WebFilterChain
import reactor.core.publisher.Mono

@Component
open class SleuthBaggageToResponseHeadersFilter(
    @Autowired private val tracer: Tracer,
    @Autowired private val currentTraceContext: CurrentTraceContext,
) : WebFilter, Ordered {

    override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        exchange.response.beforeCommit {
            Mono.deferContextual { Mono.just(it) }.doOnNext { addToResponseHeaders(exchange) }.then()
        }

        return chain.filter(exchange)
    }

    private fun addToResponseHeaders(exchange: ServerWebExchange) =
        WebFluxSleuthOperators.withSpanInScope(tracer, currentTraceContext, exchange) {
            val requestId = tracer.getBaggage("REQUEST_ID")?.get() ?: "NOT_FOUND"
            exchange.response.headers.remove("REQUEST_ID")
            exchange.response.headers.add("REQUEST_ID", requestId)
        }

    override fun getOrder() = SleuthBaggageDefaultValuesFilter.ORDER + 1
}

What can we use instead for this purpose?

There is a migration guide for this, but I found it to be rather unhelpful for my situation https://github.com/micrometer-metrics/tracing/wiki/Spring-Cloud-Sleuth-3.1-Migration-Guide


Solution

  • Finally found the answer. It is

    observationRegistry.currentObservation?.scoped {}

    Using this, I can access baggages not problem.

    To make it works, I needed to add also this in main application

    Hooks.enableAutomaticContextPropagation()

    I also needed to add the observationRegistry to the WebClient

    return WebClient.builder().exchangeStrategies(exchangeStrategies).baseUrl("/")
        .filter(someFilterFunction).observationRegistry(observationRegistry)
    

    Finally, I replaced the Authenticate WebFilter with a Authentication Converter

    open class SetSecurityDetailsFromTokenConverter(
        @Autowired val securityConfiguration: SecurityConfiguration,
        @Autowired val authenticationFactory: UserClaimAuthenticationFactory,
        @Autowired val authenticationManager: ReactiveAuthenticationManager,
    ) : ServerAuthenticationConverter {
    
        override fun convert(exchange: ServerWebExchange): Mono<Authentication> {
            if (securityConfiguration.isExcluded(exchange.request.path.value())) {
                return Mono.empty()
            }
    
            ...
    
            return authenticationManager.authenticate(userClaimAuthentication).flatMap { Mono.just(userClaimAuthentication) }
        }
    }