/** * 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.strategy.metrics; import static junit.framework.Assert.assertNotSame; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicInteger; import com.netflix.hystrix.strategy.HystrixPlugins; import org.junit.Before; import org.junit.Test; import com.netflix.hystrix.HystrixCircuitBreaker; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.HystrixCommandMetrics; import com.netflix.hystrix.HystrixCommandProperties; import com.netflix.hystrix.HystrixThreadPoolKey; import com.netflix.hystrix.HystrixThreadPoolMetrics; import com.netflix.hystrix.HystrixThreadPoolProperties; public class HystrixMetricsPublisherFactoryTest { @Before public void reset() { HystrixPlugins.reset(); } /** * Assert that we only call a publisher once for a given Command or ThreadPool key. */ @Test public void testSingleInitializePerKey() { final TestHystrixMetricsPublisher publisher = new TestHystrixMetricsPublisher(); HystrixPlugins.getInstance().registerMetricsPublisher(publisher); final HystrixMetricsPublisherFactory factory = new HystrixMetricsPublisherFactory(); ArrayList<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 20; i++) { threads.add(new Thread(new Runnable() { @Override public void run() { factory.getPublisherForCommand(TestCommandKey.TEST_A, null, null, null, null); factory.getPublisherForCommand(TestCommandKey.TEST_B, null, null, null, null); factory.getPublisherForThreadPool(TestThreadPoolKey.TEST_A, null, null); } })); } // start them for (Thread t : threads) { t.start(); } // wait for them to finish for (Thread t : threads) { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } } // we should see 2 commands and 1 threadPool publisher created assertEquals(2, publisher.commandCounter.get()); assertEquals(1, publisher.threadCounter.get()); } @Test public void testMetricsPublisherReset() { // precondition: HystrixMetricsPublisherFactory class is not loaded. Calling HystrixPlugins.reset() here should be good enough to run this with other tests. // set first custom publisher HystrixCommandKey key = HystrixCommandKey.Factory.asKey("key"); HystrixMetricsPublisherCommand firstCommand = new HystrixMetricsPublisherCommandDefault(key, null, null, null, null); HystrixMetricsPublisher firstPublisher = new CustomPublisher(firstCommand); HystrixPlugins.getInstance().registerMetricsPublisher(firstPublisher); // ensure that first custom publisher is used HystrixMetricsPublisherCommand cmd = HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(key, null, null, null, null); assertSame(firstCommand, cmd); // reset, then change to second custom publisher HystrixPlugins.reset(); HystrixMetricsPublisherCommand secondCommand = new HystrixMetricsPublisherCommandDefault(key, null, null, null, null); HystrixMetricsPublisher secondPublisher = new CustomPublisher(secondCommand); HystrixPlugins.getInstance().registerMetricsPublisher(secondPublisher); // ensure that second custom publisher is used cmd = HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(key, null, null, null, null); assertNotSame(firstCommand, cmd); assertSame(secondCommand, cmd); } private static class TestHystrixMetricsPublisher extends HystrixMetricsPublisher { AtomicInteger commandCounter = new AtomicInteger(); AtomicInteger threadCounter = new AtomicInteger(); @Override public HystrixMetricsPublisherCommand getMetricsPublisherForCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandOwner, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { return new HystrixMetricsPublisherCommand() { @Override public void initialize() { commandCounter.incrementAndGet(); } }; } @Override public HystrixMetricsPublisherThreadPool getMetricsPublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { return new HystrixMetricsPublisherThreadPool() { @Override public void initialize() { threadCounter.incrementAndGet(); } }; } } private static enum TestCommandKey implements HystrixCommandKey { TEST_A, TEST_B } private static enum TestThreadPoolKey implements HystrixThreadPoolKey { TEST_A, TEST_B } static class CustomPublisher extends HystrixMetricsPublisher{ private HystrixMetricsPublisherCommand commandToReturn; public CustomPublisher(HystrixMetricsPublisherCommand commandToReturn){ this.commandToReturn = commandToReturn; } @Override public HystrixMetricsPublisherCommand getMetricsPublisherForCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandGroupKey, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { return commandToReturn; } } }