diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolMetrics.java b/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolMetrics.java index 65d17a859..22e978b1d 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolMetrics.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolMetrics.java @@ -25,8 +25,10 @@ import rx.functions.Func0; import rx.functions.Func2; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadPoolExecutor; @@ -93,7 +95,18 @@ public static HystrixThreadPoolMetrics getInstance(HystrixThreadPoolKey key) { * @return {@code Collection} */ public static Collection getInstances() { - return Collections.unmodifiableCollection(metrics.values()); + List threadPoolMetrics = new ArrayList(); + for (HystrixThreadPoolMetrics tpm: metrics.values()) { + if (hasExecutedCommandsOnThread(tpm)) { + threadPoolMetrics.add(tpm); + } + } + + return Collections.unmodifiableCollection(threadPoolMetrics); + } + + private static boolean hasExecutedCommandsOnThread(HystrixThreadPoolMetrics threadPoolMetrics) { + return threadPoolMetrics.getCurrentCompletedTaskCount().intValue() > 0; } public static final Func2 appendEventToBucket diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/util/PlatformSpecific.java b/hystrix-core/src/main/java/com/netflix/hystrix/util/PlatformSpecific.java index 4cac86f15..6ddf9afa9 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/util/PlatformSpecific.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/util/PlatformSpecific.java @@ -19,16 +19,24 @@ import java.util.concurrent.ThreadFactory; public class PlatformSpecific { - private final boolean isAppEngineStandardEnvironment; + private final Platform platform; + + private enum Platform { + STANDARD, APPENGINE_STANDARD, APPENGINE_FLEXIBLE + } private static PlatformSpecific INSTANCE = new PlatformSpecific(); private PlatformSpecific() { - isAppEngineStandardEnvironment = determineAppEngineReflectively(); + platform = determinePlatformReflectively(); } public static boolean isAppEngineStandardEnvironment() { - return INSTANCE.isAppEngineStandardEnvironment; + return INSTANCE.platform == Platform.APPENGINE_STANDARD; + } + + public static boolean isAppEngine() { + return INSTANCE.platform == Platform.APPENGINE_FLEXIBLE || INSTANCE.platform == Platform.APPENGINE_STANDARD; } /* @@ -36,31 +44,32 @@ public static boolean isAppEngineStandardEnvironment() { * http://docs.guava-libraries.googlecode.com/git/javadoc/src-html/com/google/common/util/concurrent/MoreExecutors.html#line.766 * Added GAE_LONG_APP_ID check to detect only AppEngine Standard Environment */ - private static boolean determineAppEngineReflectively() { + private static Platform determinePlatformReflectively() { if (System.getProperty("com.google.appengine.runtime.environment") == null) { - return false; + return Platform.STANDARD; } // GAE_LONG_APP_ID is only set in the GAE Flexible Environment, where we want standard threading if (System.getenv("GAE_LONG_APP_ID") != null) { - return false; + return Platform.APPENGINE_FLEXIBLE; } try { // If the current environment is null, we're not inside AppEngine. - return Class.forName("com.google.apphosting.api.ApiProxy") + boolean isInsideAppengine = Class.forName("com.google.apphosting.api.ApiProxy") .getMethod("getCurrentEnvironment") .invoke(null) != null; + return isInsideAppengine ? Platform.APPENGINE_STANDARD : Platform.STANDARD; } catch (ClassNotFoundException e) { // If ApiProxy doesn't exist, we're not on AppEngine at all. - return false; + return Platform.STANDARD; } catch (InvocationTargetException e) { // If ApiProxy throws an exception, we're not in a proper AppEngine environment. - return false; + return Platform.STANDARD; } catch (IllegalAccessException e) { // If the method isn't accessible, we're not on a supported version of AppEngine; - return false; + return Platform.STANDARD; } catch (NoSuchMethodException e) { // If the method doesn't exist, we're not on a supported version of AppEngine; - return false; + return Platform.STANDARD; } } diff --git a/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolMetricsTest.java b/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolMetricsTest.java index 13c47136c..ed29a25a9 100644 --- a/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolMetricsTest.java +++ b/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolMetricsTest.java @@ -25,51 +25,50 @@ public class HystrixThreadPoolMetricsTest { - private static final HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("HystrixThreadPoolMetrics-UnitTest"); - private static final HystrixThreadPoolKey tpKey = HystrixThreadPoolKey.Factory.asKey("HystrixThreadPoolMetrics-ThreadPool"); + private static final HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("HystrixThreadPoolMetrics-UnitTest"); + private static final HystrixThreadPoolKey tpKey = HystrixThreadPoolKey.Factory.asKey("HystrixThreadPoolMetrics-ThreadPool"); @Before public void resetAll() { - HystrixThreadPoolMetrics.reset(); - } + HystrixThreadPoolMetrics.reset(); + } - @Test - public void shouldYieldNoExecutedTasksOnStartup() throws Exception { - //given - final Collection instances = HystrixThreadPoolMetrics.getInstances(); + @Test + public void shouldYieldNoExecutedTasksOnStartup() throws Exception { + //given + final Collection instances = HystrixThreadPoolMetrics.getInstances(); - //then - assertEquals(0, instances.size()); + //then + assertEquals(0, instances.size()); - } - @Test - public void shouldReturnOneExecutedTask() throws Exception { - //given - final Collection instances = HystrixThreadPoolMetrics.getInstances(); - RollingThreadPoolEventCounterStream.getInstance(tpKey, 10, 100).startCachingStreamValuesIfUnstarted(); + } + @Test + public void shouldReturnOneExecutedTask() throws Exception { + //given + RollingThreadPoolEventCounterStream.getInstance(tpKey, 10, 100).startCachingStreamValuesIfUnstarted(); - //when - new NoOpHystrixCommand().execute(); + new NoOpHystrixCommand().execute(); + Thread.sleep(100); - //then - Thread.sleep(100); - assertEquals(1, instances.size()); - assertEquals(1, instances.iterator().next().getRollingCountThreadsExecuted()); - } + final Collection instances = HystrixThreadPoolMetrics.getInstances(); - private static class NoOpHystrixCommand extends HystrixCommand { - public NoOpHystrixCommand() { - super(Setter.withGroupKey(groupKey) + //then + assertEquals(1, instances.size()); + HystrixThreadPoolMetrics metrics = instances.iterator().next(); + assertEquals(1, instances.iterator().next().getRollingCountThreadsExecuted()); + } + + private static class NoOpHystrixCommand extends HystrixCommand { + public NoOpHystrixCommand() { + super(Setter.withGroupKey(groupKey) .andThreadPoolKey(tpKey) .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withMetricsRollingStatisticalWindowInMilliseconds(100))); - } + } - @Override - protected Void run() throws Exception { - System.out.println("Run in thread : " + Thread.currentThread().getName()); + @Override + protected Void run() throws Exception { + System.out.println("Run in thread : " + Thread.currentThread().getName()); return null; - } - } - - + } + } } \ No newline at end of file