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