Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing trace ID within reactive WebFilter #30470

Closed
chechoochoo opened this issue May 10, 2023 · 4 comments
Closed

Accessing trace ID within reactive WebFilter #30470

chechoochoo opened this issue May 10, 2023 · 4 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: invalid An issue that we don't feel is valid theme: observability An issue related to observability and tracing

Comments

@chechoochoo
Copy link

Affects: 6.0.8 (spring-webflux)


I have a simple filter that should just inject current trace ID to the response:

package some.controller;

import io.micrometer.tracing.Span;
import io.micrometer.tracing.Tracer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
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;

import java.util.UUID;

@Slf4j
@Component
public class AddResponseHeaderWebFilter implements WebFilter, Ordered {

    private final Tracer tracer;

    public AddResponseHeaderWebFilter(
        final Tracer tracer
    ) {
        this.tracer = tracer;
    }

    @SuppressWarnings("NullableProblems")
    @Override
    public Mono<Void> filter(final ServerWebExchange exchange, final WebFilterChain chain) {
        return chain.filter(withCallback(exchange));
    }

    private ServerWebExchange withCallback(final ServerWebExchange exchange) {
        exchange
            .getResponse()
            .beforeCommit(() -> {
                HttpHeaders httpHeaders = exchange.getResponse().getHeaders();

                httpHeaders.add("trace-id", callId());

                return Mono.empty();
            });

        return exchange;
    }

    private static String fallbackValue() {
        String fallbackValue = UUID.randomUUID().toString();
        log.warn("Could not use trace ID; generated dummy UUID for tracking purposes: {}", fallbackValue);

        return fallbackValue;
    }

    private String callId() {
        Span currentSpan = this.tracer.currentSpan();

        return currentSpan == null
            ? fallbackValue()
            : currentSpan.context().traceId();
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

it works well if my controller returns Mono<List> or Mono but always falls into "fallback" when controller returns Flux;

I am not sure if it is a known limitation now, or some additional configuration / code change is needed on my end?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label May 10, 2023
@quaff
Copy link
Contributor

quaff commented May 11, 2023

Have you tried MDC.get("traceId") ?

@chechoochoo
Copy link
Author

chechoochoo commented May 11, 2023

@quaff my filter is based on webflux/reactive stack;

such call to MDC returns the "00000000000000000000000000000000" so the result of https://github.com/open-telemetry/opentelemetry-java/blob/47ee573f07c9025547d494608863d9314b29df4b/api/all/src/main/java/io/opentelemetry/api/trace/TraceId.java#L51


note: I updated issue summary with a note it is on reactive stack

@chechoochoo chechoochoo changed the title Accessing trace ID within WebFilter 🤔 Accessing trace ID within reactive WebFilter 🤔 May 11, 2023
@snicoll snicoll changed the title Accessing trace ID within reactive WebFilter 🤔 Accessing trace ID within reactive WebFilter May 12, 2023
@Storje
Copy link

Storje commented Jun 30, 2023

Same issue for me with Spring Boot 3 (it's ok with Spring Boot 2)
Unable to have a traceId in a webFilter even in logs.

With this attached project , after lauching the test, we can see in the logs that traceId is available only in the REST Controller :

{"@timestamp":"2023-06-30T14:11:37.982Z","level":"INFO","message":"In filter with null","logger_name":"com.example.demo.TestFilter"}
{"@timestamp":"2023-06-30T14:11:38.003338Z","level":"INFO","message":"In ping","logger_name":"com.example.demo.DemoApplication","traceId":"649ee2995bae5e514c22a6bb1283fd1b","spanId":"4c22a6bb1283fd1b"}
{"@timestamp":"2023-06-30T14:11:38.033049Z","level":"INFO","message":"Success","logger_name":"com.example.demo.TestFilter"}
{"@timestamp":"2023-06-30T14:11:38.033174Z","level":"INFO","message":"OnEach","logger_name":"com.example.demo.TestFilter"}

traceIdis not available in logs from the following filter :

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class TestFilter(private val tracer: Tracer): WebFilter {

	private val logger: Logger = LoggerFactory.getLogger(TestFilter::class.java)

	override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {

		val traceId = tracer.currentSpan()?.context()?.traceId()

		logger.info("In filter with $traceId")

		return chain.filter(exchange)
			.doOnSuccess {
				logger.info("Success")
			}
			.doOnEach {
				val context = it.contextView
				// Any way to get the traceId from this context ?
				logger.info("OnEach")
			}


	}

}

As a workaround, is there a way to get the traceId from the reactor context in a filter ?

@bclozel
Copy link
Member

bclozel commented Jul 5, 2023

Running your sample app yields the following for me:

{"@timestamp":"2023-07-05T15:17:22.68438Z","level":"INFO","message":"In filter with null","logger_name":"com.example.demo.TestFilter"}
{"@timestamp":"2023-07-05T15:17:22.721378Z","level":"INFO","message":"In ping","logger_name":"com.example.demo.DemoApplication","traceId":"64a5898227ebba51c3b4e4e50052c59a","spanId":"c3b4e4e50052c59a"}
{"@timestamp":"2023-07-05T15:17:22.73997Z","level":"INFO","message":"Success","logger_name":"com.example.demo.TestFilter","traceId":"64a5898227ebba51c3b4e4e50052c59a","spanId":"c3b4e4e50052c59a"}
{"@timestamp":"2023-07-05T15:17:22.740158Z","level":"INFO","message":"OnEach","logger_name":"com.example.demo.TestFilter","traceId":"64a5898227ebba51c3b4e4e50052c59a","spanId":"c3b4e4e50052c59a"}

Doing the same when the filter is configured at @Order(Ordered.HIGHEST_PRECEDENCE + 2) shows this:

{"@timestamp":"2023-07-05T15:18:18.406686Z","level":"INFO","message":"In filter with 64a589ba88545a7873690cb021cac9a8","logger_name":"com.example.demo.TestFilter","traceId":"64a589ba88545a7873690cb021cac9a8","spanId":"73690cb021cac9a8"}
{"@timestamp":"2023-07-05T15:18:18.423131Z","level":"INFO","message":"In ping","logger_name":"com.example.demo.DemoApplication","traceId":"64a589ba88545a7873690cb021cac9a8","spanId":"73690cb021cac9a8"}
{"@timestamp":"2023-07-05T15:18:18.441259Z","level":"INFO","message":"Success","logger_name":"com.example.demo.TestFilter","traceId":"64a589ba88545a7873690cb021cac9a8","spanId":"73690cb021cac9a8"}
{"@timestamp":"2023-07-05T15:18:18.441434Z","level":"INFO","message":"OnEach","logger_name":"com.example.demo.TestFilter","traceId":"64a589ba88545a7873690cb021cac9a8","spanId":"73690cb021cac9a8"}

This can be explained by the fact that the ServerHttpObservationFilter is ordered at Ordered.HIGHEST_PRECEDENCE + 1. Because of this and other limitations, we've retired the WebFilter in #30013 and there will be a follow up issue in Spring Boot for that.

I'm closing this issue as this was a problem with the ordering of the WebFilter in the application.

@bclozel bclozel closed this as not planned Won't fix, can't repro, duplicate, stale Jul 5, 2023
@bclozel bclozel added in: web Issues in web modules (web, webmvc, webflux, websocket) status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jul 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: invalid An issue that we don't feel is valid theme: observability An issue related to observability and tracing
Projects
None yet
Development

No branches or pull requests

5 participants