/** * Copyright 2015 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.netflix.hystrix.metric; import com.netflix.hystrix.ExecutionResult; import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.HystrixEventType; import com.netflix.hystrix.HystrixThreadPoolKey; import org.junit.Test; import rx.Subscriber; import rx.functions.Action1; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; public class HystrixThreadEventStreamTest { HystrixCommandKey commandKey; HystrixThreadPoolKey threadPoolKey; HystrixThreadEventStream writeToStream; HystrixCommandCompletionStream readCommandStream; HystrixThreadPoolCompletionStream readThreadPoolStream; public HystrixThreadEventStreamTest() { commandKey = HystrixCommandKey.Factory.asKey("CMD-ThreadStream"); threadPoolKey = HystrixThreadPoolKey.Factory.asKey("TP-ThreadStream"); writeToStream = HystrixThreadEventStream.getInstance(); readCommandStream = HystrixCommandCompletionStream.getInstance(commandKey); readThreadPoolStream = HystrixThreadPoolCompletionStream.getInstance(threadPoolKey); } private <T> Subscriber<T> getLatchedSubscriber(final CountDownLatch latch) { return new Subscriber<T>() { @Override public void onCompleted() { latch.countDown(); } @Override public void onError(Throwable e) { fail(e.getMessage()); e.printStackTrace(); latch.countDown(); } @Override public void onNext(T value) { System.out.println("OnNext : " + value); } }; } @Test public void noEvents() throws InterruptedException { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); //no writes assertFalse(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testThreadIsolatedSuccess() throws InterruptedException { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.SUCCESS).setExecutedInThread(); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertTrue(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testSemaphoreIsolatedSuccess() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.SUCCESS); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testThreadIsolatedFailure() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.FAILURE).setExecutedInThread(); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertTrue(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testSemaphoreIsolatedFailure() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.FAILURE); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testThreadIsolatedTimeout() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.TIMEOUT).setExecutedInThread(); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertTrue(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testSemaphoreIsolatedTimeout() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.TIMEOUT); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testThreadIsolatedBadRequest() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.BAD_REQUEST).setExecutedInThread(); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertTrue(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testSemaphoreIsolatedBadRequest() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.BAD_REQUEST); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testThreadRejectedCommand() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.THREAD_POOL_REJECTED); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertTrue(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testSemaphoreRejectedCommand() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.SEMAPHORE_REJECTED); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testThreadIsolatedResponseFromCache() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<List<HystrixCommandCompletion>> commandListSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().buffer(500, TimeUnit.MILLISECONDS).take(1) .doOnNext(new Action1<List<HystrixCommandCompletion>>() { @Override public void call(List<HystrixCommandCompletion> hystrixCommandCompletions) { System.out.println("LIST : " + hystrixCommandCompletions); assertEquals(3, hystrixCommandCompletions.size()); } }) .subscribe(commandListSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.SUCCESS).setExecutedInThread(); ExecutionResult cache1 = ExecutionResult.from(HystrixEventType.RESPONSE_FROM_CACHE); ExecutionResult cache2 = ExecutionResult.from(HystrixEventType.RESPONSE_FROM_CACHE); writeToStream.executionDone(result, commandKey, threadPoolKey); writeToStream.executionDone(cache1, commandKey, threadPoolKey); writeToStream.executionDone(cache2, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertTrue(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testSemaphoreIsolatedResponseFromCache() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<List<HystrixCommandCompletion>> commandListSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().buffer(500, TimeUnit.MILLISECONDS).take(1) .doOnNext(new Action1<List<HystrixCommandCompletion>>() { @Override public void call(List<HystrixCommandCompletion> hystrixCommandCompletions) { System.out.println("LIST : " + hystrixCommandCompletions); assertEquals(3, hystrixCommandCompletions.size()); } }) .subscribe(commandListSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.SUCCESS); ExecutionResult cache1 = ExecutionResult.from(HystrixEventType.RESPONSE_FROM_CACHE); ExecutionResult cache2 = ExecutionResult.from(HystrixEventType.RESPONSE_FROM_CACHE); writeToStream.executionDone(result, commandKey, threadPoolKey); writeToStream.executionDone(cache1, commandKey, threadPoolKey); writeToStream.executionDone(cache2, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } @Test public void testShortCircuit() throws Exception { CountDownLatch commandLatch = new CountDownLatch(1); CountDownLatch threadPoolLatch = new CountDownLatch(1); Subscriber<HystrixCommandCompletion> commandSubscriber = getLatchedSubscriber(commandLatch); readCommandStream.observe().take(1).subscribe(commandSubscriber); Subscriber<HystrixCommandCompletion> threadPoolSubscriber = getLatchedSubscriber(threadPoolLatch); readThreadPoolStream.observe().take(1).subscribe(threadPoolSubscriber); ExecutionResult result = ExecutionResult.from(HystrixEventType.SHORT_CIRCUITED); writeToStream.executionDone(result, commandKey, threadPoolKey); assertTrue(commandLatch.await(1000, TimeUnit.MILLISECONDS)); assertFalse(threadPoolLatch.await(1000, TimeUnit.MILLISECONDS)); } }