Skip to content

Tracing propagation does not work in ControllerAdvice with async controllers since 3.2.7 #41266

Not planned
@raczynsm

Description

@raczynsm

In my application I have async controllers and ControllerAdvice with exceptions handling.
Tracing propagation was working until I upgraded from 3.2.6 to 3.2.7.
I use below dependencies:

implementation("org.springframework.boot:spring-boot-starter-web")
implementation("io.micrometer:micrometer-tracing-bridge-brave")

This is minimal reproduction for the issue:

  • main class:
package com.example.tracing

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.scheduling.annotation.EnableAsync

@SpringBootApplication
@EnableAsync
class TracingApplication

fun main(args: Array<String>) {
	runApplication<TracingApplication>(*args)
}

  • async controller with controller advice:
package com.example.tracing

import io.micrometer.context.ContextExecutorService
import io.micrometer.context.ContextSnapshotFactory
import io.micrometer.tracing.Tracer
import org.springframework.context.annotation.Configuration
import org.springframework.http.ResponseEntity
import org.springframework.scheduling.annotation.Async
import org.springframework.scheduling.annotation.AsyncConfigurer
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody
import org.springframework.web.context.request.WebRequest
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors


@Controller
class WebController(
    val tracer : Tracer
) {

    @Async
    @GetMapping(path = ["/hello"], produces = ["text/plain"])
    @ResponseBody
    fun hello() : CompletableFuture<String> {
        val traceId = tracer.currentSpan()?.context()?.traceId()
        println("TRACING in Controller: $traceId")
        return CompletableFuture.completedFuture("Hello with [${traceId}]\n")
    }

    @Async
    @GetMapping(path = ["/fail"], produces = ["text/plain"])
    @ResponseBody
    fun fail() : CompletableFuture<String> {
        val traceId = tracer.currentSpan()?.context()?.traceId()
        println("TRACING in Controller: $traceId")
        throw IllegalStateException()
    }
}

@ControllerAdvice
class MyErrorHandler(
    val tracer : Tracer
) {

    @ExceptionHandler(value = [IllegalStateException::class])
    protected fun handleException(ex: RuntimeException, request: WebRequest): ResponseEntity<String> {
        val traceId = tracer.currentSpan()?.context()?.traceId()
        println("TRACING in ErrorHandler: $traceId")
        return ResponseEntity.ok("FAILURE with [$traceId]\n")
    }
}

@Configuration
internal class AsyncContextPropagationConfig : AsyncConfigurer {
    override fun getAsyncExecutor() = ContextExecutorService.wrap(executor) {
        contextSnapshotFactory.captureAll()
    }

    companion object {
        val executor: ExecutorService = Executors.newCachedThreadPool()
        val contextSnapshotFactory = ContextSnapshotFactory.builder()
            .build()
    }
}

Since 3.2.7 curl http://localhost:8080/fail returns:

FAILURE with [null]

before 3.2.7 there was a traceId:

FAILURE with [667e86d51406d20c273b9f4e8a9bc9a5]

Activity

bclozel

bclozel commented on Jun 28, 2024

@bclozel
Member
added
for: external-projectFor an external project and not something we can fix
and removed on Jun 28, 2024
raczynsm

raczynsm commented on Jun 28, 2024

@raczynsm
Author

@bclozel I am not sure if this is exactly the same issue as the other one mentioned regression between 3.3.0 and 3.3.1 and in my case the regression is between 3.2.6 and 3.2.7

wilkinsona

wilkinsona commented on Jun 28, 2024

@wilkinsona
Member

Spring Boot 3.2.7 and 3.3.1 both contain the same Spring Framework upgrade so they're both affected by spring-projects/spring-framework#32730.

bclozel

bclozel commented on Jun 28, 2024

@bclozel
Member

Apologies if this was closed as a duplicate too quickly.
I assumed that this was a duplicate of spring-projects/spring-framework#33091 because both Spring Boot 3.2.7 and 3.3.1 upgraded to Spring Framework 6.1.9 (see #41019 and #41034).

Can you confirm you can reproduce the problem even after downgrading your application to Spring Framework 6.1.8?
You can use the following for Gradle:

ext['spring-framework.version'] = "6.1.8"

If you cannot reproduce the problem after the downgrade, this means that the problem is in Spring Framework directly and that it is most likely linked to spring-projects/spring-framework#32730.

added and removed
for: external-projectFor an external project and not something we can fix
on Jun 28, 2024
self-assigned this
on Jun 28, 2024
raczynsm

raczynsm commented on Jun 28, 2024

@raczynsm
Author

I cannot reproduce after downgrading this dependency to implementation("org.springframework:spring-web:6.1.8")

bclozel

bclozel commented on Jun 28, 2024

@bclozel
Member

Thanks for letting me know. I'll close this one as a duplicate then. Please follow spring-projects/spring-framework#33091 if you'd like to test the fix once it's in SNAPSHOTs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

for: external-projectFor an external project and not something we can fixstatus: duplicateA duplicate of another issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @bclozel@wilkinsona@spring-projects-issues@raczynsm

      Issue actions

        Tracing propagation does not work in ControllerAdvice with async controllers since 3.2.7 · Issue #41266 · spring-projects/spring-boot