Merge branch '6.1.x'
This commit is contained in:
@@ -119,13 +119,13 @@ public class ServerHttpObservationFilter extends OncePerRequestFilter {
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
// If async is started, register a listener for completion notification.
|
||||
if (request.isAsyncStarted()) {
|
||||
// If async is started during the first dispatch, register a listener for completion notification.
|
||||
if (request.isAsyncStarted() && request.getDispatcherType() == DispatcherType.REQUEST) {
|
||||
request.getAsyncContext().addListener(new ObservationAsyncListener(observation));
|
||||
}
|
||||
// scope is opened for ASYNC dispatches, but the observation will be closed
|
||||
// by the async listener.
|
||||
else if (request.getDispatcherType() != DispatcherType.ASYNC){
|
||||
else if (!isAsyncDispatch(request)) {
|
||||
Throwable error = fetchException(request);
|
||||
if (error != null) {
|
||||
observation.error(error);
|
||||
@@ -180,6 +180,7 @@ public class ServerHttpObservationFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
public void onStartAsync(AsyncEvent event) {
|
||||
event.getAsyncContext().addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,11 +22,16 @@ import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistryAssert;
|
||||
import jakarta.servlet.AsyncContext;
|
||||
import jakarta.servlet.AsyncEvent;
|
||||
import jakarta.servlet.AsyncListener;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
@@ -149,6 +154,21 @@ class ServerHttpObservationFilterTests {
|
||||
assertThatHttpObservation().hasLowCardinalityKeyValue("outcome", "SUCCESS").hasBeenStopped();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRegisterListenerForAsyncStarts() throws Exception {
|
||||
CustomAsyncFilter customAsyncFilter = new CustomAsyncFilter();
|
||||
this.mockFilterChain = new MockFilterChain(new NoOpServlet(), customAsyncFilter);
|
||||
this.request.setAsyncSupported(true);
|
||||
this.request.setDispatcherType(DispatcherType.REQUEST);
|
||||
this.filter.doFilter(this.request, this.response, this.mockFilterChain);
|
||||
customAsyncFilter.asyncContext.dispatch();
|
||||
this.request.setDispatcherType(DispatcherType.ASYNC);
|
||||
AsyncContext newAsyncContext = this.request.startAsync();
|
||||
newAsyncContext.complete();
|
||||
|
||||
assertThatHttpObservation().hasLowCardinalityKeyValue("outcome", "SUCCESS").hasBeenStopped();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCloseObservationAfterAsyncError() throws Exception {
|
||||
this.request.setAsyncSupported(true);
|
||||
@@ -210,6 +230,29 @@ class ServerHttpObservationFilterTests {
|
||||
Assert.notNull(response, "response must not be null");
|
||||
response.setHeader("X-Trace-Id", "badc0ff33");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
static class NoOpServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class CustomAsyncFilter implements Filter {
|
||||
|
||||
AsyncContext asyncContext;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
this.asyncContext = servletRequest.startAsync();
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ import java.util.TimeZone;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.AsyncContext;
|
||||
import jakarta.servlet.AsyncEvent;
|
||||
import jakarta.servlet.AsyncListener;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.ServletConnection;
|
||||
@@ -920,7 +922,19 @@ public class MockHttpServletRequest implements HttpServletRequest {
|
||||
public AsyncContext startAsync(ServletRequest request, @Nullable ServletResponse response) {
|
||||
Assert.state(this.asyncSupported, "Async not supported");
|
||||
this.asyncStarted = true;
|
||||
this.asyncContext = new MockAsyncContext(request, response);
|
||||
MockAsyncContext newAsyncContext = new MockAsyncContext(request, response);
|
||||
if (this.asyncContext != null) {
|
||||
try {
|
||||
AsyncEvent startEvent = new AsyncEvent(newAsyncContext);
|
||||
for (AsyncListener asyncListener : this.asyncContext.getListeners()) {
|
||||
asyncListener.onStartAsync(startEvent);
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore failures
|
||||
}
|
||||
}
|
||||
this.asyncContext = newAsyncContext;
|
||||
return this.asyncContext;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user