2929import io .micrometer .observation .Observation ;
3030import io .micrometer .observation .ObservationConvention ;
3131import io .micrometer .observation .ObservationRegistry ;
32+ import io .micrometer .observation .ObservationView ;
3233import jakarta .servlet .Filter ;
3334import jakarta .servlet .FilterChain ;
3435import jakarta .servlet .ServletException ;
4647 * wraps the chain in before and after observations
4748 *
4849 * @author Josh Cummings
50+ * @author Nikita Konev
4951 * @since 6.0
5052 */
5153public final class ObservationFilterChainDecorator implements FilterChainProxy .FilterChainDecorator {
@@ -54,6 +56,12 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
5456
5557 private static final String ATTRIBUTE = ObservationFilterChainDecorator .class + ".observation" ;
5658
59+ private static final String ATTRIBUTE_BEFORE_OBSERVATION_VIEW = ObservationFilterChainDecorator .class
60+ + ".observation.view.before" ;
61+
62+ private static final String ATTRIBUTE_AFTER_OBSERVATION_VIEW = ObservationFilterChainDecorator .class
63+ + ".observation.view.after" ;
64+
5765 static final String UNSECURED_OBSERVATION_NAME = "spring.security.http.unsecured.requests" ;
5866
5967 static final String SECURED_OBSERVATION_NAME = "spring.security.http.secured.requests" ;
@@ -250,9 +258,30 @@ private void wrapFilter(ServletRequest request, ServletResponse response, Filter
250258 private AroundFilterObservation parent (HttpServletRequest request ) {
251259 FilterChainObservationContext beforeContext = FilterChainObservationContext .before ();
252260 FilterChainObservationContext afterContext = FilterChainObservationContext .after ();
261+
262+ Object maybeBeforeObservationView = request .getAttribute (ATTRIBUTE_BEFORE_OBSERVATION_VIEW );
263+ if (maybeBeforeObservationView != null ) {
264+ ObservationView observationView = (ObservationView ) maybeBeforeObservationView ;
265+ beforeContext .setParentObservation (observationView );
266+ }
267+
268+ Object maybeAfterObservationView = request .getAttribute (ATTRIBUTE_AFTER_OBSERVATION_VIEW );
269+ if (maybeAfterObservationView != null ) {
270+ ObservationView observationView = (ObservationView ) maybeAfterObservationView ;
271+ afterContext .setParentObservation (observationView );
272+ }
273+
253274 Observation before = Observation .createNotStarted (this .convention , () -> beforeContext , this .registry );
254275 Observation after = Observation .createNotStarted (this .convention , () -> afterContext , this .registry );
255276 AroundFilterObservation parent = AroundFilterObservation .create (before , after );
277+
278+ if (maybeBeforeObservationView == null ) {
279+ request .setAttribute (ATTRIBUTE_BEFORE_OBSERVATION_VIEW , before .getContext ().getParentObservation ());
280+ }
281+ if (maybeAfterObservationView == null ) {
282+ request .setAttribute (ATTRIBUTE_AFTER_OBSERVATION_VIEW , after .getContext ().getParentObservation ());
283+ }
284+
256285 request .setAttribute (ATTRIBUTE , parent );
257286 return parent ;
258287 }
0 commit comments