Merge branch '1.1.x'

This commit is contained in:
Dave Syer 2014-08-05 07:56:55 -07:00
commit 1e51c5db15
2 changed files with 92 additions and 1 deletions

View File

@ -37,8 +37,10 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.util.StopWatch;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.UrlPathHelper;
/**
@ -55,6 +57,7 @@ import org.springframework.web.util.UrlPathHelper;
public class MetricFilterAutoConfiguration {
private static final int UNDEFINED_HTTP_STATUS = 999;
private static final String UNKNOWN_PATH_SUFFIX = "/unmapped";
@Autowired
private CounterService counterService;
@ -86,10 +89,19 @@ public class MetricFilterAutoConfiguration {
}
finally {
stopWatch.stop();
int status = getStatus(response);
if (request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE) != null) {
suffix = request
.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)
.toString().replaceAll("[{}]", "-");
}
else if (HttpStatus.valueOf(status).is4xxClientError()) {
suffix = UNKNOWN_PATH_SUFFIX;
}
String gaugeKey = getKey("response" + suffix);
MetricFilterAutoConfiguration.this.gaugeService.submit(gaugeKey,
stopWatch.getTotalTimeMillis());
String counterKey = getKey("status." + getStatus(response) + suffix);
String counterKey = getKey("status." + status + suffix);
MetricFilterAutoConfiguration.this.counterService.increment(counterKey);
}
}

View File

@ -27,8 +27,16 @@ import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
@ -36,7 +44,10 @@ import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* Tests for {@link MetricFilterAutoConfiguration}.
@ -68,6 +79,57 @@ public class MetricFilterAutoConfigurationTests {
context.close();
}
@Test
public void recordsHttpInteractionsWithTemplateVariable() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
Config.class, MetricFilterAutoConfiguration.class);
Filter filter = context.getBean(Filter.class);
MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController())
.addFilter(filter).build();
mvc.perform(get("/templateVarTest/foo")).andExpect(status().isOk());
verify(context.getBean(CounterService.class)).increment(
"status.200.templateVarTest.-someVariable-");
verify(context.getBean(GaugeService.class)).submit(
eq("response.templateVarTest.-someVariable-"), anyDouble());
context.close();
}
@Test
public void recordsKnown404HttpInteractionsAsSingleMetricWithPathAndTemplateVariable()
throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
Config.class, MetricFilterAutoConfiguration.class);
Filter filter = context.getBean(Filter.class);
MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController())
.addFilter(filter).build();
mvc.perform(get("/knownPath/foo")).andExpect(status().isNotFound());
verify(context.getBean(CounterService.class)).increment(
"status.404.knownPath.-someVariable-");
verify(context.getBean(GaugeService.class)).submit(
eq("response.knownPath.-someVariable-"), anyDouble());
context.close();
}
@Test
public void records404HttpInteractionsAsSingleMetric() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
Config.class, MetricFilterAutoConfiguration.class);
Filter filter = context.getBean(Filter.class);
MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController())
.addFilter(filter).build();
mvc.perform(get("/unknownPath/1")).andExpect(status().isNotFound());
mvc.perform(get("/unknownPath/2")).andExpect(status().isNotFound());
verify(context.getBean(CounterService.class), times(2)).increment(
"status.404.unmapped");
verify(context.getBean(GaugeService.class), times(2)).submit(
eq("response.unmapped"), anyDouble());
context.close();
}
@Test
public void skipsFilterIfMissingServices() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
@ -88,6 +150,23 @@ public class MetricFilterAutoConfigurationTests {
public GaugeService gaugeService() {
return mock(GaugeService.class);
}
}
}
@RestController
class MetricFilterTestController {
@RequestMapping("templateVarTest/{someVariable}")
public String testTemplateVariableResolution(@PathVariable String someVariable) {
return someVariable;
}
@RequestMapping("knownPath/{someVariable}")
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public String testKnownPathWith404Response(@PathVariable String someVariable) {
return someVariable;
}
}