Add status and error messages to /trace
[Fixes #57949108] [bs-323] Make sure /trace shows error responses
This commit is contained in:
parent
1bdb2ce1c2
commit
f7fa63bcb4
|
|
@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.boot.actuate.trace.WebRequestTraceFilter;
|
||||
import org.springframework.boot.actuate.web.BasicErrorController;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
|
|
@ -42,6 +43,9 @@ public class TraceWebFilterAutoConfiguration {
|
|||
@Autowired
|
||||
private TraceRepository traceRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
private BasicErrorController errorController;
|
||||
|
||||
@Value("${management.dump_requests:false}")
|
||||
private boolean dumpRequests;
|
||||
|
||||
|
|
@ -49,6 +53,9 @@ public class TraceWebFilterAutoConfiguration {
|
|||
public WebRequestTraceFilter webRequestLoggingFilter(BeanFactory beanFactory) {
|
||||
WebRequestTraceFilter filter = new WebRequestTraceFilter(this.traceRepository);
|
||||
filter.setDumpRequests(this.dumpRequests);
|
||||
if (this.errorController != null) {
|
||||
filter.setErrorController(this.errorController);
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.actuate.web.BasicErrorController;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
|
@ -56,6 +57,8 @@ public class WebRequestTraceFilter implements Filter, Ordered {
|
|||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private BasicErrorController errorController;
|
||||
|
||||
/**
|
||||
* @param traceRepository
|
||||
*/
|
||||
|
|
@ -122,6 +125,7 @@ public class WebRequestTraceFilter implements Filter, Ordered {
|
|||
String value = response.getHeader(header);
|
||||
headers.put(header, value);
|
||||
}
|
||||
headers.put("status", "" + response.getStatus());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> allHeaders = (Map<String, Object>) trace.get("headers");
|
||||
allHeaders.put("response", headers);
|
||||
|
|
@ -151,6 +155,13 @@ public class WebRequestTraceFilter implements Filter, Ordered {
|
|||
trace.put("method", request.getMethod());
|
||||
trace.put("path", request.getRequestURI());
|
||||
trace.put("headers", allHeaders);
|
||||
Throwable error = (Throwable) request
|
||||
.getAttribute("javax.servlet.error.exception");
|
||||
if (error != null) {
|
||||
if (this.errorController != null) {
|
||||
trace.put("error", this.errorController.error(request));
|
||||
}
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
|
|
@ -162,4 +173,8 @@ public class WebRequestTraceFilter implements Filter, Ordered {
|
|||
public void destroy() {
|
||||
}
|
||||
|
||||
public void setErrorController(BasicErrorController errorController) {
|
||||
this.errorController = errorController;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.actuate.trace;
|
|||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.web.BasicErrorController;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
|
|
@ -55,6 +56,38 @@ public class WebRequestTraceFilterTests {
|
|||
this.filter.enhanceTrace(trace, response);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) trace.get("headers");
|
||||
assertEquals("{Content-Type=application/json}", map.get("response").toString());
|
||||
assertEquals("{Content-Type=application/json, status=200}", map.get("response")
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHasResponseStatus() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.setStatus(404);
|
||||
response.addHeader("Content-Type", "application/json");
|
||||
Map<String, Object> trace = this.filter.getTrace(request);
|
||||
this.filter.enhanceTrace(trace, response);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) ((Map<String, Object>) trace
|
||||
.get("headers")).get("response");
|
||||
assertEquals("404", map.get("status").toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHasError() {
|
||||
this.filter.setErrorController(new BasicErrorController());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.setStatus(500);
|
||||
request.setAttribute("javax.servlet.error.exception", new IllegalStateException(
|
||||
"Foo"));
|
||||
response.addHeader("Content-Type", "application/json");
|
||||
Map<String, Object> trace = this.filter.getTrace(request);
|
||||
this.filter.enhanceTrace(trace, response);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) trace.get("error");
|
||||
System.err.println(map);
|
||||
assertEquals("Foo", map.get("message").toString());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
package org.springframework.boot.sample.ops;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -43,10 +47,6 @@ import org.springframework.security.crypto.codec.Base64;
|
|||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Basic integration tests for service demo application.
|
||||
*
|
||||
|
|
@ -134,13 +134,27 @@ public class SampleActuatorApplicationTests {
|
|||
|
||||
@Test
|
||||
public void testErrorPage() throws Exception {
|
||||
ResponseEntity<String> entity = getRestTemplate().getForEntity(
|
||||
"http://localhost:8080/health", String.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertEquals("ok", entity.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrace() throws Exception {
|
||||
getRestTemplate().getForEntity(
|
||||
"http://localhost:8080/health", String.class);
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = getRestTemplate("user", getPassword()).getForEntity(
|
||||
"http://localhost:8080/foo", Map.class);
|
||||
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode());
|
||||
ResponseEntity<List> entity = getRestTemplate("user", getPassword()).getForEntity(
|
||||
"http://localhost:8080/trace", List.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> body = entity.getBody();
|
||||
assertEquals(500, body.get("status"));
|
||||
List<Map<String,Object>> list = (List<Map<String, Object>>) entity.getBody();
|
||||
Map<String, Object> trace = list.get(list.size()-1);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) ((Map<String, Object>) ((Map<String, Object>)
|
||||
trace.get("info")).get("headers")).get("response");
|
||||
assertEquals("200", map.get("status"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue