Commit 55667497 by Spencer Gibb

Merge pull request #633 from jkschneider/metrics-test-fixes

* metrics-test-fixes: Fix flaky Servo tests by avoiding DefaultMonitorRegistry
parents 679e659c 7bf6a85b
...@@ -49,6 +49,9 @@ public class MetricsClientHttpRequestInterceptor implements ClientHttpRequestInt ...@@ -49,6 +49,9 @@ public class MetricsClientHttpRequestInterceptor implements ClientHttpRequestInt
@Autowired @Autowired
Collection<MetricsTagProvider> tagProviders; Collection<MetricsTagProvider> tagProviders;
@Autowired
ServoMonitorCache servoMonitorCache;
@Value("${netflix.metrics.restClient.metricName:restclient}") @Value("${netflix.metrics.restClient.metricName:restclient}")
String metricName; String metricName;
...@@ -75,7 +78,7 @@ public class MetricsClientHttpRequestInterceptor implements ClientHttpRequestInt ...@@ -75,7 +78,7 @@ public class MetricsClientHttpRequestInterceptor implements ClientHttpRequestInt
.builder(metricName); .builder(metricName);
monitorConfigBuilder.withTags(builder); monitorConfigBuilder.withTags(builder);
ServoMonitorCache.getTimer(monitorConfigBuilder.build()).record( servoMonitorCache.getTimer(monitorConfigBuilder.build()).record(
System.nanoTime() - startTime, TimeUnit.NANOSECONDS); System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
} }
} }
......
...@@ -48,6 +48,9 @@ public class MetricsHandlerInterceptor extends HandlerInterceptorAdapter { ...@@ -48,6 +48,9 @@ public class MetricsHandlerInterceptor extends HandlerInterceptorAdapter {
MonitorRegistry registry; MonitorRegistry registry;
@Autowired @Autowired
ServoMonitorCache servoMonitorCache;
@Autowired
Collection<MetricsTagProvider> tagProviders; Collection<MetricsTagProvider> tagProviders;
@Override @Override
...@@ -89,7 +92,7 @@ public class MetricsHandlerInterceptor extends HandlerInterceptorAdapter { ...@@ -89,7 +92,7 @@ public class MetricsHandlerInterceptor extends HandlerInterceptorAdapter {
MonitorConfig.Builder monitorConfigBuilder = MonitorConfig.builder(metricName); MonitorConfig.Builder monitorConfigBuilder = MonitorConfig.builder(metricName);
monitorConfigBuilder.withTags(builder); monitorConfigBuilder.withTags(builder);
ServoMonitorCache.getTimer(monitorConfigBuilder.build()).record( servoMonitorCache.getTimer(monitorConfigBuilder.build()).record(
System.nanoTime() - startTime, TimeUnit.NANOSECONDS); System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
} }
} }
...@@ -60,13 +60,18 @@ public class ServoMetricsAutoConfiguration { ...@@ -60,13 +60,18 @@ public class ServoMetricsAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public MonitorRegistry monitorRegistry() { public MonitorRegistry monitorRegistry(ServoMetricsConfigBean servoMetricsConfig) {
System.setProperty(DefaultMonitorRegistry.class.getCanonicalName() + ".registryClass", servoMetricsConfig() System.setProperty(DefaultMonitorRegistry.class.getCanonicalName() + ".registryClass", servoMetricsConfig
.getRegistryClass()); .getRegistryClass());
return DefaultMonitorRegistry.getInstance(); return DefaultMonitorRegistry.getInstance();
} }
@Bean @Bean
public ServoMonitorCache monitorCache(MonitorRegistry monitorRegistry) {
return new ServoMonitorCache(monitorRegistry);
}
@Bean
public MetricReaderPublicMetrics servoPublicMetrics(MonitorRegistry monitorRegistry, ServoMetricNaming servoMetricNaming) { public MetricReaderPublicMetrics servoPublicMetrics(MonitorRegistry monitorRegistry, ServoMetricNaming servoMetricNaming) {
ServoMetricReader reader = new ServoMetricReader(monitorRegistry, servoMetricNaming); ServoMetricReader reader = new ServoMetricReader(monitorRegistry, servoMetricNaming);
return new MetricReaderPublicMetrics(reader); return new MetricReaderPublicMetrics(reader);
......
...@@ -16,10 +16,8 @@ package org.springframework.cloud.netflix.metrics.servo; ...@@ -16,10 +16,8 @@ package org.springframework.cloud.netflix.metrics.servo;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.netflix.servo.DefaultMonitorRegistry;
import com.netflix.servo.MonitorRegistry; import com.netflix.servo.MonitorRegistry;
import com.netflix.servo.monitor.BasicTimer; import com.netflix.servo.monitor.BasicTimer;
import com.netflix.servo.monitor.Monitor;
import com.netflix.servo.monitor.MonitorConfig; import com.netflix.servo.monitor.MonitorConfig;
/** /**
...@@ -28,32 +26,26 @@ import com.netflix.servo.monitor.MonitorConfig; ...@@ -28,32 +26,26 @@ import com.netflix.servo.monitor.MonitorConfig;
* @author Jon Schneider * @author Jon Schneider
*/ */
public class ServoMonitorCache { public class ServoMonitorCache {
private static final Map<MonitorConfig, BasicTimer> timerCache = new HashMap<>(); private final Map<MonitorConfig, BasicTimer> timerCache = new HashMap<>();
private final MonitorRegistry monitorRegistry;
public ServoMonitorCache(MonitorRegistry monitorRegistry) {
this.monitorRegistry = monitorRegistry;
}
/** /**
* @param config contains the name and tags that uniquely identify a timer * @param config contains the name and tags that uniquely identify a timer
* @return an already registered timer if it exists, otherwise create/register one and * @return an already registered timer if it exists, otherwise create/register one and
* return it. * return it.
*/ */
public synchronized static BasicTimer getTimer(MonitorConfig config) { public synchronized BasicTimer getTimer(MonitorConfig config) {
BasicTimer t = timerCache.get(config); BasicTimer t = timerCache.get(config);
if (t != null) if (t != null)
return t; return t;
t = new BasicTimer(config); t = new BasicTimer(config);
timerCache.put(config, t); timerCache.put(config, t);
DefaultMonitorRegistry.getInstance().register(t); monitorRegistry.register(t);
return t; return t;
} }
/**
* Useful for tests to clear the monitor registry between runs
*/
public static void unregisterAll() {
MonitorRegistry registry = DefaultMonitorRegistry.getInstance();
for (Monitor<?> monitor : registry.getRegisteredMonitors()) {
registry.unregister(monitor);
}
timerCache.clear();
}
} }
...@@ -24,6 +24,7 @@ import org.springframework.cloud.netflix.metrics.servo.ServoMetricsAutoConfigura ...@@ -24,6 +24,7 @@ import org.springframework.cloud.netflix.metrics.servo.ServoMetricsAutoConfigura
import org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache; import org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
...@@ -46,11 +47,14 @@ import com.netflix.servo.monitor.MonitorConfig; ...@@ -46,11 +47,14 @@ import com.netflix.servo.monitor.MonitorConfig;
MetricsRestTemplateTestConfig.class }) MetricsRestTemplateTestConfig.class })
@TestPropertySource(properties = { "netflix.metrics.restClient.metricName=metricName", @TestPropertySource(properties = { "netflix.metrics.restClient.metricName=metricName",
"spring.aop.proxy-target-class=true" }) "spring.aop.proxy-target-class=true" })
public class MetricsClientHttpRequestInterceptorTests extends AbstractMetricsTests { public class MetricsClientHttpRequestInterceptorTests {
@Autowired @Autowired
MonitorRegistry registry; MonitorRegistry registry;
@Autowired @Autowired
ServoMonitorCache servoMonitorCache;
@Autowired
RestTemplate restTemplate; RestTemplate restTemplate;
@Test @Test
...@@ -67,7 +71,7 @@ public class MetricsClientHttpRequestInterceptorTests extends AbstractMetricsTes ...@@ -67,7 +71,7 @@ public class MetricsClientHttpRequestInterceptorTests extends AbstractMetricsTes
.withTag("status", "200") .withTag("status", "200")
.withTag("clientName", "none"); .withTag("clientName", "none");
BasicTimer timer = ServoMonitorCache.getTimer(builder.build()); BasicTimer timer = servoMonitorCache.getTimer(builder.build());
Assert.assertEquals(1L, (long) timer.getCount()); Assert.assertEquals(1L, (long) timer.getCount());
mockServer.verify(); mockServer.verify();
...@@ -78,6 +82,11 @@ public class MetricsClientHttpRequestInterceptorTests extends AbstractMetricsTes ...@@ -78,6 +82,11 @@ public class MetricsClientHttpRequestInterceptorTests extends AbstractMetricsTes
@ImportAutoConfiguration({ ServoMetricsAutoConfiguration.class, @ImportAutoConfiguration({ ServoMetricsAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, AopAutoConfiguration.class }) PropertyPlaceholderAutoConfiguration.class, AopAutoConfiguration.class })
class MetricsRestTemplateTestConfig { class MetricsRestTemplateTestConfig {
@Bean
@Primary
public MonitorRegistry monitorRegistry() {
return new SimpleMonitorRegistry();
}
} }
@Configuration @Configuration
......
...@@ -26,6 +26,7 @@ import org.springframework.cloud.netflix.metrics.servo.ServoMetricsAutoConfigura ...@@ -26,6 +26,7 @@ import org.springframework.cloud.netflix.metrics.servo.ServoMetricsAutoConfigura
import org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache; import org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
...@@ -60,13 +61,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. ...@@ -60,13 +61,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@WebAppConfiguration @WebAppConfiguration
@TestPropertySource(properties = "netflix.metrics.rest.metricName=metricName") @TestPropertySource(properties = "netflix.metrics.rest.metricName=metricName")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class MetricsHandlerInterceptorIntegrationTests extends AbstractMetricsTests { public class MetricsHandlerInterceptorIntegrationTests {
@Autowired @Autowired
WebApplicationContext webAppContext; WebApplicationContext webAppContext;
@Autowired @Autowired
MonitorRegistry registry; MonitorRegistry registry;
@Autowired
ServoMonitorCache servoMonitorCache;
MockMvc mvc; MockMvc mvc;
@Test @Test
...@@ -117,7 +121,7 @@ public class MetricsHandlerInterceptorIntegrationTests extends AbstractMetricsTe ...@@ -117,7 +121,7 @@ public class MetricsHandlerInterceptorIntegrationTests extends AbstractMetricsTe
if (exceptionType != null) if (exceptionType != null)
builder = builder.withTag("exception", exceptionType); builder = builder.withTag("exception", exceptionType);
BasicTimer timer = ServoMonitorCache.getTimer(builder.build()); BasicTimer timer = servoMonitorCache.getTimer(builder.build());
Assert.assertEquals(1L, (long) timer.getCount()); Assert.assertEquals(1L, (long) timer.getCount());
} }
} }
...@@ -131,6 +135,12 @@ class MetricsTestConfig { ...@@ -131,6 +135,12 @@ class MetricsTestConfig {
MetricsTestController testController() { MetricsTestController testController() {
return new MetricsTestController(); return new MetricsTestController();
} }
@Bean
@Primary
public MonitorRegistry monitorRegistry() {
return new SimpleMonitorRegistry();
}
} }
@RestController @RestController
......
...@@ -13,15 +13,40 @@ ...@@ -13,15 +13,40 @@
package org.springframework.cloud.netflix.metrics; package org.springframework.cloud.netflix.metrics;
import org.junit.Before; import java.util.ArrayList;
import org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache; import java.util.Collection;
import java.util.List;
import com.netflix.servo.MonitorRegistry;
import com.netflix.servo.monitor.Monitor;
/** /**
* @author Jon Schneider * @author Jon Schneider
*/ */
public class AbstractMetricsTests { public class SimpleMonitorRegistry implements MonitorRegistry {
@Before List<Monitor<?>> monitors = new ArrayList<>();
public void setup() {
ServoMonitorCache.unregisterAll(); @Override
public Collection<Monitor<?>> getRegisteredMonitors() {
return monitors;
}
@Override
public void register(Monitor<?> monitor) {
monitors.add(monitor);
}
@Override
public void unregister(Monitor<?> monitor) {
monitors.remove(monitor);
}
@Override
public boolean isRegistered(Monitor<?> monitor) {
for (Monitor<?> m : monitors) {
if (m.equals(monitor))
return true;
}
return false;
} }
} }
\ No newline at end of file
...@@ -4,37 +4,24 @@ import java.util.ArrayList; ...@@ -4,37 +4,24 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.cloud.netflix.metrics.AbstractMetricsTests; import org.springframework.cloud.netflix.metrics.SimpleMonitorRegistry;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.netflix.servo.DefaultMonitorRegistry;
import com.netflix.servo.MonitorRegistry;
import com.netflix.servo.monitor.BasicTimer;
import com.netflix.servo.monitor.Monitor;
import com.netflix.servo.monitor.MonitorConfig; import com.netflix.servo.monitor.MonitorConfig;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
public class ServoMetricReaderTests extends AbstractMetricsTests { public class ServoMetricReaderTests {
@Test @Test
@Ignore
public void singleCompositeMonitorYieldsMultipleActuatorMetrics() { public void singleCompositeMonitorYieldsMultipleActuatorMetrics() {
MonitorRegistry registry = DefaultMonitorRegistry.getInstance(); SimpleMonitorRegistry registry = new SimpleMonitorRegistry();
ServoMetricReader reader = new ServoMetricReader(registry, new DimensionalServoMetricNaming());
// deal with monitors registered in other tests
for (Monitor<?> monitor : registry.getRegisteredMonitors()) {
registry.unregister(monitor);
}
ServoMetricReader reader = new ServoMetricReader(registry,
new DimensionalServoMetricNaming());
MonitorConfig.Builder builder = new MonitorConfig.Builder("metricName"); MonitorConfig.Builder builder = new MonitorConfig.Builder("metricName");
ServoMonitorCache servoMonitorCache = new ServoMonitorCache(registry);
BasicTimer timer = ServoMonitorCache.getTimer(builder.build()); servoMonitorCache.getTimer(builder.build());
List<Metric<?>> metrics = Lists.newArrayList(reader.findAll()); List<Metric<?>> metrics = Lists.newArrayList(reader.findAll());
......
...@@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ...@@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.cloud.netflix.metrics.DefaultMetricsTagProvider; import org.springframework.cloud.netflix.metrics.DefaultMetricsTagProvider;
import org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration; import org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration;
import org.springframework.cloud.netflix.metrics.MetricsTagProvider; import org.springframework.cloud.netflix.metrics.MetricsTagProvider;
import org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
...@@ -66,6 +67,11 @@ public class SpectatorMetricsAutoConfiguration { ...@@ -66,6 +67,11 @@ public class SpectatorMetricsAutoConfiguration {
return new ServoRegistry(); return new ServoRegistry();
} }
@Bean
public ServoMonitorCache monitorCache() {
return new ServoMonitorCache(monitorRegistry());
}
@Bean @Bean
@ConditionalOnMissingBean(MetricPoller.class) @ConditionalOnMissingBean(MetricPoller.class)
MetricPoller metricPoller() { MetricPoller metricPoller() {
......
...@@ -67,6 +67,9 @@ public class SpectatorMetricsHandlerInterceptorIntegrationTests { ...@@ -67,6 +67,9 @@ public class SpectatorMetricsHandlerInterceptorIntegrationTests {
@Autowired @Autowired
MonitorRegistry registry; MonitorRegistry registry;
@Autowired
ServoMonitorCache servoMonitorCache;
MockMvc mvc; MockMvc mvc;
@Test @Test
...@@ -117,7 +120,7 @@ public class SpectatorMetricsHandlerInterceptorIntegrationTests { ...@@ -117,7 +120,7 @@ public class SpectatorMetricsHandlerInterceptorIntegrationTests {
if (exceptionType != null) if (exceptionType != null)
builder = builder.withTag("exception", exceptionType); builder = builder.withTag("exception", exceptionType);
BasicTimer timer = ServoMonitorCache.getTimer(builder.build()); BasicTimer timer = servoMonitorCache.getTimer(builder.build());
Assert.assertEquals(1L, (long) timer.getCount()); Assert.assertEquals(1L, (long) timer.getCount());
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment