@@ -314,6 +314,65 @@ public void doFilterWhenMatchesThenObservationRegistryObserves() throws Exceptio
314314 assertFilterChainObservation (contexts .next (), "after" , 1 );
315315 }
316316
317+ // gh-12610
318+ @ Test
319+ void parentObservationIsTakenIntoAccountDuringDispatchError () throws Exception {
320+ ObservationHandler <Observation .Context > handler = mock (ObservationHandler .class );
321+ given (handler .supportsContext (any ())).willReturn (true );
322+ ObservationRegistry registry = ObservationRegistry .create ();
323+ registry .observationConfig ().observationHandler (handler );
324+
325+ given (this .matcher .matches (any ())).willReturn (true );
326+ SecurityFilterChain sec = new DefaultSecurityFilterChain (this .matcher , Arrays .asList (this .filter ));
327+ FilterChainProxy fcp = new FilterChainProxy (sec );
328+ fcp .setFilterChainDecorator (new ObservationFilterChainDecorator (registry ));
329+ Filter initialFilter = ObservationFilterChainDecorator .FilterObservation
330+ .create (Observation .createNotStarted ("wrap" , registry ))
331+ .wrap (fcp );
332+
333+ ServletRequest initialRequest = new MockHttpServletRequest ("GET" , "/" );
334+ initialFilter .doFilter (initialRequest , new MockHttpServletResponse (), this .chain );
335+
336+ // simulate request attribute copying in case dispatching to ERROR
337+ ObservationFilterChainDecorator .AroundFilterObservation parentObservation = (ObservationFilterChainDecorator .AroundFilterObservation ) initialRequest
338+ .getAttribute (ObservationFilterChainDecorator .ATTRIBUTE );
339+ assertThat (parentObservation ).isNotNull ();
340+
341+ // simulate dispatching error-related request
342+ Filter errorRelatedFilter = ObservationFilterChainDecorator .FilterObservation
343+ .create (Observation .createNotStarted ("wrap" , registry ))
344+ .wrap (fcp );
345+ ServletRequest errorRelatedRequest = new MockHttpServletRequest ("GET" , "/error" );
346+ errorRelatedRequest .setAttribute (ObservationFilterChainDecorator .ATTRIBUTE , parentObservation );
347+ errorRelatedFilter .doFilter (errorRelatedRequest , new MockHttpServletResponse (), this .chain );
348+
349+ ArgumentCaptor <Observation .Context > captor = ArgumentCaptor .forClass (Observation .Context .class );
350+ verify (handler , times (8 )).onStart (captor .capture ());
351+ verify (handler , times (8 )).onStop (any ());
352+ List <Observation .Context > contexts = captor .getAllValues ();
353+
354+ Observation .Context initialRequestObservationContextBefore = contexts .get (1 );
355+ Observation .Context initialRequestObservationContextAfter = contexts .get (3 );
356+ assertFilterChainObservation (initialRequestObservationContextBefore , "before" , 1 );
357+ assertFilterChainObservation (initialRequestObservationContextAfter , "after" , 1 );
358+
359+ assertThat (initialRequestObservationContextBefore .getParentObservation ()).isNotNull ();
360+ assertThat (initialRequestObservationContextBefore .getParentObservation ())
361+ .isSameAs (initialRequestObservationContextAfter .getParentObservation ());
362+
363+ Observation .Context errorRelatedRequestObservationContextBefore = contexts .get (5 );
364+ Observation .Context errorRelatedRequestObservationContextAfter = contexts .get (7 );
365+ assertFilterChainObservation (errorRelatedRequestObservationContextBefore , "before" , 1 );
366+ assertFilterChainObservation (errorRelatedRequestObservationContextAfter , "after" , 1 );
367+
368+ assertThat (errorRelatedRequestObservationContextBefore .getParentObservation ()).isNotNull ();
369+ assertThat (errorRelatedRequestObservationContextBefore .getParentObservation ())
370+ .isSameAs (initialRequestObservationContextBefore .getParentObservation ());
371+ assertThat (errorRelatedRequestObservationContextAfter .getParentObservation ()).isNotNull ();
372+ assertThat (errorRelatedRequestObservationContextAfter .getParentObservation ())
373+ .isSameAs (initialRequestObservationContextBefore .getParentObservation ());
374+ }
375+
317376 @ Test
318377 public void doFilterWhenMultipleFiltersThenObservationRegistryObserves () throws Exception {
319378 ObservationHandler <Observation .Context > handler = mock (ObservationHandler .class );
0 commit comments