From 3a3fd9fcbef530f7fb5e114103378fac7d724511 Mon Sep 17 00:00:00 2001 From: Nikita Konev Date: Sun, 18 May 2025 15:57:28 +0300 Subject: [PATCH] Fix traceId discrepancy in case error in servlet web Signed-off-by: Nikita Konev --- .../web/ObservationFilterChainDecorator.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/web/src/main/java/org/springframework/security/web/ObservationFilterChainDecorator.java b/web/src/main/java/org/springframework/security/web/ObservationFilterChainDecorator.java index ed24f19f910..c6ca9b7679d 100644 --- a/web/src/main/java/org/springframework/security/web/ObservationFilterChainDecorator.java +++ b/web/src/main/java/org/springframework/security/web/ObservationFilterChainDecorator.java @@ -29,6 +29,7 @@ import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationConvention; import io.micrometer.observation.ObservationRegistry; +import io.micrometer.observation.ObservationView; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -46,6 +47,7 @@ * wraps the chain in before and after observations * * @author Josh Cummings + * @author Nikita Konev * @since 6.0 */ public final class ObservationFilterChainDecorator implements FilterChainProxy.FilterChainDecorator { @@ -54,6 +56,12 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F private static final String ATTRIBUTE = ObservationFilterChainDecorator.class + ".observation"; + private static final String ATTRIBUTE_BEFORE_OBSERVATION_VIEW = ObservationFilterChainDecorator.class + + ".observation.view.before"; + + private static final String ATTRIBUTE_AFTER_OBSERVATION_VIEW = ObservationFilterChainDecorator.class + + ".observation.view.after"; + static final String UNSECURED_OBSERVATION_NAME = "spring.security.http.unsecured.requests"; static final String SECURED_OBSERVATION_NAME = "spring.security.http.secured.requests"; @@ -250,9 +258,30 @@ private void wrapFilter(ServletRequest request, ServletResponse response, Filter private AroundFilterObservation parent(HttpServletRequest request) { FilterChainObservationContext beforeContext = FilterChainObservationContext.before(); FilterChainObservationContext afterContext = FilterChainObservationContext.after(); + + Object maybeBeforeObservationView = request.getAttribute(ATTRIBUTE_BEFORE_OBSERVATION_VIEW); + if (maybeBeforeObservationView != null) { + ObservationView observationView = (ObservationView) maybeBeforeObservationView; + beforeContext.setParentObservation(observationView); + } + + Object maybeAfterObservationView = request.getAttribute(ATTRIBUTE_AFTER_OBSERVATION_VIEW); + if (maybeAfterObservationView != null) { + ObservationView observationView = (ObservationView) maybeAfterObservationView; + afterContext.setParentObservation(observationView); + } + Observation before = Observation.createNotStarted(this.convention, () -> beforeContext, this.registry); Observation after = Observation.createNotStarted(this.convention, () -> afterContext, this.registry); AroundFilterObservation parent = AroundFilterObservation.create(before, after); + + if (maybeBeforeObservationView == null) { + request.setAttribute(ATTRIBUTE_BEFORE_OBSERVATION_VIEW, before.getContext().getParentObservation()); + } + if (maybeAfterObservationView == null) { + request.setAttribute(ATTRIBUTE_AFTER_OBSERVATION_VIEW, after.getContext().getParentObservation()); + } + request.setAttribute(ATTRIBUTE, parent); return parent; }