public void testTripCircuitOnTimeoutsAboveThreshold()
        {
            var             properties = CommandPropertiesTest.GetUnitTestPropertiesSetter();
            var             clock      = new MockedClock();
            CommandMetrics  metrics    = getMetrics(properties, clock);
            ICircuitBreaker cb         = getCircuitBreaker("KEY_ONE", "OWNER_TWO", metrics, properties, clock);

            // this should start as allowing requests
            Assert.True(cb.AllowRequest);
            Assert.False(cb.IsOpen());

            // success with high latency
            metrics.MarkSuccess(400);
            metrics.MarkSuccess(400);
            metrics.MarkTimeout(10);
            metrics.MarkSuccess(400);
            metrics.MarkTimeout(10);
            metrics.MarkTimeout(10);
            metrics.MarkSuccess(400);
            metrics.MarkTimeout(10);
            metrics.MarkTimeout(10);

            // this should trip the circuit as the error percentage is above the threshold
            Assert.False(cb.AllowRequest);
            Assert.True(cb.IsOpen());
        }
        public void testTripCircuitOnTimeouts()
        {
            var             properties = CommandPropertiesTest.GetUnitTestPropertiesSetter();
            var             clock      = new MockedClock();
            CommandMetrics  metrics    = getMetrics(properties, clock);
            ICircuitBreaker cb         = getCircuitBreaker("KEY_ONE", "OWNER_TWO", metrics, properties, clock);

            // this should start as allowing requests
            Assert.True(cb.AllowRequest);
            Assert.False(cb.IsOpen());

            // timeouts
            metrics.MarkTimeout(2000);
            metrics.MarkTimeout(2000);
            metrics.MarkTimeout(2000);
            metrics.MarkTimeout(2000);

            // everything has been a timeout so we should not allow any requests
            Assert.False(cb.AllowRequest);
            Assert.True(cb.IsOpen());
        }
Exemple #3
0
        public void testErrorPercentage()
        {
            var            properties = CommandPropertiesTest.GetUnitTestPropertiesSetter();
            var            clock      = new MockedClock();
            CommandMetrics metrics    = getMetrics(properties, clock);

            metrics.MarkSuccess(100);
            Assert.Equal(0, metrics.GetHealthCounts().ErrorPercentage);
            clock.Increment(1);
            metrics.MarkFailure(1000);
            Assert.Equal(50, metrics.GetHealthCounts().ErrorPercentage);

            clock.Increment(1);
            metrics.MarkSuccess(100);
            metrics.MarkSuccess(100);
            Assert.Equal(25, metrics.GetHealthCounts().ErrorPercentage);

            clock.Increment(1);
            metrics.MarkTimeout(5000);
            metrics.MarkTimeout(5000);
            Assert.Equal(50, metrics.GetHealthCounts().ErrorPercentage);

            clock.Increment(1);
            metrics.MarkSuccess(100);
            metrics.MarkSuccess(100);
            metrics.MarkSuccess(100);

            // latent
            clock.Increment(1);
            metrics.MarkSuccess(5000);

            // 6 success + 1 latent success + 1 failure + 2 timeout = 10 total
            // latent success not considered error
            // error percentage = 1 failure + 2 timeout / 10
            Assert.Equal(30, metrics.GetHealthCounts().ErrorPercentage);
        }
        public void testCircuitClosedAfterSuccess()
        {
            int sleepWindow = 1000;
            var properties  = CommandPropertiesTest.GetUnitTestPropertiesSetter()
                              .WithCircuitBreakerSleepWindowInMilliseconds(sleepWindow);
            var             clock   = new MockedClock();
            CommandMetrics  metrics = getMetrics(properties, clock);
            ICircuitBreaker cb      = getCircuitBreaker("KEY_ONE", "OWNER_TWO", metrics, properties, clock);

            // fail
            metrics.MarkFailure(1000);
            metrics.MarkFailure(1000);
            metrics.MarkFailure(1000);
            metrics.MarkTimeout(1000);

            // everything has failed in the test window so we should return false now
            Assert.False(cb.AllowRequest);
            Assert.True(cb.IsOpen());

            // wait for sleepWindow to pass
            clock.Increment(sleepWindow + 50);

            // we should now allow 1 request
            Assert.True(cb.AllowRequest);
            // but the circuit should still be open
            Assert.True(cb.IsOpen());
            clock.Increment(sleepWindow);
            // and further requests are still blocked
            Assert.False(cb.AllowRequest);

            // the 'singleTest' succeeds so should cause the circuit to be closed
            metrics.MarkSuccess(500);
            clock.Increment(sleepWindow);
            cb.MarkSuccess();

            // all requests should be open again
            Assert.True(cb.AllowRequest);
            clock.Increment(sleepWindow);
            Assert.True(cb.AllowRequest);
            clock.Increment(sleepWindow);
            Assert.True(cb.AllowRequest);
            // and the circuit should be closed again
            Assert.False(cb.IsOpen());
        }
Exemple #5
0
        private T InnerExecute <T>(Func <T> primaryFunction, Func <IEnumerable <Exception>, T> fallbackFunction, CancellationTokenSource cancellationTokenSource)
        {
            if (!ConfigurationService.GetHystrixCommandEnabled())
            {
                return(primaryFunction.Invoke());
            }

            var innerExceptions = new List <Exception>();

            Stopwatch userThreadStopWatch = Stopwatch.StartNew();

            if (CircuitBreaker.AllowRequest())
            {
                CommandMetrics.IncrementConcurrentExecutionCount();
                ThreadPoolMetrics.MarkThreadExecution();

                Stopwatch commandStopWatch = Stopwatch.StartNew();

                try
                {
                    var result = timeoutWrapper.Execute(primaryFunction, cancellationTokenSource);

                    commandStopWatch.Stop();

                    CircuitBreaker.CloseCircuit();

                    CommandMetrics.MarkSuccess();

                    return(result);
                }
                catch (HystrixTimeoutException hte)
                {
                    commandStopWatch.Stop();
                    CommandMetrics.MarkTimeout();
                    innerExceptions.Add(hte);
                }
                catch (Exception ex)
                {
                    commandStopWatch.Stop();
                    CommandMetrics.MarkFailure();
                    CommandMetrics.MarkExceptionThrown();
                    innerExceptions.Add(ex);
                }
                finally
                {
                    // track command execution time
                    commandStopWatch.Stop();
                    CommandMetrics.AddCommandExecutionTime(commandStopWatch.Elapsed.TotalMilliseconds);

                    CommandMetrics.DecrementConcurrentExecutionCount();
                    ThreadPoolMetrics.MarkThreadCompletion();

                    // track execution time including threading overhead
                    userThreadStopWatch.Stop();
                    CommandMetrics.AddUserThreadExecutionTime(userThreadStopWatch.Elapsed.TotalMilliseconds);
                }
            }
            else
            {
                CommandMetrics.MarkShortCircuited();

                // track execution time including threading overhead
                userThreadStopWatch.Stop();
                CommandMetrics.AddUserThreadExecutionTime(userThreadStopWatch.Elapsed.TotalMilliseconds);
            }

            T fallbackResult = fallbackFunction.Invoke(innerExceptions);

            CommandMetrics.MarkFallbackSuccess();

            return(fallbackResult);
        }