From 1578b4a95caa1e2f1c45da151db7a198523d44a8 Mon Sep 17 00:00:00 2001 From: Dave Tillman Date: Tue, 19 Dec 2017 08:58:09 -0700 Subject: [PATCH] Apply StyleCop to src packages --- .travis.yml | 4 +- CircuitBreaker.sln | 30 +- README.md | 68 +- appveyor.yml | 4 +- config/versions-dev.props | 17 +- config/versions-master.props | 19 +- config/versions.props | 19 +- scripts/appveyor_build.cmd | 8 +- scripts/appveyor_tests.cmd | 2 +- scripts/travis_build.sh | 2 +- scripts/travis_test.sh | 2 +- .../HystrixBaseOptions.cs | 57 - .../HystrixCollapserOptions.cs | 134 -- .../IHystrixCollapserOptions.cs | 94 - .../IHystrixCommandOptions.cs | 253 --- .../IHystrixThreadPoolOptions.cs | 79 - .../Metric/HystrixRequestEvents.cs | 224 --- .../CancellationTokenExtensions.cs | 4 +- .../HystrixConfigStreamController.cs | 13 +- .../HystrixMetricsStreamController.cs | 21 +- .../HystrixRequestEventStreamController.cs | 13 +- .../HystrixStreamBaseController.cs | 39 +- .../HystrixUtilizationStreamController.cs | 13 +- .../HystrixApplicationBuilderExtensions.cs | 5 +- .../HystrixServiceCollectionExtensions.cs | 7 +- .../Properties/AssemblyInfo.cs | 16 +- ...itBreaker.Hystrix.MetricsEventsCore.csproj | 22 +- .../HystrixContainerBuilderExtensions.cs | 8 +- .../Properties/AssemblyInfo.cs | 16 +- .../RabbitMetricsStreamPublisher.cs | 67 +- ...reaker.Hystrix.MetricsStreamAutofac.csproj | 20 +- .../HystrixApplicationBuilderExtensions.cs | 5 +- .../HystrixServiceCollectionExtensions.cs | 6 +- .../Properties/AssemblyInfo.cs | 16 +- .../RabbitMetricsStreamPublisher.cs | 67 +- ...itBreaker.Hystrix.MetricsStreamCore.csproj | 18 +- .../HystrixContainerBuilderExtensions.cs | 78 +- .../HystrixRequestContextModule.cs | 6 +- .../Properties/AssemblyInfo.cs | 16 +- ...eltoe.CircuitBreaker.HystrixAutofac.csproj | 16 +- .../AbstractCommand.cs | 1647 +++++++++-------- .../HystrixCircuitBreakerFactory.cs | 13 +- .../HystrixCircuitBreakerImpl.cs | 31 +- .../CircuitBreaker/NoOpCircuitBreaker.cs | 7 +- .../Collapser/CollapsedRequest.cs | 46 +- .../Collapser/CollapsedTask.cs | 59 + .../Collapser/ICollapserTimer.cs | 5 +- .../Collapser/RealCollapserTimer.cs | 10 +- .../Collapser/RequestBatch.cs | 160 +- .../Collapser/RequestCollapser.cs | 77 +- .../Collapser/RequestCollapserFactory.cs | 65 +- .../CollapserEventTypeHelper.cs | 52 + .../Config/HystrixCollapserConfiguration.cs | 27 +- .../Config/HystrixCommandConfiguration.cs | 73 +- .../Config/HystrixConfiguration.cs | 19 +- .../Config/HystrixConfigurationStream.cs | 60 +- .../Config/HystrixThreadPoolConfiguration.cs | 20 +- .../Exceptions/FailureType.cs | 6 +- .../Exceptions/HystrixBadRequestException.cs | 11 +- .../Exceptions/HystrixRuntimeException.cs | 17 +- .../Exceptions/HystrixTimeoutException.cs | 12 +- .../Exceptions/RejectedExecutionException.cs | 8 +- .../ExecutionResult.cs | 394 ++-- .../HealthCounts.cs | 80 + .../HystrixBaseOptions.cs | 64 + .../HystrixCachedTask.cs | 16 +- .../HystrixCollapser.cs | 165 +- .../HystrixCollapserMetrics.cs | 46 +- .../HystrixCollapserOptions.cs | 79 + .../HystrixCommand.cs | 200 +- .../HystrixCommandMetrics.cs | 118 +- .../HystrixCommandOptions.cs | 280 +-- .../HystrixCounters.cs | 18 +- .../HystrixEventType.cs | 51 + .../HystrixEventTypeHelper.cs} | 180 +- .../HystrixMetrics.cs | 23 +- .../HystrixRequestCache.cs | 126 +- .../HystrixRequestLog.cs | 147 +- .../HystrixThreadPoolMetrics.cs | 52 +- .../HystrixThreadPoolOptions.cs | 86 +- .../ICollapsedRequest.cs | 6 +- .../IHystrixCircuitBreaker.cs | 7 +- .../IHystrixCollapserKey.cs | 15 +- .../IHystrixCollapserOptions.cs | 41 + .../IHystrixCommandGroupKey.cs | 29 +- .../IHystrixCommandKey.cs | 25 +- .../IHystrixCommandOptions.cs | 73 + .../IHystrixExecutable.cs | 8 +- .../IHystrixInvokable.cs | 11 +- .../IHystrixInvokableInfo.cs | 7 +- .../IHystrixKey.cs | 17 +- .../IHystrixObservable.cs | 6 +- .../IHystrixThreadPool.cs | 23 +- .../IHystrixThreadPoolKey.cs | 14 +- .../IHystrixThreadPoolOptions.cs | 37 + .../Metric/CachedValuesHistogram.cs | 32 +- .../Metric/CommandAndCacheKey.cs | 67 + .../Metric/Consumer/BucketedCounterStream.cs | 62 +- .../BucketedCumulativeCounterStream.cs | 34 +- .../Consumer/BucketedRollingCounterStream.cs | 54 +- .../CumulativeCollapserEventCounterStream.cs | 14 +- .../CumulativeCommandEventCounterStream.cs | 13 +- .../CumulativeThreadPoolEventCounterStream.cs | 13 +- .../Metric/Consumer/HealthCountsStream.cs | 18 +- .../Metric/Consumer/HystrixDashboardStream.cs | 42 +- ...ingCollapserBatchSizeDistributionStream.cs | 47 +- .../RollingCollapserEventCounterStream.cs | 31 +- .../RollingCommandEventCounterStream.cs | 11 +- ...RollingCommandLatencyDistributionStream.cs | 18 +- .../RollingCommandMaxConcurrencyStream.cs | 12 +- ...ingCommandUserLatencyDistributionStream.cs | 15 +- .../Consumer/RollingConcurrencyStream.cs | 23 +- .../Consumer/RollingDistributionStream.cs | 39 +- .../RollingThreadPoolEventCounterStream.cs | 12 +- .../RollingThreadPoolMaxConcurrencyStream.cs | 15 +- .../Metric/ExecutionSignature.cs | 108 ++ .../Metric/HystrixCollapserEvent.cs | 7 +- .../Metric/HystrixCollapserEventStream.cs | 21 +- .../Metric/HystrixCommandCompletion.cs | 19 +- .../Metric/HystrixCommandCompletionStream.cs | 21 +- .../Metric/HystrixCommandEvent.cs | 32 +- .../Metric/HystrixCommandExecutionStarted.cs | 8 +- .../Metric/HystrixCommandStartStream.cs | 19 +- .../Metric/HystrixRequestEvents.cs | 106 ++ .../Metric/HystrixRequestEventsStream.cs | 12 +- .../Metric/HystrixThreadEventStream.cs | 24 +- .../HystrixThreadPoolCompletionStream.cs | 20 +- .../Metric/HystrixThreadPoolStartStream.cs | 22 +- .../Metric/IHystrixEvent.cs | 4 +- .../Metric/IHystrixEventStream.cs | 8 +- .../Sample/HystrixCommandUtilization.cs | 5 +- .../Sample/HystrixThreadPoolUtilization.cs | 10 +- .../Metric/Sample/HystrixUtilization.cs | 13 +- .../Metric/Sample/HystrixUtilizationStream.cs | 45 +- .../HystrixMetricsStreamOptions.cs | 5 +- .../HystrixMetricsStreamPublisher.cs | 91 +- .../MetricsStream/Serialize.cs | 47 +- .../Properties/AssemblyInfo.cs | 20 +- .../README.md | 0 .../Serial/SerialHystrixConfiguration.cs | 16 +- .../Serial/SerialHystrixDashboardData.cs | 70 +- .../Serial/SerialHystrixRequestEvents.cs | 38 +- .../Serial/SerialHystrixUtilization.cs | 31 +- .../Serial/SerializationExtensions.cs | 10 +- ...teeltoe.CircuitBreaker.HystrixBase.csproj} | 22 +- .../Concurrency/HystrixConcurrencyStrategy.cs | 13 +- .../HystrixConcurrencyStrategyDefault.cs | 22 +- .../Concurrency/HystrixQueuedTaskScheduler.cs | 47 +- .../Concurrency/HystrixRequestContext.cs | 35 +- .../HystrixRequestVariableDefault.cs | 46 +- .../Concurrency/HystrixSyncTaskScheduler.cs | 102 +- .../Concurrency/HystrixTaskScheduler.cs | 22 +- .../Concurrency/IHystrixRequestVariable.cs | 11 +- .../Concurrency/IHystrixTaskScheduler.cs | 18 +- .../EventNotifier/HystrixEventNotifier.cs | 10 +- .../HystrixEventNotifierDefault.cs | 12 +- .../HystrixCommandExecutionHook.cs | 41 +- .../HystrixCommandExecutionHookDefault.cs | 11 +- .../Strategy/HystrixPlugins.cs | 72 +- .../Metrics/HystrixMetricsPublisher.cs | 6 +- ...HystrixMetricsPublisherCollapserDefault.cs | 5 +- .../HystrixMetricsPublisherCommandDefault.cs | 4 +- .../Metrics/HystrixMetricsPublisherDefault.cs | 9 +- .../Metrics/HystrixMetricsPublisherFactory.cs | 48 +- ...ystrixMetricsPublisherThreadPoolDefault.cs | 4 +- .../IHystrixMetricsPublisherCollapser.cs | 4 +- .../IHystrixMetricsPublisherCommand.cs | 4 +- .../IHystrixMetricsPublisherThreadPool.cs | 4 +- .../Options/HystrixDynamicOptionsDefault.cs | 18 +- .../Strategy/Options/HystrixOptionsFactory.cs | 27 +- .../Options/HystrixOptionsStrategy.cs | 17 +- .../Options/HystrixOptionsStrategyDefault.cs | 11 +- .../Options/IHystrixDynamicOptions.cs | 3 +- .../ThreadPool/HystrixThreadPoolDefault.cs | 84 +- .../ThreadPool/HystrixThreadPoolFactory.cs | 23 +- .../ThreadPoolEventTypeHelper.cs | 68 + .../TimerReference.cs | 9 +- .../Util/ActualTime.cs | 24 + .../Util/AtomicBoolean.cs | 9 +- .../Util/AtomicInteger.cs | 11 +- .../Util/AtomicIntegerArray.cs | 9 +- .../Util/AtomicLong.cs | 7 +- .../Util/AtomicReference.cs | 14 +- .../Util/AtomicReferenceArray.cs | 7 +- .../Util/ConcurrentDictionaryExtensions.cs | 13 +- .../Util/HystrixRollingNumber.cs | 348 ++-- .../Util/HystrixRollingNumberEvent.cs | 41 + .../Util/HystrixRollingNumberEventHelper.cs} | 85 +- .../Util/HystrixRollingPercentile.cs | 326 ++-- .../Util/HystrixTimer.cs | 10 +- .../Util/ITime.cs | 24 + .../Util/ITimerListener.cs | 6 +- .../Util/LongAdder.cs | 7 +- .../Util/LongMaxUpdater.cs | 12 +- .../Util/ObservableExtensions.cs | 20 +- .../Util/SemaphoreSlimExtensions.cs | 6 +- .../Util/Time.cs | 31 +- .../HystrixApplicationBuilderExtensions.cs | 8 +- .../HystrixRequestContextMiddleware.cs | 22 +- .../HystrixRequestContextMiddlewareOwin.cs | 40 + .../HystrixServiceCollectionExtensions.cs | 74 +- .../Properties/AssemblyInfo.cs | 16 +- ...Steeltoe.CircuitBreaker.HystrixCore.csproj | 17 +- stylecop.json | 27 + .../HystrixConfigStreamControllerTest.cs | 2 +- .../HystrixMetricsStreamControllerTest.cs | 2 +- ...HystrixRequestEventStreamControllerTest.cs | 2 +- .../HystrixUtilizationStreamControllerTest.cs | 2 +- ...aker.Hystrix.MetricsEventsCore.Test.csproj | 1 + .../HystrixContainerBuilderExtensionsTest.cs | 2 +- .../RabbitMetricsStreamPublisherTest.cs | 6 +- .../HystrixServiceCollectionExtensionsTest.cs | 2 +- .../RabbitMetricsStreamPublisherTest.cs | 6 +- ...aker.Hystrix.MetricsStreamCore.Test.csproj | 1 + .../HystrixContainerBuilderExtensionsTest.cs | 16 +- .../CommonHystrixCommandTests.cs | 0 .../Config/HystrixConfigurationStreamTest.cs | 0 .../CountDownEventExtensions.cs | 0 .../HystrixCircuitBreakerTest.cs | 22 +- .../HystrixCollapserTest.cs | 0 .../HystrixCommandMetricsTest.cs | 6 +- .../HystrixCommandOptionsTest.cs | 0 .../HystrixCommandTest.cs | 100 +- ...HystrixCommandTimeoutConcurrencyTesting.cs | 0 .../HystrixRequestCacheTest.cs | 0 .../HystrixRequestLogTest.cs | 4 +- .../HystrixSubclassCommandTest.cs | 0 .../HystrixTestBase.cs | 0 .../HystrixThreadPoolMetricsTest.cs | 0 .../HystrixThreadPoolOptionsTest.cs | 0 .../HystrixThreadPoolTest.cs | 6 +- .../Metric/CommandStreamTest.cs | 6 +- ...mulativeCollapserEventCounterStreamTest.cs | 0 ...CumulativeCommandEventCounterStreamTest.cs | 0 ...ulativeThreadPoolEventCounterStreamTest.cs | 0 .../Metric/Consumer/HealthCountsStreamTest.cs | 0 .../Consumer/HystrixDashboardStreamTest.cs | 4 +- ...ollapserBatchSizeDistributionStreamTest.cs | 0 .../RollingCollapserEventCounterStreamTest.cs | 0 .../RollingCommandEventCounterStreamTest.cs | 0 ...ingCommandLatencyDistributionStreamTest.cs | 0 .../RollingCommandMaxConcurrencyStreamTest.cs | 0 ...RollingThreadPoolEventCounterStreamTest.cs | 0 ...llingThreadPoolMaxConcurrencyStreamTest.cs | 0 .../HystrixCommandCompletionStreamTest.cs | 0 .../Metric/HystrixThreadEventStreamTest.cs | 0 .../Sample/HystrixUtilizationStreamTest.cs | 0 .../HystrixMetricsStreamOptionsTest.cs | 0 .../HystrixMetricsStreamPublisherTest.cs | 4 +- .../MetricsStream/SerializeTest.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Serial/SerialHystrixRequestEventsTest.cs | 0 ...oe.CircuitBreaker.HystrixBase.Test.csproj} | 13 +- .../HystrixConcurrencyStrategyTest.cs | 0 .../HystrixMetricsPublisherFactoryTest.cs | 4 +- .../TestCircuitBreaker.cs | 0 .../TestCommandBuilder.cs | 0 .../TestHystrixCommand.cs | 0 .../TestableExecutionHook.cs | 0 .../Util/HystrixRollingNumberTest.cs | 130 +- .../Util/HystrixRollingPercentileTest.cs | 14 +- .../Util/HystrixTimerTest.cs | 0 .../xunit.runner.json | 0 .../HystrixServiceCollectionExtensionsTest.cs | 16 +- ...toe.CircuitBreaker.HystrixCore.Test.csproj | 1 + 265 files changed, 4854 insertions(+), 5345 deletions(-) delete mode 100644 src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixBaseOptions.cs delete mode 100644 src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapserOptions.cs delete mode 100644 src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCollapserOptions.cs delete mode 100644 src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandOptions.cs delete mode 100644 src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPoolOptions.cs delete mode 100644 src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixRequestEvents.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/AbstractCommand.cs (71%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/CircuitBreaker/HystrixCircuitBreakerFactory.cs (88%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/CircuitBreaker/HystrixCircuitBreakerImpl.cs (89%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/CircuitBreaker/NoOpCircuitBreaker.cs (89%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Collapser/CollapsedRequest.cs (98%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/CollapsedTask.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Collapser/ICollapserTimer.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Collapser/RealCollapserTimer.cs (81%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Collapser/RequestBatch.cs (83%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Collapser/RequestCollapser.cs (63%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Collapser/RequestCollapserFactory.cs (88%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/CollapserEventTypeHelper.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Config/HystrixCollapserConfiguration.cs (86%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Config/HystrixCommandConfiguration.cs (82%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Config/HystrixConfiguration.cs (69%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Config/HystrixConfigurationStream.cs (88%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Config/HystrixThreadPoolConfiguration.cs (89%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Exceptions/FailureType.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Exceptions/HystrixBadRequestException.cs (81%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Exceptions/HystrixRuntimeException.cs (90%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Exceptions/HystrixTimeoutException.cs (81%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Exceptions/RejectedExecutionException.cs (83%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/ExecutionResult.cs (69%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/HealthCounts.cs create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/HystrixBaseOptions.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixCachedTask.cs (64%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixCollapser.cs (84%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixCollapserMetrics.cs (84%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapserOptions.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixCommand.cs (56%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixCommandMetrics.cs (76%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixCommandOptions.cs (55%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixCounters.cs (76%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/HystrixEventType.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core/HystrixEventType.cs => Steeltoe.CircuitBreaker.HystrixBase/HystrixEventTypeHelper.cs} (50%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixMetrics.cs (75%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixRequestCache.cs (76%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixRequestLog.cs (65%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixThreadPoolMetrics.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/HystrixThreadPoolOptions.cs (61%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/ICollapsedRequest.cs (93%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixCircuitBreaker.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixCollapserKey.cs (81%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCollapserOptions.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixCommandGroupKey.cs (51%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixCommandKey.cs (56%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandOptions.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixExecutable.cs (87%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixInvokable.cs (83%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixInvokableInfo.cs (95%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixKey.cs (75%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixObservable.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixThreadPool.cs (54%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/IHystrixThreadPoolKey.cs (88%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPoolOptions.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/CachedValuesHistogram.cs (92%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/Metric/CommandAndCacheKey.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/BucketedCounterStream.cs (58%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/BucketedCumulativeCounterStream.cs (70%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/BucketedRollingCounterStream.cs (69%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/CumulativeCollapserEventCounterStream.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/CumulativeCommandEventCounterStream.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/CumulativeThreadPoolEventCounterStream.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/HealthCountsStream.cs (90%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/HystrixDashboardStream.cs (76%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingCollapserBatchSizeDistributionStream.cs (70%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingCollapserEventCounterStream.cs (73%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingCommandEventCounterStream.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingCommandLatencyDistributionStream.cs (91%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingCommandMaxConcurrencyStream.cs (90%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingCommandUserLatencyDistributionStream.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingConcurrencyStream.cs (88%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingDistributionStream.cs (81%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingThreadPoolEventCounterStream.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Consumer/RollingThreadPoolMaxConcurrencyStream.cs (85%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/Metric/ExecutionSignature.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixCollapserEvent.cs (96%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixCollapserEventStream.cs (87%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixCommandCompletion.cs (90%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixCommandCompletionStream.cs (90%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixCommandEvent.cs (82%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixCommandExecutionStarted.cs (96%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixCommandStartStream.cs (88%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixRequestEvents.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixRequestEventsStream.cs (85%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixThreadEventStream.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixThreadPoolCompletionStream.cs (87%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/HystrixThreadPoolStartStream.cs (86%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/IHystrixEvent.cs (91%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/IHystrixEventStream.cs (83%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Sample/HystrixCommandUtilization.cs (95%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Sample/HystrixThreadPoolUtilization.cs (91%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Sample/HystrixUtilization.cs (79%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Metric/Sample/HystrixUtilizationStream.cs (87%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/MetricsStream/HystrixMetricsStreamOptions.cs (93%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/MetricsStream/HystrixMetricsStreamPublisher.cs (83%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/MetricsStream/Serialize.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Properties/AssemblyInfo.cs (57%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/README.md (100%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Serial/SerialHystrixConfiguration.cs (99%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Serial/SerialHystrixDashboardData.cs (85%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Serial/SerialHystrixRequestEvents.cs (86%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Serial/SerialHystrixUtilization.cs (78%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Serial/SerializationExtensions.cs (97%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core/Steeltoe.CircuitBreaker.Hystrix.Core.csproj => Steeltoe.CircuitBreaker.HystrixBase/Steeltoe.CircuitBreaker.HystrixBase.csproj} (71%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/HystrixConcurrencyStrategy.cs (89%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/HystrixConcurrencyStrategyDefault.cs (67%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/HystrixQueuedTaskScheduler.cs (87%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/HystrixRequestContext.cs (74%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/HystrixRequestVariableDefault.cs (89%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/HystrixSyncTaskScheduler.cs (72%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/HystrixTaskScheduler.cs (93%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/IHystrixRequestVariable.cs (83%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Concurrency/IHystrixTaskScheduler.cs (90%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/EventNotifier/HystrixEventNotifier.cs (93%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/EventNotifier/HystrixEventNotifierDefault.cs (84%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/ExecutionHook/HystrixCommandExecutionHook.cs (77%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/ExecutionHook/HystrixCommandExecutionHookDefault.cs (81%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/HystrixPlugins.cs (66%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/HystrixMetricsPublisher.cs (96%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/HystrixMetricsPublisherCollapserDefault.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/HystrixMetricsPublisherCommandDefault.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/HystrixMetricsPublisherDefault.cs (85%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/HystrixMetricsPublisherFactory.cs (65%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/HystrixMetricsPublisherThreadPoolDefault.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/IHystrixMetricsPublisherCollapser.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/IHystrixMetricsPublisherCommand.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Metrics/IHystrixMetricsPublisherThreadPool.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Options/HystrixDynamicOptionsDefault.cs (91%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Options/HystrixOptionsFactory.cs (82%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Options/HystrixOptionsStrategy.cs (90%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Options/HystrixOptionsStrategyDefault.cs (78%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Strategy/Options/IHystrixDynamicOptions.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/ThreadPool/HystrixThreadPoolDefault.cs (85%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/ThreadPool/HystrixThreadPoolFactory.cs (74%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPoolEventTypeHelper.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/TimerReference.cs (93%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/Util/ActualTime.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/AtomicBoolean.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/AtomicInteger.cs (94%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/AtomicIntegerArray.cs (84%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/AtomicLong.cs (93%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/AtomicReference.cs (85%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/AtomicReferenceArray.cs (95%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/ConcurrentDictionaryExtensions.cs (86%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/HystrixRollingNumber.cs (68%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEvent.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingNumberEvent.cs => Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEventHelper.cs} (68%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/HystrixRollingPercentile.cs (73%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/HystrixTimer.cs (91%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixBase/Util/ITime.cs rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/ITimerListener.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/LongAdder.cs (92%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/LongMaxUpdater.cs (85%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/ObservableExtensions.cs (72%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/SemaphoreSlimExtensions.cs (91%) rename src/{Steeltoe.CircuitBreaker.Hystrix.Core => Steeltoe.CircuitBreaker.HystrixBase}/Util/Time.cs (82%) create mode 100644 src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddlewareOwin.cs create mode 100644 stylecop.json rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/CommonHystrixCommandTests.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Config/HystrixConfigurationStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/CountDownEventExtensions.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixCircuitBreakerTest.cs (97%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixCollapserTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixCommandMetricsTest.cs (98%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixCommandOptionsTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixCommandTest.cs (98%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixCommandTimeoutConcurrencyTesting.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixRequestCacheTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixRequestLogTest.cs (98%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixSubclassCommandTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixTestBase.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixThreadPoolMetricsTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixThreadPoolOptionsTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/HystrixThreadPoolTest.cs (96%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/CommandStreamTest.cs (98%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/CumulativeCollapserEventCounterStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/CumulativeCommandEventCounterStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/CumulativeThreadPoolEventCounterStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/HealthCountsStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/HystrixDashboardStreamTest.cs (99%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/RollingCollapserBatchSizeDistributionStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/RollingCollapserEventCounterStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/RollingCommandEventCounterStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/RollingCommandLatencyDistributionStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/RollingCommandMaxConcurrencyStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/RollingThreadPoolEventCounterStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Consumer/RollingThreadPoolMaxConcurrencyStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/HystrixCommandCompletionStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/HystrixThreadEventStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Metric/Sample/HystrixUtilizationStreamTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/MetricsStream/HystrixMetricsStreamOptionsTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/MetricsStream/HystrixMetricsStreamPublisherTest.cs (92%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/MetricsStream/SerializeTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Properties/AssemblyInfo.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Serial/SerialHystrixRequestEventsTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test/Steeltoe.CircuitBreaker.Hystrix.Core.Test.csproj => Steeltoe.CircuitBreaker.HystrixBase.Test/Steeltoe.CircuitBreaker.HystrixBase.Test.csproj} (84%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Strategy/Concurrency/HystrixConcurrencyStrategyTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Strategy/Metrics/HystrixMetricsPublisherFactoryTest.cs (98%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/TestCircuitBreaker.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/TestCommandBuilder.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/TestHystrixCommand.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/TestableExecutionHook.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Util/HystrixRollingNumberTest.cs (83%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Util/HystrixRollingPercentileTest.cs (99%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/Util/HystrixTimerTest.cs (100%) rename test/{Steeltoe.CircuitBreaker.Hystrix.Core.Test => Steeltoe.CircuitBreaker.HystrixBase.Test}/xunit.runner.json (100%) diff --git a/.travis.yml b/.travis.yml index 308e3c8..2ca0b54 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,11 +6,11 @@ env: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 mono: none -dotnet: 2.0.0 +dotnet: 2.0.3 os: - linux - osx -osx_image: xcode8.2 +osx_image: xcode8.3 branches: only: - master diff --git a/CircuitBreaker.sln b/CircuitBreaker.sln index 36eceb7..70ac058 100644 --- a/CircuitBreaker.sln +++ b/CircuitBreaker.sln @@ -1,16 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2005 +VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C687B093-C2A5-4600-99A7-853C581FBBC0}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{100AA6E3-E1C8-41D0-A6AF-64AF3E5A2F7C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.CircuitBreaker.Hystrix.Core", "src\Steeltoe.CircuitBreaker.Hystrix.Core\Steeltoe.CircuitBreaker.Hystrix.Core.csproj", "{72098E45-C212-440F-B10B-A424177F53AC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.CircuitBreaker.Hystrix.Core.Test", "test\Steeltoe.CircuitBreaker.Hystrix.Core.Test\Steeltoe.CircuitBreaker.Hystrix.Core.Test.csproj", "{6A2F3E57-BEE2-41CB-92B2-6F64E6963B14}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4F262F8F-A478-4C8C-AA23-48B1103E5B8B}" ProjectSection(SolutionItems) = preProject .travis.yml = .travis.yml @@ -61,20 +57,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.CircuitBreaker.Hys EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test", "test\Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test\Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test.csproj", "{52E3AE73-56C6-41B1-8C79-C1960F5C58F6}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.CircuitBreaker.HystrixBase", "src\Steeltoe.CircuitBreaker.HystrixBase\Steeltoe.CircuitBreaker.HystrixBase.csproj", "{BE323306-CFF2-4FCA-8EA6-C994861A2E8E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.CircuitBreaker.HystrixBase.Test", "test\Steeltoe.CircuitBreaker.HystrixBase.Test\Steeltoe.CircuitBreaker.HystrixBase.Test.csproj", "{703E56B4-6467-4E94-9A41-44F7FBD8A701}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {72098E45-C212-440F-B10B-A424177F53AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72098E45-C212-440F-B10B-A424177F53AC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72098E45-C212-440F-B10B-A424177F53AC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72098E45-C212-440F-B10B-A424177F53AC}.Release|Any CPU.Build.0 = Release|Any CPU - {6A2F3E57-BEE2-41CB-92B2-6F64E6963B14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6A2F3E57-BEE2-41CB-92B2-6F64E6963B14}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6A2F3E57-BEE2-41CB-92B2-6F64E6963B14}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6A2F3E57-BEE2-41CB-92B2-6F64E6963B14}.Release|Any CPU.Build.0 = Release|Any CPU {1662B8D3-9E41-4A94-9759-52975E62CA34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1662B8D3-9E41-4A94-9759-52975E62CA34}.Debug|Any CPU.Build.0 = Debug|Any CPU {1662B8D3-9E41-4A94-9759-52975E62CA34}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -115,13 +107,19 @@ Global {52E3AE73-56C6-41B1-8C79-C1960F5C58F6}.Debug|Any CPU.Build.0 = Debug|Any CPU {52E3AE73-56C6-41B1-8C79-C1960F5C58F6}.Release|Any CPU.ActiveCfg = Release|Any CPU {52E3AE73-56C6-41B1-8C79-C1960F5C58F6}.Release|Any CPU.Build.0 = Release|Any CPU + {BE323306-CFF2-4FCA-8EA6-C994861A2E8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE323306-CFF2-4FCA-8EA6-C994861A2E8E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE323306-CFF2-4FCA-8EA6-C994861A2E8E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE323306-CFF2-4FCA-8EA6-C994861A2E8E}.Release|Any CPU.Build.0 = Release|Any CPU + {703E56B4-6467-4E94-9A41-44F7FBD8A701}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {703E56B4-6467-4E94-9A41-44F7FBD8A701}.Debug|Any CPU.Build.0 = Debug|Any CPU + {703E56B4-6467-4E94-9A41-44F7FBD8A701}.Release|Any CPU.ActiveCfg = Release|Any CPU + {703E56B4-6467-4E94-9A41-44F7FBD8A701}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {72098E45-C212-440F-B10B-A424177F53AC} = {C687B093-C2A5-4600-99A7-853C581FBBC0} - {6A2F3E57-BEE2-41CB-92B2-6F64E6963B14} = {100AA6E3-E1C8-41D0-A6AF-64AF3E5A2F7C} {1662B8D3-9E41-4A94-9759-52975E62CA34} = {C687B093-C2A5-4600-99A7-853C581FBBC0} {488AF4E6-5843-49F4-9141-1247D0601055} = {C687B093-C2A5-4600-99A7-853C581FBBC0} {87A66E60-712C-42A2-AC6A-CBE3CF77A83C} = {C687B093-C2A5-4600-99A7-853C581FBBC0} @@ -132,6 +130,8 @@ Global {FB2330AF-37FA-4794-B16C-7AC1046DE307} = {100AA6E3-E1C8-41D0-A6AF-64AF3E5A2F7C} {4BC245DD-2067-4938-8C09-AB938FFF8BCD} = {C687B093-C2A5-4600-99A7-853C581FBBC0} {52E3AE73-56C6-41B1-8C79-C1960F5C58F6} = {100AA6E3-E1C8-41D0-A6AF-64AF3E5A2F7C} + {BE323306-CFF2-4FCA-8EA6-C994861A2E8E} = {C687B093-C2A5-4600-99A7-853C581FBBC0} + {703E56B4-6467-4E94-9A41-44F7FBD8A701} = {100AA6E3-E1C8-41D0-A6AF-64AF3E5A2F7C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {58720A8A-389C-477F-BD36-2DB217BAF674} diff --git a/README.md b/README.md index c78733f..a3f55d3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # .NET Circuit Breaker Frameworks + Cloud-native architectures are typically composed of multiple layers of distributed services. End-user requests may comprise multiple calls to these services, and if a lower-level service fails, the failure can cascade up to the end user and spread to other dependent services. Heavy traffic to a failing service can also make it difficult to repair. Using Circuit Breaker patterns, you can prevent failures from cascading and provide fallback behavior until a failing service is restored to normal operation. When applied to a service, a circuit breaker framework watches for failing calls to the service. If failures reach a certain threshold, it “opens” the circuit and automatically redirects calls to the specified fallback mechanism. This gives the failing service time to recover. @@ -19,17 +20,20 @@ Linux/OS X Master: [![Travis Master](https://travis-ci.org/SteeltoeOSS/CircuitBr Linux/OSX Dev: [![Travis Dev](https://travis-ci.org/SteeltoeOSS/CircuitBreaker.svg?branch=dev)](https://travis-ci.org/SteeltoeOSS/CircuitBreaker) -# .NET Runtime & Framework Support +## .NET Runtime & Framework Support + The packages are intended to support both .NET 4.6+ and .NET Core (CoreCLR/CoreFX) runtimes. They are built and unit tested on Windows, Linux and OSX. While the primary usage of the providers is intended to be with ASP.NET Core applications, they should also work fine with UWP, Console and ASP.NET 4.x apps. -Currently all of the code and samples have been tested on .NET Core 1.1, .NET 4.6.x, and on ASP.NET Core 1.1.0. -# Usage +Currently all of the code and samples have been tested on .NET Core 2.0, .NET 4.6.x, and on ASP.NET Core 2.0.0. + +## Usage For more information on how to use these components see the online [Steeltoe documentation](http://steeltoe.io/). -# Nuget Feeds +## Nuget Feeds + All new development is done on the dev branch. More stable versions of the packages can be found on the master branch. The latest prebuilt packages from each branch can be found on one of two MyGet feeds. Released version can be found on nuget.org. [Development feed (Less Stable)](https://www.myget.org/gallery/steeltoedev) - https://www.myget.org/gallery/steeltoedev @@ -38,53 +42,53 @@ All new development is done on the dev branch. More stable versions of the packa [Release or Release Candidate feed](https://www.nuget.org/) - https://www.nuget.org/. -# Building Pre-requisites +## Building Pre-requisites + To build and run the unit tests: -1. .NET Core SDK 1.0.4 or greater -2. .NET Core Runtime 1.1 +1. .NET Core SDK 2.0.3 or greater +1. .NET Core Runtime 2.0.3 + +## Building Packages & Running Tests - Windows -# Building Packages & Running Tests - Windows To build the packages on windows: 1. git clone ... -2. cd clone directory -3. Install .NET Core SDK -4. dotnet restore src -5. cd src\project (e.g. cd src\Steeltoe.CircuitBreaker.Hystrix.Core) -6. dotnet pack --configuration Release or Debug +1. cd clone directory +1. cd src/project (e.g. cd src/Steeltoe.CircuitBreaker.HystrixBase) +1. dotnet restore +1. dotnet pack --configuration Release or Debug -The resulting artifacts can be found in the bin folder under the corresponding project. (e.g. src/Steeltoe.CircuitBreaker.Hystrix.Core/bin +The resulting artifacts can be found in the bin folder under the corresponding project. (e.g. src/Steeltoe.CircuitBreaker.HystrixBase/bin To run the unit tests: 1. git clone ... -2. cd clone directory -3. Install .NET Core SDK -4. dotnet restore test -5. cd test\test project (e.g. cd test\Steeltoe.CircuitBreaker.Hystrix.Core.Test) -6. dotnet xunit -verbose +1. cd clone directory +1. cd test/test project (e.g. cd test/Steeltoe.CircuitBreaker.HystrixBase.Test) +1. dotnet restore +1. dotnet xunit -verbose + +## Building Packages & Running Tests - Linux/OSX -# Building Packages & Running Tests - Linux/OSX To build the packages on Linux/OSX: 1. git clone ... -2. cd clone directory -3. Install .NET Core SDK -4. dotnet restore src -5. cd src/project (e.g.. cd src/Steeltoe.CircuitBreaker.Hystrix.Core) -6. dotnet pack --configuration Release or Debug +1. cd clone directory +1. cd src/project (e.g.. cd src/Steeltoe.CircuitBreaker.HystrixBase) +1. dotnet restore +1. dotnet pack --configuration Release or Debug -The resulting artifacts can be found in the bin folder under the corresponding project. (e.g. src/Steeltoe.CircuitBreaker.Hystrix.Core/bin +The resulting artifacts can be found in the bin folder under the corresponding project. (e.g. src/Steeltoe.CircuitBreaker.HystrixBase/bin To run the unit tests: 1. git clone ... -2. cd clone directory -3. Install .NET Core SDK -4. dotnet restore test -5. cd test\test project (e.g. cd test/Steeltoe.CircuitBreaker.Hystrix.Core.Test) -6. dotnet xunit -verbose -framework netcoreapp1.1 +1. cd clone directory +1. cd test/test project (e.g. cd test/Steeltoe.CircuitBreaker.HystrixBase.Test) +1. dotnet restore +1. dotnet xunit -verbose -framework netcoreapp2.0 + +## Sample Applications -# Sample Applications See the [Samples](https://github.com/SteeltoeOSS/Samples) repo for examples of how to use these packages. diff --git a/appveyor.yml b/appveyor.yml index 663e668..0bcc07a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,13 +18,13 @@ build_script: artifacts: - path: 'src\Steeltoe.CircuitBreaker.HystrixCore\bin\Release\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.HystrixAutofac\bin\Release\*.nupkg' -- path: 'src\Steeltoe.CircuitBreaker.Hystrix.Core\bin\Release\*.nupkg' +- path: 'src\Steeltoe.CircuitBreaker.HystrixBase\bin\Release\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore\bin\Release\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore\bin\Release\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac\bin\Release\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.HystrixCore\bin\Debug\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.HystrixAutofac\bin\Debug\*.nupkg' -- path: 'src\Steeltoe.CircuitBreaker.Hystrix.Core\bin\Debug\*.nupkg' +- path: 'src\Steeltoe.CircuitBreaker.HystrixBase\bin\Debug\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore\bin\Debug\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore\bin\Debug\*.nupkg' - path: 'src\Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac\bin\Debug\*.nupkg' diff --git a/config/versions-dev.props b/config/versions-dev.props index 8a46f65..8975748 100644 --- a/config/versions-dev.props +++ b/config/versions-dev.props @@ -2,19 +2,20 @@ $(STEELTOE_VERSION) $(STEELTOE_DASH_VERSION_SUFFIX) - 2.0.0-dev-00192 - 2.0.0-dev-00018 + 2.0.0-dev-00200 + 2.0.0-dev-00040 2.0.0 2.0.0 2.0.0 2.0.0 - 4.3.1 - 4.3.0 - 10.0.1 + 4.3.3 + 4.4.0 + 1.0.2 + 10.0.3 5.0.1 - 15.3.0 - 2.3.0-beta4-build3742 - 2.3.0-beta4-build3742 + 15.5.0 + 2.3.1 + 2.3.1 2.0.0 3.1.1 diff --git a/config/versions-master.props b/config/versions-master.props index 8ab14df..6e06322 100644 --- a/config/versions-master.props +++ b/config/versions-master.props @@ -2,19 +2,20 @@ $(STEELTOE_VERSION) $(STEELTOE_DASH_VERSION_SUFFIX) - 2.0.0-master-00173 - 2.0.0-master-00018 + 2.0.0-master-00201 + 2.0.0-master-00041 2.0.0 2.0.0 2.0.0 2.0.0 - 4.3.1 - 4.3.0 - 10.0.1 - 4.1.3 - 15.3.0 - 2.3.0-beta4-build3742 - 2.3.0-beta4-build3742 + 4.3.3 + 4.4.0 + 1.0.2 + 10.0.3 + 5.0.1 + 15.5.0 + 2.3.1 + 2.3.1 2.0.0 3.1.1 diff --git a/config/versions.props b/config/versions.props index 151b8dc..4aa6c3f 100644 --- a/config/versions.props +++ b/config/versions.props @@ -2,19 +2,20 @@ $(STEELTOE_VERSION) $(STEELTOE_DASH_VERSION_SUFFIX) - 2.0.0 - 2.0.0-dev + 2.0.0-rc1 + 2.0.0-rc1 2.0.0 2.0.0 2.0.0 2.0.0 - 4.3.1 - 4.3.0 - 10.0.1 - 4.1.3 - 15.3.0 - 2.3.0-beta4-build3742 - 2.3.0-beta4-build3742 + 4.3.3 + 4.4.0 + 1.0.2 + 10.0.3 + 5.0.1 + 15.5.0 + 2.3.1 + 2.3.1 2.0.0 3.1.1 diff --git a/scripts/appveyor_build.cmd b/scripts/appveyor_build.cmd index c8f3c23..372bc4b 100644 --- a/scripts/appveyor_build.cmd +++ b/scripts/appveyor_build.cmd @@ -1,20 +1,20 @@ :: @ECHO OFF :: Build packages -cd src\Steeltoe.CircuitBreaker.Hystrix.Core +cd src\Steeltoe.CircuitBreaker.HystrixBase dotnet restore --configfile ..\..\nuget.config IF NOT "%APPVEYOR_REPO_TAG_NAME%"=="" ( IF NOT "%STEELTOE_VERSION_SUFFIX%"=="" ( dotnet pack --configuration %BUILD_TYPE% --version-suffix %STEELTOE_VERSION_SUFFIX% - nuget add "bin\%BUILD_TYPE%\Steeltoe.CircuitBreaker.Hystrix.Core.%STEELTOE_VERSION%-%STEELTOE_VERSION_SUFFIX%.nupkg" -Source "%USERPROFILE%\localfeed" + nuget add "bin\%BUILD_TYPE%\Steeltoe.CircuitBreaker.HystrixBase.%STEELTOE_VERSION%-%STEELTOE_VERSION_SUFFIX%.nupkg" -Source "%USERPROFILE%\localfeed" ) ELSE ( dotnet pack --configuration %BUILD_TYPE% - nuget add "bin\%BUILD_TYPE%\Steeltoe.CircuitBreaker.Hystrix.Core.%STEELTOE_VERSION%.nupkg" -Source "%USERPROFILE%\localfeed" + nuget add "bin\%BUILD_TYPE%\Steeltoe.CircuitBreaker.HystrixBase.%STEELTOE_VERSION%.nupkg" -Source "%USERPROFILE%\localfeed" ) ) IF "%APPVEYOR_REPO_TAG_NAME%"=="" (dotnet pack --configuration %BUILD_TYPE% --version-suffix %STEELTOE_VERSION_SUFFIX% --include-symbols --include-source) -IF "%APPVEYOR_REPO_TAG_NAME%"=="" (nuget add -Source %USERPROFILE%\localfeed bin\%BUILD_TYPE%\Steeltoe.CircuitBreaker.Hystrix.Core.%STEELTOE_VERSION%-%STEELTOE_VERSION_SUFFIX%.nupkg) +IF "%APPVEYOR_REPO_TAG_NAME%"=="" (nuget add -Source %USERPROFILE%\localfeed bin\%BUILD_TYPE%\Steeltoe.CircuitBreaker.HystrixBase.%STEELTOE_VERSION%-%STEELTOE_VERSION_SUFFIX%.nupkg) cd ..\.. cd src\Steeltoe.CircuitBreaker.HystrixCore diff --git a/scripts/appveyor_tests.cmd b/scripts/appveyor_tests.cmd index 996c29c..39d2118 100644 --- a/scripts/appveyor_tests.cmd +++ b/scripts/appveyor_tests.cmd @@ -1,7 +1,7 @@ @ECHO OFF :: Run unit tests -cd test\Steeltoe.CircuitBreaker.Hystrix.Core.Test +cd test\Steeltoe.CircuitBreaker.HystrixBase.Test dotnet restore --configfile ..\..\nuget.config dotnet xunit -verbose if not "%errorlevel%"=="0" goto failure diff --git a/scripts/travis_build.sh b/scripts/travis_build.sh index c03b3a0..fab4422 100755 --- a/scripts/travis_build.sh +++ b/scripts/travis_build.sh @@ -2,7 +2,7 @@ echo Code is built in Unit Tests -cd src/Steeltoe.CircuitBreaker.Hystrix.Core +cd src/Steeltoe.CircuitBreaker.HystrixBase dotnet restore --configfile ../../nuget.config cd ../.. diff --git a/scripts/travis_test.sh b/scripts/travis_test.sh index 9e70318..587cc86 100755 --- a/scripts/travis_test.sh +++ b/scripts/travis_test.sh @@ -1,7 +1,7 @@ #!/bin/bash # Run unit tests -cd test/Steeltoe.CircuitBreaker.Hystrix.Core.Test +cd test/Steeltoe.CircuitBreaker.HystrixBase.Test dotnet restore --configfile ../../nuget.config dotnet xunit -verbose -framework netcoreapp2.0 if [[ $? != 0 ]]; then exit 1 ; fi diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixBaseOptions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixBaseOptions.cs deleted file mode 100644 index 490506e..0000000 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixBaseOptions.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Steeltoe.CircuitBreaker.Hystrix -{ - public abstract class HystrixBaseOptions - { - - internal protected IHystrixDynamicOptions dynamic; - - protected HystrixBaseOptions(IHystrixDynamicOptions dynamicOptions) - { - this.dynamic = dynamicOptions; - } - - protected virtual bool GetBoolean(string prefix, string key, string property, bool globalDefault, bool? instanceDefaultFromCode) - { - bool result = globalDefault; - result = (dynamic != null) ? dynamic.GetBoolean(prefix + ":default:" + property, result) : result; // dynamic global default - result = instanceDefaultFromCode.HasValue ? instanceDefaultFromCode.Value : result; // instance default from code - result = (dynamic != null) ? dynamic.GetBoolean(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value - return result; - - } - protected virtual int GetInteger(string prefix, string key, string property, int globalDefault, int? instanceDefaultFromCode) - { - int result = globalDefault; - result = (dynamic != null) ? dynamic.GetInteger(prefix + ":default:" + property, result) : result; // dynamic global default - result = instanceDefaultFromCode.HasValue ? instanceDefaultFromCode.Value : result; // instance default from code - result = (dynamic != null) ? dynamic.GetInteger(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value - return result; - - } - protected virtual long GetLong(string prefix, string key, string property, long globalDefault, long? instanceDefaultFromCode) - { - long result = globalDefault; - result = (dynamic != null) ? dynamic.GetLong(prefix + ":default:" + property, result) : result; // dynamic global default - result = instanceDefaultFromCode.HasValue ? instanceDefaultFromCode.Value : result; // instance default from code - result = (dynamic != null) ? dynamic.GetLong(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value - return result; - - } - protected virtual string GetString(string prefix, string key, string property, string globalDefault, string instanceDefaultFromCode) - { - string result = globalDefault; - result = (dynamic != null) ? dynamic.GetString(prefix + ":default:" + property, result) : result; // dynamic global default - result = instanceDefaultFromCode != null ? instanceDefaultFromCode : result; // instance default from code - result = (dynamic != null) ? dynamic.GetString(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value - return result; - - } - } -} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapserOptions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapserOptions.cs deleted file mode 100644 index d0abf1f..0000000 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapserOptions.cs +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright 2017 the original author or authors. -// -// 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. - -using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options; -using System; - -namespace Steeltoe.CircuitBreaker.Hystrix -{ - public class HystrixCollapserOptions : HystrixBaseOptions, IHystrixCollapserOptions - { - protected const string HYSTRIX_COLLAPSER_PREFIX = "hystrix:collapser"; - - internal const int default_maxRequestsInBatch = Int32.MaxValue; - internal const int default_timerDelayInMilliseconds = 10; - internal const bool default_requestCacheEnabled = true; - internal const int default_metricsRollingStatisticalWindow = 10000;// default => statisticalWindow: 10000 = 10 seconds (and default of 10 buckets so each bucket is 1 second) - internal const int default_metricsRollingStatisticalWindowBuckets = 10;// default => statisticalWindowBuckets: 10 = 10 buckets in a 10 second window so each bucket is 1 second - internal const bool default_metricsRollingPercentileEnabled = true; - internal const int default_metricsRollingPercentileWindow = 60000; // default to 1 minute for RollingPercentile - internal const int default_metricsRollingPercentileWindowBuckets = 6; // default to 6 buckets (10 seconds each in 60 second window) - internal const int default_metricsRollingPercentileBucketSize = 100; // default to 100 values max per bucket - private IHystrixCollapserOptions defaults; - - public HystrixCollapserOptions(IHystrixCollapserKey collapserKey, IHystrixCollapserOptions defaults = null, IHystrixDynamicOptions dynamic = null) - : this(collapserKey, RequestCollapserScope.REQUEST, defaults, dynamic) - { - } - - - public HystrixCollapserOptions(IHystrixCollapserKey key, RequestCollapserScope scope, IHystrixCollapserOptions defaults = null, IHystrixDynamicOptions dynamic = null) - :base(dynamic) - { - this.CollapserKey = key; - this.Scope = scope; - this.defaults = defaults; - - this.MaxRequestsInBatch = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "maxRequestsInBatch", default_maxRequestsInBatch, defaults?.MaxRequestsInBatch); - this.TimerDelayInMilliseconds = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "timerDelayInMilliseconds", default_timerDelayInMilliseconds, defaults?.TimerDelayInMilliseconds); - this.RequestCacheEnabled = GetBoolean(HYSTRIX_COLLAPSER_PREFIX, key.Name, "requestCache.enabled", default_requestCacheEnabled, defaults?.RequestCacheEnabled); - this.MetricsRollingStatisticalWindowInMilliseconds = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingStats.timeInMilliseconds", default_metricsRollingStatisticalWindow, defaults?.MetricsRollingStatisticalWindowInMilliseconds); - this.MetricsRollingStatisticalWindowBuckets = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingStats.numBuckets", default_metricsRollingStatisticalWindowBuckets, defaults?.MetricsRollingStatisticalWindowBuckets); - this.MetricsRollingPercentileEnabled = GetBoolean(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.enabled", default_metricsRollingPercentileEnabled, defaults?.MetricsRollingPercentileEnabled); - this.MetricsRollingPercentileWindowInMilliseconds = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.timeInMilliseconds", default_metricsRollingPercentileWindow, defaults?.MetricsRollingPercentileWindowInMilliseconds); - this.MetricsRollingPercentileWindowBuckets = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.numBuckets", default_metricsRollingPercentileWindowBuckets, defaults?.MetricsRollingPercentileWindowBuckets); - this.MetricsRollingPercentileBucketSize = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.bucketSize", default_metricsRollingPercentileBucketSize, defaults?.MetricsRollingPercentileBucketSize); - } - - - public IHystrixCollapserKey CollapserKey { get; set; } - - public RequestCollapserScope Scope { get; set; } - - /** - * Whether request caching is enabled for {@link HystrixCollapser#execute} and {@link HystrixCollapser#queue} invocations. - * - * @return {@code HystrixProperty} - */ - public bool RequestCacheEnabled { get; set; } - - /** - * The maximum number of requests allowed in a batch before triggering a batch execution. - * - * @return {@code HystrixProperty} - */ - public int MaxRequestsInBatch { get; set; } - - /** - * The number of milliseconds between batch executions (unless {@link #maxRequestsInBatch} is hit which will cause a batch to execute early. - * - * @return {@code HystrixProperty} - */ - public int TimerDelayInMilliseconds { get; set; } - - - /** - * Duration of statistical rolling window in milliseconds. This is passed into {@link HystrixRollingNumber} inside {@link HystrixCommandMetrics}. - * - * @return {@code HystrixProperty} - */ - public int MetricsRollingStatisticalWindowInMilliseconds { get; set; } - - - /** - * Number of buckets the rolling statistical window is broken into. This is passed into {@link HystrixRollingNumber} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - public int MetricsRollingStatisticalWindowBuckets { get; set; } - - - /** - * Whether percentile metrics should be captured using {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - public bool MetricsRollingPercentileEnabled { get; set; } - - - /** - * Duration of percentile rolling window in milliseconds. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - public int MetricsRollingPercentileWindowInMilliseconds { get; set; } - - /** - * Number of buckets the rolling percentile window is broken into. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - public int MetricsRollingPercentileWindowBuckets { get; set; } - - - /** - * Maximum number of values stored in each bucket of the rolling percentile. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - public int MetricsRollingPercentileBucketSize { get; set; } - - } -} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCollapserOptions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCollapserOptions.cs deleted file mode 100644 index c3df4a9..0000000 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCollapserOptions.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright 2017 the original author or authors. -// -// 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. - - -namespace Steeltoe.CircuitBreaker.Hystrix -{ - public interface IHystrixCollapserOptions - { - - IHystrixCollapserKey CollapserKey { get; set; } - - RequestCollapserScope Scope { get; set; } - - /** - * Whether request caching is enabled for {@link HystrixCollapser#execute} and {@link HystrixCollapser#queue} invocations. - * - * @return {@code HystrixProperty} - */ - bool RequestCacheEnabled { get; set; } - - /** - * The maximum number of requests allowed in a batch before triggering a batch execution. - * - * @return {@code HystrixProperty} - */ - int MaxRequestsInBatch { get; set; } - - /** - * The number of milliseconds between batch executions (unless {@link #maxRequestsInBatch} is hit which will cause a batch to execute early. - * - * @return {@code HystrixProperty} - */ - int TimerDelayInMilliseconds { get; set; } - - - /** - * Duration of statistical rolling window in milliseconds. This is passed into {@link HystrixRollingNumber} inside {@link HystrixCommandMetrics}. - * - * @return {@code HystrixProperty} - */ - int MetricsRollingStatisticalWindowInMilliseconds { get; set; } - - - /** - * Number of buckets the rolling statistical window is broken into. This is passed into {@link HystrixRollingNumber} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - int MetricsRollingStatisticalWindowBuckets { get; set; } - - - /** - * Whether percentile metrics should be captured using {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - bool MetricsRollingPercentileEnabled { get; set; } - - - /** - * Duration of percentile rolling window in milliseconds. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - int MetricsRollingPercentileWindowInMilliseconds { get; set; } - - /** - * Number of buckets the rolling percentile window is broken into. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - int MetricsRollingPercentileWindowBuckets { get; set; } - - - /** - * Maximum number of values stored in each bucket of the rolling percentile. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}. - * - * @return {@code HystrixProperty} - */ - int MetricsRollingPercentileBucketSize { get; set; } - } -} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandOptions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandOptions.cs deleted file mode 100644 index b632f25..0000000 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandOptions.cs +++ /dev/null @@ -1,253 +0,0 @@ -// -// Copyright 2017 the original author or authors. -// -// 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. - - -namespace Steeltoe.CircuitBreaker.Hystrix -{ - public interface IHystrixCommandOptions - { - IHystrixCommandGroupKey GroupKey { get; set; } - - IHystrixCommandKey CommandKey { get; set; } - - IHystrixThreadPoolKey ThreadPoolKey { get; set; } - - /// - /// Whether to use a or not. If false no circuit-breaker logic will be used and all requests permitted. - /// - /// This is similar in effect to except that continues tracking metrics and knowing whether it - /// should be open/closed, this property results in not even instantiating a circuit-breaker. - /// - /// - /// - /// {@code Boolean>} - bool CircuitBreakerEnabled { get; set; } - - /// - /// Error percentage threshold (as whole number such as 50) at which point the circuit breaker will trip open and reject requests. - /// - /// It will stay tripped for the duration defined in ; - /// - /// - /// The error percentage this is compared against comes from . - /// - /// - /// - /// {@code Integer>} - int CircuitBreakerErrorThresholdPercentage { get; set; } - - - /// - /// If true the will always return true to allow requests regardless of the error percentage from . - /// - /// The property takes precedence so if it set to true this property does nothing. - /// - /// - /// - /// {@code Boolean>} - bool CircuitBreakerForceClosed { get; set; } - - /// - /// If true the will always return false, causing the circuit to be open (tripped) and reject all requests. - /// - /// This property takes precedence over ; - /// - /// - /// - /// {@code Boolean>} - bool CircuitBreakerForceOpen { get; set; } - - /// - /// Minimum number of requests in the that must exist before the will trip. - /// - /// If below this number the circuit will not trip regardless of error percentage. - /// - /// - /// - /// {@code Integer>} - int CircuitBreakerRequestVolumeThreshold { get; set; } - - /// - /// The time in milliseconds after a trips open that it should wait before trying requests again. - /// - /// {@code Integer>} - int CircuitBreakerSleepWindowInMilliseconds { get; set; } - - /// - /// Number of concurrent requests permitted to . Requests beyond the concurrent limit will be rejected. - /// - /// Applicable only when == SEMAPHORE. - /// - /// - /// - /// {@code Integer>} - int ExecutionIsolationSemaphoreMaxConcurrentRequests { get; set; } - - /// - /// What isolation strategy will be executed with. - /// - /// If then it will be executed on a separate thread and concurrent requests limited by the number of threads in the thread-pool. - /// - /// - /// If then it will be executed on the calling thread and concurrent requests limited by the semaphore count. - /// - /// - /// - /// {@code Boolean>} - ExecutionIsolationStrategy ExecutionIsolationStrategy { get; set; } - - - /// - /// Whether the execution thread should attempt an interrupt (using ) when a thread times out. - /// - /// Applicable only when == THREAD. - /// - /// - /// - /// {@code Boolean>} - //public virtual bool ExecutionIsolationThreadInterruptOnTimeout { get; set; } - - /// - /// Whether the execution thread should be interrupted if the execution observable is unsubscribed or the future is cancelled via ). - /// - /// Applicable only when == THREAD. - /// - /// - /// - /// {@code Boolean>} - //public virtual bool ExecutionIsolationThreadInterruptOnFutureCancel { get; set; } - - - /// - /// Allow a dynamic override of the that will dynamically change which a executes on. - /// - /// Typically this should return NULL which will cause it to use the injected into a or derived from the . - /// - /// - /// When set the injected or derived values will be ignored and a new created (if necessary) and the will begin using the newly defined pool. - /// - /// - /// - /// {@code String>} - string ExecutionIsolationThreadPoolKeyOverride { get; set; } - - /// - /// Time in milliseconds at which point the command will timeout and halt execution. - /// - /// If == true and the command is thread-isolated, the executing thread will be interrupted. - /// If the command is semaphore-isolated and a , that command will get unsubscribed. - /// - /// - /// - /// - /// - /// {@code Integer>} - int ExecutionTimeoutInMilliseconds { get; set; } - - - /// - /// Whether the timeout mechanism is enabled for this command - /// - /// {@code Boolean>} - /// - /// @since 1.4.4 - bool ExecutionTimeoutEnabled { get; set; } - - - /// - /// Number of concurrent requests permitted to . Requests beyond the concurrent limit will fail-fast and not attempt retrieving a fallback. - /// - /// {@code Integer>} - int FallbackIsolationSemaphoreMaxConcurrentRequests { get; set; } - - - /// - /// Whether should be attempted when failure occurs. - /// - /// {@code Boolean>} - /// - /// @since 1.2 - bool FallbackEnabled { get; set; } - - /// - /// Time in milliseconds to wait between allowing health snapshots to be taken that calculate success and error percentages and affect status. - /// - /// On high-volume circuits the continual calculation of error percentage can become CPU intensive thus this controls how often it is calculated. - /// - /// - /// - /// {@code Integer>} - int MetricsHealthSnapshotIntervalInMilliseconds { get; set; } - - - /// - /// Maximum number of values stored in each bucket of the rolling percentile. This is passed into inside . - /// - /// {@code Integer>} - int MetricsRollingPercentileBucketSize { get; set; } - - /// - /// Whether percentile metrics should be captured using inside . - /// - /// {@code Boolean>} - bool MetricsRollingPercentileEnabled { get; set; } - - /// - /// Duration of percentile rolling window in milliseconds. This is passed into inside . - /// - /// {@code Integer>} - /// @deprecated Use - int MetricsRollingPercentileWindow { get; set; } - - /// - /// Duration of percentile rolling window in milliseconds. This is passed into inside . - /// - /// {@code Integer>} - int MetricsRollingPercentileWindowInMilliseconds { get; set; } - - - /// - /// Number of buckets the rolling percentile window is broken into. This is passed into inside . - /// - /// {@code Integer>} - int MetricsRollingPercentileWindowBuckets { get; set; } - /// - /// Duration of statistical rolling window in milliseconds. This is passed into inside . - /// - /// {@code Integer>} - int MetricsRollingStatisticalWindowInMilliseconds { get; set; } - - - /// - /// Number of buckets the rolling statistical window is broken into. This is passed into inside . - /// - /// {@code Integer>} - int MetricsRollingStatisticalWindowBuckets { get; set; } - - /// - /// Whether should be used with to provide de-duplication functionality via request-scoped caching. - /// - /// {@code Boolean>} - bool RequestCacheEnabled { get; set; } - - /// - /// Whether execution and events should be logged to . - /// - /// {@code Boolean>} - bool RequestLogEnabled { get; set; } - - IHystrixThreadPoolOptions ThreadPoolOptions { get; set; } - } -} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPoolOptions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPoolOptions.cs deleted file mode 100644 index dccbcc3..0000000 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPoolOptions.cs +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright 2017 the original author or authors. -// -// 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. - - -namespace Steeltoe.CircuitBreaker.Hystrix -{ - public interface IHystrixThreadPoolOptions - { - IHystrixThreadPoolKey ThreadPoolKey { get; } - - /// - /// Core thread-pool size that gets passed to - /// - /// {@code HystrixProperty} - int CoreSize { get; set; } - - /// - /// Maximum thread-pool size that gets passed to - /// - /// {@code HystrixProperty} - int MaximumSize { get; set; } - - /// - /// Keep-alive time in minutes that gets passed to - /// - /// {@code HystrixProperty} - int KeepAliveTimeMinutes { get; set; } - - - /// - /// Max queue size that gets passed to in - /// - /// This should only affect the instantiation of a threadpool - it is not eliglible to change a queue size on the fly. - /// For that, use . - /// - /// {@code HystrixProperty} - int MaxQueueSize { get; set; } - - /// - /// Queue size rejection threshold is an artificial "max" size at which rejections will occur even if has not been reached. This is done because the of a - /// can not be dynamically changed and we want to support dynamically changing the queue size that affects rejections. - /// - /// This is used by when queuing a thread for execution. - /// - /// - /// - /// {@code HystrixProperty} - int QueueSizeRejectionThreshold { get; set; } - - - bool AllowMaximumSizeToDivergeFromCoreSize { get; set; } - - - /// - /// Duration of statistical rolling window in milliseconds. This is passed into inside each instance. - /// - /// {@code HystrixProperty} - int MetricsRollingStatisticalWindowInMilliseconds { get; set; } - - /// - /// Number of buckets the rolling statistical window is broken into. This is passed into inside each instance. - /// - /// {@code HystrixProperty} - int MetricsRollingStatisticalWindowBuckets { get; set; } - - } -} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixRequestEvents.cs b/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixRequestEvents.cs deleted file mode 100644 index 76d5d4e..0000000 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixRequestEvents.cs +++ /dev/null @@ -1,224 +0,0 @@ -// -// Copyright 2017 the original author or authors. -// -// 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. -// - -using System; -using System.Collections.Generic; - - -namespace Steeltoe.CircuitBreaker.Hystrix.Metric -{ - public class HystrixRequestEvents - { - private readonly ICollection executions; - - public HystrixRequestEvents(ICollection executions) - { - this.executions = executions; - } - - public ICollection Executions - { - get { return executions; } - } - - public IDictionary> ExecutionsMappedToLatencies - { - get { - Dictionary cachingDetector = new Dictionary(); - List nonCachedExecutions = new List(executions.Count); - foreach (IHystrixInvokableInfo execution in executions) - { - if (execution.PublicCacheKey != null) - { - //eligible for caching - might be the initial, or might be from cache - CommandAndCacheKey key = new CommandAndCacheKey(execution.CommandKey.Name, execution.PublicCacheKey); - int count = -1; - if (cachingDetector.TryGetValue(key, out count)) - { - //key already seen - cachingDetector[key] = count + 1; - } - else - { - //key not seen yet - cachingDetector.Add(key, 0); - } - } - if (!execution.IsResponseFromCache) - { - nonCachedExecutions.Add(execution); - } - } - - Dictionary> commandDeduper = new Dictionary>(); - foreach (IHystrixInvokableInfo execution in nonCachedExecutions) - { - int cachedCount = 0; - string cacheKey = execution.PublicCacheKey; - if (cacheKey != null) - { - CommandAndCacheKey key = new CommandAndCacheKey(execution.CommandKey.Name, cacheKey); - cachingDetector.TryGetValue(key, out cachedCount); - } - ExecutionSignature signature; - if (cachedCount > 0) - { - //this has a RESPONSE_FROM_CACHE and needs to get split off - signature = ExecutionSignature.From(execution, cacheKey, cachedCount); - } - else - { - //nothing cached from this, can collapse further - signature = ExecutionSignature.From(execution); - } - List currentLatencyList = null; - if (commandDeduper.TryGetValue(signature, out currentLatencyList)) - { - currentLatencyList.Add(execution.ExecutionTimeInMilliseconds); - } - else - { - List newLatencyList = new List(); - newLatencyList.Add(execution.ExecutionTimeInMilliseconds); - commandDeduper.Add(signature, newLatencyList); - } - } - - return commandDeduper; - } - } - - - } - class CommandAndCacheKey - { - private readonly string commandName; - private readonly string cacheKey; - - public CommandAndCacheKey(String commandName, String cacheKey) - { - this.commandName = commandName; - this.cacheKey = cacheKey; - } - - public override bool Equals(Object o) - { - if (this == o) return true; - if (o == null || GetType() != o.GetType()) return false; - - CommandAndCacheKey that = (CommandAndCacheKey)o; - - if (!commandName.Equals(that.commandName)) return false; - return cacheKey.Equals(that.cacheKey); - - } - - - public override int GetHashCode() - { - int result = commandName.GetHashCode(); - result = 31 * result + cacheKey.GetHashCode(); - return result; - } - - public override string ToString() - { - return "CommandAndCacheKey{" + - "commandName='" + commandName + '\'' + - ", cacheKey='" + cacheKey + '\'' + - '}'; - } - } - - public class ExecutionSignature - { - private readonly string commandName; - private readonly ExecutionResult.EventCounts eventCounts; - private readonly string cacheKey; - private readonly int cachedCount; - private readonly IHystrixCollapserKey collapserKey; - private readonly int collapserBatchSize; - - private ExecutionSignature(IHystrixCommandKey commandKey, ExecutionResult.EventCounts eventCounts, String cacheKey, int cachedCount, IHystrixCollapserKey collapserKey, int collapserBatchSize) - { - this.commandName = commandKey.Name; - this.eventCounts = eventCounts; - this.cacheKey = cacheKey; - this.cachedCount = cachedCount; - this.collapserKey = collapserKey; - this.collapserBatchSize = collapserBatchSize; - } - - public static ExecutionSignature From(IHystrixInvokableInfo execution) - { - return new ExecutionSignature(execution.CommandKey, execution.EventCounts, null, 0, execution.OriginatingCollapserKey, execution.NumberCollapsed); - } - - public static ExecutionSignature From(IHystrixInvokableInfo execution, string cacheKey, int cachedCount) - { - return new ExecutionSignature(execution.CommandKey, execution.EventCounts, cacheKey, cachedCount, execution.OriginatingCollapserKey, execution.NumberCollapsed); - } - - - public override bool Equals(Object o) - { - if (this == o) return true; - if (o == null || GetType() != o.GetType()) return false; - - ExecutionSignature that = (ExecutionSignature)o; - - if (!commandName.Equals(that.commandName)) return false; - if (!eventCounts.Equals(that.eventCounts)) return false; - return !(cacheKey != null ? !cacheKey.Equals(that.cacheKey) : that.cacheKey != null); - - } - - public override int GetHashCode() - { - int result = commandName.GetHashCode(); - result = 31 * result + eventCounts.GetHashCode(); - result = 31 * result + (cacheKey != null ? cacheKey.GetHashCode() : 0); - return result; - } - - public string CommandName - { - get { return commandName; } - } - - public ExecutionResult.EventCounts Eventcounts - { - get { return eventCounts; } - } - - public int CachedCount - { - get { return cachedCount; } - } - - - public IHystrixCollapserKey CollapserKey - { - get { return collapserKey; } - } - - public int CollapserBatchSize - { - get { return collapserBatchSize; } - } - } -} - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/CancellationTokenExtensions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/CancellationTokenExtensions.cs index 9fdc6f9..e872800 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/CancellationTokenExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/CancellationTokenExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,6 +24,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents { return new CancellationTokenAwaiter(cancellationToken); } + public class CancellationTokenAwaiter : INotifyCompletion { private readonly CancellationToken _cancellationToken; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixConfigStreamController.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixConfigStreamController.cs index fd39ed3..410038f 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixConfigStreamController.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixConfigStreamController.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,14 +24,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers [Route("hystrix/config.stream")] public class HystrixConfigStreamController : HystrixStreamBaseController { - public HystrixConfigStreamController(HystrixConfigurationStream stream) : - this(stream.Observe()) + public HystrixConfigStreamController(HystrixConfigurationStream stream) + : this(stream.Observe()) { - } private HystrixConfigStreamController(IObservable observable) - : base(observable.Map( (hystrixConfiguration) => { + : base(observable.Map((hystrixConfiguration) => + { return SerialHystrixConfiguration.ToJsonString(hystrixConfiguration); })) { @@ -43,7 +42,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers { HandleRequest(); await Request.HttpContext.RequestAborted; - sampleSubscription.Dispose(); + SampleSubscription.Dispose(); } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixMetricsStreamController.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixMetricsStreamController.cs index fd2b67e..159bfb9 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixMetricsStreamController.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixMetricsStreamController.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,29 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using Microsoft.AspNetCore.Mvc; using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; -using System.Threading.Tasks; +using Steeltoe.CircuitBreaker.Hystrix.Serial; +using System; using System.Reactive.Linq; using System.Reactive.Observable.Aliases; -using Steeltoe.CircuitBreaker.Hystrix.Serial; +using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers { [Route("hystrix/hystrix.stream")] public class HystrixMetricsStreamController : HystrixStreamBaseController { - - - public HystrixMetricsStreamController(HystrixDashboardStream stream) : - this(stream.Observe()) + public HystrixMetricsStreamController(HystrixDashboardStream stream) + : this(stream.Observe()) { - } private HystrixMetricsStreamController(IObservable observable) - : base(observable.Map((data) => { + : base(observable.Map((data) => + { return SerialHystrixDashboardData.ToMultipleJsonStrings(data).ToObservable(); }).SelectMany(n => n)) { @@ -46,7 +43,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers { HandleRequest(); await Request.HttpContext.RequestAborted; - sampleSubscription.Dispose(); + SampleSubscription.Dispose(); } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixRequestEventStreamController.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixRequestEventStreamController.cs index bbbd369..c27e5b5 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixRequestEventStreamController.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixRequestEventStreamController.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,14 +24,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers [Route("hystrix/request.stream")] public class HystrixRequestEventStreamController : HystrixStreamBaseController { - public HystrixRequestEventStreamController(HystrixRequestEventsStream stream) : - this(stream.Observe()) + public HystrixRequestEventStreamController(HystrixRequestEventsStream stream) + : this(stream.Observe()) { - } private HystrixRequestEventStreamController(IObservable observable) - : base(observable.Map( (requestEvents) => { + : base(observable.Map((requestEvents) => + { return SerialHystrixRequestEvents.ToJsonString(requestEvents); })) { @@ -43,7 +42,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers { HandleRequest(); await Request.HttpContext.RequestAborted; - sampleSubscription.Dispose(); + SampleSubscription.Dispose(); } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixStreamBaseController.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixStreamBaseController.cs index 83bfd7b..56b915b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixStreamBaseController.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixStreamBaseController.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,23 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; -using System.Reactive.Linq; +using Microsoft.AspNetCore.Mvc; +using System; using System.Reactive.Concurrency; +using System.Reactive.Linq; namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers { public class HystrixStreamBaseController : Controller { - internal IObservable sampleStream; + private IObservable sampleStream; - internal IDisposable sampleSubscription = null; + private IDisposable sampleSubscription = null; + + protected internal IObservable SampleStream { get => sampleStream; set => sampleStream = value; } + + protected internal IDisposable SampleSubscription { get => sampleSubscription; set => sampleSubscription = value; } public HystrixStreamBaseController(IObservable observable) { - this.sampleStream = observable; + this.SampleStream = observable; } protected void HandleRequest() @@ -40,7 +43,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers Response.Headers.Add("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate"); Response.Headers.Add("Pragma", "no-cache"); - sampleSubscription = sampleStream + SampleSubscription = SampleStream .ObserveOn(NewThreadScheduler.Default) .Subscribe( async (sampleDataAsString) => @@ -54,28 +57,28 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers } catch (Exception) { - if (sampleSubscription != null) + if (SampleSubscription != null) { - sampleSubscription.Dispose(); - sampleSubscription = null; + SampleSubscription.Dispose(); + SampleSubscription = null; } } } }, (error) => { - if (sampleSubscription != null) + if (SampleSubscription != null) { - sampleSubscription.Dispose(); - sampleSubscription = null; + SampleSubscription.Dispose(); + SampleSubscription = null; } }, () => { - if (sampleSubscription != null) + if (SampleSubscription != null) { - sampleSubscription.Dispose(); - sampleSubscription = null; + SampleSubscription.Dispose(); + SampleSubscription = null; } }); Response.Body.FlushAsync(); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixUtilizationStreamController.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixUtilizationStreamController.cs index 7db3f3f..01c7d20 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixUtilizationStreamController.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Controllers/HystrixUtilizationStreamController.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,14 +24,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers [Route("hystrix/utilization.stream")] public class HystrixUtilizationStreamController : HystrixStreamBaseController { - public HystrixUtilizationStreamController(HystrixUtilizationStream stream) : - this(stream.Observe()) + public HystrixUtilizationStreamController(HystrixUtilizationStream stream) + : this(stream.Observe()) { - } private HystrixUtilizationStreamController(IObservable observable) - : base(observable.Map( (utilization) => { + : base(observable.Map((utilization) => + { return SerialHystrixUtilization.ToJsonString(utilization); })) { @@ -43,7 +42,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers { HandleRequest(); await Request.HttpContext.RequestAborted; - sampleSubscription.Dispose(); + SampleSubscription.Dispose(); } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixApplicationBuilderExtensions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixApplicationBuilderExtensions.cs index 9df8abb..4cb3ae0 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixApplicationBuilderExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixApplicationBuilderExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; namespace Steeltoe.CircuitBreaker.Hystrix { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixServiceCollectionExtensions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixServiceCollectionExtensions.cs index ee0967a..732c68e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixServiceCollectionExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/HystrixServiceCollectionExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,19 +21,16 @@ using Steeltoe.CircuitBreaker.Hystrix.Metric.Sample; using System; namespace Steeltoe.CircuitBreaker.Hystrix - { public static class HystrixServiceCollectionExtensions { public static void AddHystrixMetricsStream(this IServiceCollection services, IConfiguration config) { - if (services == null) { throw new ArgumentNullException(nameof(services)); } - services.AddSingleton(HystrixDashboardStream.GetInstance()); } @@ -80,6 +76,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix services.AddHystrixRequestEventStream(config); services.AddHystrixUtilizationStream(config); } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Properties/AssemblyInfo.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Properties/AssemblyInfo.cs index dab2a7b..8168aff 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Properties/AssemblyInfo.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Properties/AssemblyInfo.cs @@ -1,4 +1,18 @@ -using System.Reflection; +// Copyright 2017 the original author or authors. +// +// 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. + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.csproj b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.csproj index 538866a..a8e227b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.csproj +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.csproj @@ -20,22 +20,28 @@ - + - + + + All + + + + SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591 + + + + stylecop.json + Always + - - - \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/HystrixContainerBuilderExtensions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/HystrixContainerBuilderExtensions.cs index 3a3b9d9..bac3d0e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/HystrixContainerBuilderExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/HystrixContainerBuilderExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,7 +27,6 @@ using Steeltoe.Common.Options.Autofac; using System; namespace Steeltoe.CircuitBreaker.Hystrix - { public static class HystrixContainerBuilderExtensions { @@ -58,7 +56,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix container.RegisterOption(config.GetSection(HYSTRIX_STREAM_PREFIX)); container.RegisterType().SingleInstance(); - } public static void RegisterHystrixRequestEventStream(this ContainerBuilder container, IConfiguration config) @@ -67,6 +64,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { throw new ArgumentNullException(nameof(container)); } + container.RegisterInstance(HystrixRequestEventsStream.GetInstance()).SingleInstance(); } @@ -76,6 +74,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { throw new ArgumentNullException(nameof(container)); } + container.RegisterInstance(HystrixUtilizationStream.GetInstance()).SingleInstance(); } @@ -85,6 +84,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { throw new ArgumentNullException(nameof(container)); } + container.RegisterInstance(HystrixConfigurationStream.GetInstance()).SingleInstance(); } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Properties/AssemblyInfo.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Properties/AssemblyInfo.cs index 31d7d5a..b52938d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Properties/AssemblyInfo.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Properties/AssemblyInfo.cs @@ -1,4 +1,18 @@ -using System.Reflection; +// Copyright 2017 the original author or authors. +// +// 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. + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/RabbitMetricsStreamPublisher.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/RabbitMetricsStreamPublisher.cs index 4bd7fef..8209871 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/RabbitMetricsStreamPublisher.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/RabbitMetricsStreamPublisher.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,35 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using RabbitMQ.Client; -using System.Reactive.Observable.Aliases; -using System.Reactive.Linq; -using System.Reactive.Concurrency; -using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; -using System.Text; -using System.Collections.Generic; using Microsoft.Extensions.Logging; -using System.Net.Security; -using Steeltoe.Common.Discovery; -using Steeltoe.CloudFoundry.Connector.Hystrix; using Microsoft.Extensions.Options; +using RabbitMQ.Client; +using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; +using Steeltoe.CloudFoundry.Connector.Hystrix; +using Steeltoe.Common.Discovery; +using System; +using System.Collections.Generic; +using System.Net.Security; +using System.Text; namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream { - public class RabbitMetricsStreamPublisher : HystrixMetricsStreamPublisher { - internal ConnectionFactory factory; - internal IConnection connection; - internal IModel channel; + private ConnectionFactory factory; + private IConnection connection; + private IModel channel; + + protected internal ConnectionFactory Factory { get => factory; set => factory = value; } + + protected internal IConnection Connection { get => connection; set => connection = value; } + + protected internal IModel Channel { get => channel; set => channel = value; } public RabbitMetricsStreamPublisher(IOptions options, HystrixDashboardStream stream, HystrixConnectionFactory factory, ILogger logger = null, IDiscoveryClient discoveryClient = null) : base(options, stream, logger, discoveryClient) { - - this.factory = factory.ConnectionFactory as ConnectionFactory; - SslOption sslOption = this.factory.Ssl; + this.Factory = factory.ConnectionFactory as ConnectionFactory; + SslOption sslOption = this.Factory.Ssl; if (sslOption != null && sslOption.Enabled && !this.options.Validate_Certificates) { logger?.LogInformation("Hystrix Metrics disabling certificate validation"); @@ -54,18 +54,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream protected override bool EnsureConnection() { - if (connection != null) + if (Connection != null) { return true; } try { - connection = this.factory.CreateConnection(); - channel = connection.CreateModel(); + Connection = this.Factory.CreateConnection(); + Channel = Connection.CreateModel(); logger?.LogInformation("Hystrix Metrics connected!"); return true; - } catch (Exception e) { @@ -76,7 +75,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream protected override void OnNext(List jsonList) { - if (channel != null) + if (Channel != null) { foreach (var sampleDataAsString in jsonList) { @@ -85,9 +84,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream logger?.LogDebug("Hystrix Metrics: {0}", sampleDataAsString.ToString()); var body = Encoding.UTF8.GetBytes(sampleDataAsString); - var props = channel.CreateBasicProperties(); + var props = Channel.CreateBasicProperties(); props.ContentType = "application/json"; - channel.BasicPublish(SPRING_CLOUD_HYSTRIX_STREAM_EXCHANGE, "", props, body); + Channel.BasicPublish(SPRING_CLOUD_HYSTRIX_STREAM_EXCHANGE, string.Empty, props, body); } } } @@ -95,17 +94,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream protected override void Dispose() { - if (channel != null) + if (Channel != null) { - channel.Dispose(); - channel = null; + Channel.Dispose(); + Channel = null; } - if (connection != null) + + if (Connection != null) { - connection.Dispose(); - connection = null; + Connection.Dispose(); + Connection = null; } - } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.csproj b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.csproj index bb67950..9a3f183 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.csproj +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.csproj @@ -20,19 +20,29 @@ - + - + - + - + + All + + + + SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591 + + + + stylecop.json + Always + - \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixApplicationBuilderExtensions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixApplicationBuilderExtensions.cs index 67bf5b5..9af5a70 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixApplicationBuilderExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixApplicationBuilderExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; using Steeltoe.CircuitBreaker.Hystrix.MetricsStream; using System; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixServiceCollectionExtensions.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixServiceCollectionExtensions.cs index ea0a385..d6fa68e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixServiceCollectionExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/HystrixServiceCollectionExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,7 +23,6 @@ using Steeltoe.CloudFoundry.Connector.Hystrix; using System; namespace Steeltoe.CircuitBreaker.Hystrix - { public static class HystrixServiceCollectionExtensions { @@ -72,6 +70,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix services.AddSingleton(HystrixConfigurationStream.GetInstance()); } + public static void AddHystrixMonitoringStreams(this IServiceCollection services, IConfiguration config) { if (services == null) @@ -84,6 +83,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix services.AddHystrixRequestEventStream(config); services.AddHystrixUtilizationStream(config); } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Properties/AssemblyInfo.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Properties/AssemblyInfo.cs index ba61280..338a772 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Properties/AssemblyInfo.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Properties/AssemblyInfo.cs @@ -1,4 +1,18 @@ -using System.Reflection; +// Copyright 2017 the original author or authors. +// +// 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. + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/RabbitMetricsStreamPublisher.cs b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/RabbitMetricsStreamPublisher.cs index 4bd7fef..8209871 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/RabbitMetricsStreamPublisher.cs +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/RabbitMetricsStreamPublisher.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,35 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using RabbitMQ.Client; -using System.Reactive.Observable.Aliases; -using System.Reactive.Linq; -using System.Reactive.Concurrency; -using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; -using System.Text; -using System.Collections.Generic; using Microsoft.Extensions.Logging; -using System.Net.Security; -using Steeltoe.Common.Discovery; -using Steeltoe.CloudFoundry.Connector.Hystrix; using Microsoft.Extensions.Options; +using RabbitMQ.Client; +using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; +using Steeltoe.CloudFoundry.Connector.Hystrix; +using Steeltoe.Common.Discovery; +using System; +using System.Collections.Generic; +using System.Net.Security; +using System.Text; namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream { - public class RabbitMetricsStreamPublisher : HystrixMetricsStreamPublisher { - internal ConnectionFactory factory; - internal IConnection connection; - internal IModel channel; + private ConnectionFactory factory; + private IConnection connection; + private IModel channel; + + protected internal ConnectionFactory Factory { get => factory; set => factory = value; } + + protected internal IConnection Connection { get => connection; set => connection = value; } + + protected internal IModel Channel { get => channel; set => channel = value; } public RabbitMetricsStreamPublisher(IOptions options, HystrixDashboardStream stream, HystrixConnectionFactory factory, ILogger logger = null, IDiscoveryClient discoveryClient = null) : base(options, stream, logger, discoveryClient) { - - this.factory = factory.ConnectionFactory as ConnectionFactory; - SslOption sslOption = this.factory.Ssl; + this.Factory = factory.ConnectionFactory as ConnectionFactory; + SslOption sslOption = this.Factory.Ssl; if (sslOption != null && sslOption.Enabled && !this.options.Validate_Certificates) { logger?.LogInformation("Hystrix Metrics disabling certificate validation"); @@ -54,18 +54,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream protected override bool EnsureConnection() { - if (connection != null) + if (Connection != null) { return true; } try { - connection = this.factory.CreateConnection(); - channel = connection.CreateModel(); + Connection = this.Factory.CreateConnection(); + Channel = Connection.CreateModel(); logger?.LogInformation("Hystrix Metrics connected!"); return true; - } catch (Exception e) { @@ -76,7 +75,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream protected override void OnNext(List jsonList) { - if (channel != null) + if (Channel != null) { foreach (var sampleDataAsString in jsonList) { @@ -85,9 +84,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream logger?.LogDebug("Hystrix Metrics: {0}", sampleDataAsString.ToString()); var body = Encoding.UTF8.GetBytes(sampleDataAsString); - var props = channel.CreateBasicProperties(); + var props = Channel.CreateBasicProperties(); props.ContentType = "application/json"; - channel.BasicPublish(SPRING_CLOUD_HYSTRIX_STREAM_EXCHANGE, "", props, body); + Channel.BasicPublish(SPRING_CLOUD_HYSTRIX_STREAM_EXCHANGE, string.Empty, props, body); } } } @@ -95,17 +94,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream protected override void Dispose() { - if (channel != null) + if (Channel != null) { - channel.Dispose(); - channel = null; + Channel.Dispose(); + Channel = null; } - if (connection != null) + + if (Connection != null) { - connection.Dispose(); - connection = null; + Connection.Dispose(); + Connection = null; } - } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.csproj b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.csproj index a8f2b79..d387dfd 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.csproj +++ b/src/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.csproj @@ -20,11 +20,11 @@ - + - + @@ -32,7 +32,17 @@ - + + All + + + + SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591 + + + + stylecop.json + Always + - \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixContainerBuilderExtensions.cs b/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixContainerBuilderExtensions.cs index 4c6ec60..5ea6841 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixContainerBuilderExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixContainerBuilderExtensions.cs @@ -1,4 +1,18 @@ -using Autofac; +// Copyright 2017 the original author or authors. +// +// 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. + +using Autofac; using Microsoft.Extensions.Configuration; using Steeltoe.CircuitBreaker.Hystrix.Strategy; using System; @@ -8,7 +22,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix public static class HystrixContainerBuilderExtensions { public static void RegisterHystrixCommand(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (container == null) { @@ -38,7 +53,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void RegisterHystrixCommand(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (container == null) { @@ -68,9 +84,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix GroupKey = groupKey }; container.RegisterType().As().WithParameter(new TypedParameter(typeof(IHystrixCommandOptions), opts)).InstancePerDependency(); - } - public static void RegisterHystrixCommand(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IConfiguration config) where TService : class + + public static void RegisterHystrixCommand(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IConfiguration config) + where TService : class { if (container == null) { @@ -99,7 +116,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix container.RegisterType().WithParameter(new TypedParameter(typeof(IHystrixCommandOptions), opts)).InstancePerDependency(); } - public static void RegisterHystrixCommand(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, IConfiguration config) where TService : class + public static void RegisterHystrixCommand(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, IConfiguration config) + where TService : class { if (container == null) { @@ -131,7 +149,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix container.RegisterType().WithParameter(new TypedParameter(typeof(IHystrixCommandOptions), opts)).InstancePerDependency(); } - public static void RegisterHystrixCommand(this ContainerBuilder container, string groupKey, IConfiguration config) where TService : class + public static void RegisterHystrixCommand(this ContainerBuilder container, string groupKey, IConfiguration config) + where TService : class { if (container == null) { @@ -151,9 +170,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix RegisterHystrixCommand(container, HystrixCommandGroupKeyDefault.AsKey(groupKey), config); } - public static void RegisterHystrixCommand(this ContainerBuilder container, string groupKey, string commandKey, IConfiguration config) where TService : class + public static void RegisterHystrixCommand(this ContainerBuilder container, string groupKey, string commandKey, IConfiguration config) + where TService : class { - if (container == null) { throw new ArgumentNullException(nameof(container)); @@ -178,7 +197,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void RegisterHystrixCommand(this ContainerBuilder container, string groupKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (container == null) { @@ -199,9 +219,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void RegisterHystrixCommand(this ContainerBuilder container, string groupKey, string commandKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { - if (container == null) { throw new ArgumentNullException(nameof(container)); @@ -226,7 +246,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void RegisterHystrixCollapser(this ContainerBuilder container, IHystrixCollapserKey collapserKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (container == null) { @@ -249,11 +270,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix HystrixCollapserOptions opts = new HystrixCollapserOptions(collapserKey, null, dynOpts); container.RegisterType().As().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency(); - } public static void RegisterHystrixCollapser(this ContainerBuilder container, IHystrixCollapserKey collapserKey, RequestCollapserScope scope, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (container == null) { @@ -265,7 +286,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentNullException(nameof(collapserKey)); } - if (config == null) { throw new ArgumentNullException(nameof(config)); @@ -276,9 +296,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix HystrixCollapserOptions opts = new HystrixCollapserOptions(collapserKey, scope, null, dynOpts); container.RegisterType().As().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency(); - } - public static void RegisterHystrixCollapser(this ContainerBuilder container, IHystrixCollapserKey collapserKey, IConfiguration config) where TService : class + + public static void RegisterHystrixCollapser(this ContainerBuilder container, IHystrixCollapserKey collapserKey, IConfiguration config) + where TService : class { if (container == null) { @@ -302,7 +323,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix container.RegisterType().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency(); } - public static void RegisterHystrixCollapser(this ContainerBuilder container, IHystrixCollapserKey collapserKey, RequestCollapserScope scope, IConfiguration config) where TService : class + public static void RegisterHystrixCollapser(this ContainerBuilder container, IHystrixCollapserKey collapserKey, RequestCollapserScope scope, IConfiguration config) + where TService : class { if (container == null) { @@ -324,10 +346,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix HystrixCollapserOptions opts = new HystrixCollapserOptions(collapserKey, scope, null, dynOpts); container.RegisterType().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency(); - } - public static void RegisterHystrixCollapser(this ContainerBuilder container, string collapserKey, IConfiguration config) where TService : class + public static void RegisterHystrixCollapser(this ContainerBuilder container, string collapserKey, IConfiguration config) + where TService : class { if (container == null) { @@ -347,9 +369,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix RegisterHystrixCollapser(container, HystrixCollapserKeyDefault.AsKey(collapserKey), config); } - public static void RegisterHystrixCollapser(this ContainerBuilder container, string collapserKey, RequestCollapserScope scope, IConfiguration config) where TService : class + public static void RegisterHystrixCollapser(this ContainerBuilder container, string collapserKey, RequestCollapserScope scope, IConfiguration config) + where TService : class { - if (container == null) { throw new ArgumentNullException(nameof(container)); @@ -360,7 +382,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentNullException(nameof(collapserKey)); } - if (config == null) { throw new ArgumentNullException(nameof(config)); @@ -370,7 +391,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void RegisterHystrixCollapser(this ContainerBuilder container, string collapserKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (container == null) { @@ -391,9 +413,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void RegisterHystrixCollapser(this ContainerBuilder container, string collapserKey, RequestCollapserScope scope, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { - if (container == null) { throw new ArgumentNullException(nameof(container)); @@ -404,7 +426,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentNullException(nameof(collapserKey)); } - if (config == null) { throw new ArgumentNullException(nameof(config)); @@ -412,6 +433,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix RegisterHystrixCollapser(container, HystrixCollapserKeyDefault.AsKey(collapserKey), scope, config); } - } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixRequestContextModule.cs b/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixRequestContextModule.cs index 356307d..6cf2c83 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixRequestContextModule.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixAutofac/HystrixRequestContextModule.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,7 +22,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix { public void Dispose() { - } public void Init(HttpApplication context) @@ -60,8 +58,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix items["_hystrix_context_"] = HystrixRequestContext.InitializeContext(); } } - } - } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixAutofac/Properties/AssemblyInfo.cs b/src/Steeltoe.CircuitBreaker.HystrixAutofac/Properties/AssemblyInfo.cs index efeff7e..16ab98c 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixAutofac/Properties/AssemblyInfo.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixAutofac/Properties/AssemblyInfo.cs @@ -1,4 +1,18 @@ -using System.Reflection; +// Copyright 2017 the original author or authors. +// +// 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. + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/Steeltoe.CircuitBreaker.HystrixAutofac/Steeltoe.CircuitBreaker.HystrixAutofac.csproj b/src/Steeltoe.CircuitBreaker.HystrixAutofac/Steeltoe.CircuitBreaker.HystrixAutofac.csproj index e9b48db..e8e6bf4 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixAutofac/Steeltoe.CircuitBreaker.HystrixAutofac.csproj +++ b/src/Steeltoe.CircuitBreaker.HystrixAutofac/Steeltoe.CircuitBreaker.HystrixAutofac.csproj @@ -20,15 +20,27 @@ - + - + + + All + + + + SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591 + + + + stylecop.json + Always + diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/AbstractCommand.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/AbstractCommand.cs similarity index 71% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/AbstractCommand.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/AbstractCommand.cs index 1a77df5..83685df 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/AbstractCommand.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/AbstractCommand.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using Microsoft.Extensions.Logging; using Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker; using Steeltoe.CircuitBreaker.Hystrix.Exceptions; using Steeltoe.CircuitBreaker.Hystrix.Strategy; @@ -20,21 +20,19 @@ using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; using Steeltoe.CircuitBreaker.Hystrix.Strategy.EventNotifier; using Steeltoe.CircuitBreaker.Hystrix.Strategy.ExecutionHook; using Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics; +using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options; using Steeltoe.CircuitBreaker.Hystrix.ThreadPool; using Steeltoe.CircuitBreaker.Hystrix.Util; - using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Security; using System.Threading; using System.Threading.Tasks; -using System.Collections.Concurrent; -using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options; -using Microsoft.Extensions.Logging; namespace Steeltoe.CircuitBreaker.Hystrix { - public abstract class AbstractCommand : IHystrixInvokableInfo, IHystrixInvokable + public abstract class AbstractCommand : IHystrixInvokableInfo, IHystrixInvokable { #region NestedTypes protected enum TimedOutStatus @@ -63,17 +61,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix protected class AtomicCommandState : AtomicInteger { - public AtomicCommandState(CommandState state) : - base((int)state) + public AtomicCommandState(CommandState state) + : base((int)state) { - } + public new CommandState Value { get { return (CommandState)_value; } + set { _value = (int)value; @@ -82,23 +81,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix public bool CompareAndSet(CommandState expected, CommandState update) { - return base.CompareAndSet((int)expected, (int)update); + return CompareAndSet((int)expected, (int)update); } } protected class AtomicThreadState : AtomicInteger { - public AtomicThreadState(ThreadState state) : - base((int)state) + public AtomicThreadState(ThreadState state) + : base((int)state) { - } + public new ThreadState Value { get { return (ThreadState)_value; } + set { _value = (int)value; @@ -107,23 +107,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix public bool CompareAndSet(ThreadState expected, ThreadState update) { - return base.CompareAndSet((int)expected, (int)update); + return CompareAndSet((int)expected, (int)update); } } protected class AtomicTimedOutStatus : AtomicInteger { - public AtomicTimedOutStatus(TimedOutStatus state) : - base((int)state) + public AtomicTimedOutStatus(TimedOutStatus state) + : base((int)state) { - } + public new TimedOutStatus Value { get { return (TimedOutStatus)_value; } + set { _value = (int)value; @@ -132,7 +133,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix public bool CompareAndSet(TimedOutStatus expected, TimedOutStatus update) { - return base.CompareAndSet((int)expected, (int)update); + return CompareAndSet((int)expected, (int)update); } } @@ -162,9 +163,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { - return canceled.HasValue ? canceled.Value : false; + return canceled ?? false; } } + public bool IsCompleted { get @@ -172,26 +174,33 @@ namespace Steeltoe.CircuitBreaker.Hystrix return IsFaulted || IsCanceled || resultSet == true; } } - public bool IsFaulted { + + public bool IsFaulted + { get { return exception != null; } } - public Exception Exception { + + public Exception Exception + { get { return exception; } } - public Task Task { + + public Task Task + { get { return source.Task; } } - - public TResult Result { + + public TResult Result + { get { return result; @@ -210,9 +219,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix { if (!IsCompleted) { - canceled = true; + canceled = true; } - } internal void TrySetResult(TResult result) @@ -222,7 +230,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix resultSet = true; this.result = result; } - } internal void Commit() @@ -231,87 +238,139 @@ namespace Steeltoe.CircuitBreaker.Hystrix { throw new InvalidOperationException("HystrixCompletionSource not completed!"); } + if (IsCanceled) { source.SetCanceled(); - } else if (IsFaulted) + } + else if (IsFaulted) { source.SetException(this.exception); - } else + } + else { source.SetResult(this.result); } } - } #endregion NestedTypes #region Fields - internal protected long commandStartTimestamp = -1L; - internal protected long threadStartTimestamp = -1L; - internal protected volatile bool isResponseFromCache = false; + protected internal readonly HystrixRequestLog _currentRequestLog; + protected internal readonly HystrixRequestCache _requestCache; + protected internal readonly HystrixCommandExecutionHook _executionHook; + protected internal readonly HystrixCommandMetrics _metrics; + protected internal readonly HystrixEventNotifier _eventNotifier; + protected internal readonly IHystrixCircuitBreaker _circuitBreaker; + protected internal readonly IHystrixThreadPool _threadPool; + protected internal readonly SemaphoreSlim _fallbackSemaphoreOverride; + protected internal readonly SemaphoreSlim _executionSemaphoreOverride; + protected internal readonly HystrixConcurrencyStrategy _concurrencyStrategy; + protected internal long _commandStartTimestamp = -1L; + protected internal long _threadStartTimestamp = -1L; + protected internal volatile bool _isResponseFromCache = false; + protected internal Task _execThreadTask = null; + protected internal CancellationTokenSource _timeoutTcs; + protected internal CancellationToken _token; + protected internal CancellationToken _usersToken; + protected internal volatile ExecutionResult _executionResult = ExecutionResult.EMPTY; // state on shared execution + protected internal volatile ExecutionResult _executionResultAtTimeOfCancellation; + + protected static readonly ConcurrentDictionary _executionSemaphorePerCircuit = new ConcurrentDictionary(); + protected static readonly ConcurrentDictionary _fallbackSemaphorePerCircuit = new ConcurrentDictionary(); + protected readonly AtomicCommandState commandState = new AtomicCommandState(CommandState.NOT_STARTED); protected readonly AtomicThreadState threadState = new AtomicThreadState(ThreadState.NOT_USING_THREAD); protected readonly AtomicTimedOutStatus isCommandTimedOut = new AtomicTimedOutStatus(TimedOutStatus.NOT_EXECUTED); - internal protected readonly HystrixRequestLog currentRequestLog; - internal protected readonly HystrixRequestCache requestCache; - internal protected readonly HystrixCommandExecutionHook executionHook; - internal protected CancellationTokenSource timeoutTcs; - internal protected CancellationToken token; - internal protected CancellationToken usersToken; - internal protected volatile ExecutionResult executionResult = ExecutionResult.EMPTY; //state on shared execution - internal protected readonly HystrixCommandMetrics metrics; - internal protected readonly HystrixEventNotifier eventNotifier; - internal protected readonly IHystrixCircuitBreaker circuitBreaker; - internal protected readonly IHystrixThreadPool threadPool; - internal protected volatile ExecutionResult executionResultAtTimeOfCancellation; - protected static readonly ConcurrentDictionary executionSemaphorePerCircuit = new ConcurrentDictionary(); - protected static readonly ConcurrentDictionary fallbackSemaphorePerCircuit = new ConcurrentDictionary(); - internal protected readonly SemaphoreSlim fallbackSemaphoreOverride; - internal protected readonly SemaphoreSlim executionSemaphoreOverride; - internal protected readonly HystrixConcurrencyStrategy concurrencyStrategy; - internal protected Task execThreadTask = null; + protected readonly IHystrixCommandGroupKey commandGroup; + protected HystrixCompletionSource tcs; private ILogger logger; #endregion Fields #region Constructors - protected AbstractCommand(IHystrixCommandGroupKey group, IHystrixCommandKey key, IHystrixThreadPoolKey threadPoolKey, IHystrixCircuitBreaker circuitBreaker, IHystrixThreadPool threadPool, - IHystrixCommandOptions commandOptionsDefaults, IHystrixThreadPoolOptions threadPoolOptionsDefaults, - HystrixCommandMetrics metrics, SemaphoreSlim fallbackSemaphore, SemaphoreSlim executionSemaphore, HystrixOptionsStrategy optionsStrategy, HystrixCommandExecutionHook executionHook, ILogger logger = null) + protected AbstractCommand( + IHystrixCommandGroupKey group, + IHystrixCommandKey key, + IHystrixThreadPoolKey threadPoolKey, + IHystrixCircuitBreaker circuitBreaker, + IHystrixThreadPool threadPool, + IHystrixCommandOptions commandOptionsDefaults, + IHystrixThreadPoolOptions threadPoolOptionsDefaults, + HystrixCommandMetrics metrics, + SemaphoreSlim fallbackSemaphore, + SemaphoreSlim executionSemaphore, + HystrixOptionsStrategy optionsStrategy, + HystrixCommandExecutionHook executionHook, + ILogger logger = null) { - this.logger = logger; this.commandGroup = InitGroupKey(group); this.commandKey = InitCommandKey(key, GetType()); this.options = InitCommandOptions(this.commandKey, optionsStrategy, commandOptionsDefaults); this.threadPoolKey = InitThreadPoolKey(threadPoolKey, this.commandGroup, this.options.ExecutionIsolationThreadPoolKeyOverride); - this.metrics = InitMetrics(metrics, this.commandGroup, this.threadPoolKey, this.commandKey, this.options); - this.circuitBreaker = InitCircuitBreaker(this.options.CircuitBreakerEnabled, circuitBreaker, this.commandGroup, this.commandKey, this.options, this.metrics); + this._metrics = InitMetrics(metrics, this.commandGroup, this.threadPoolKey, this.commandKey, this.options); + this._circuitBreaker = InitCircuitBreaker(this.options.CircuitBreakerEnabled, circuitBreaker, this.commandGroup, this.commandKey, this.options, this._metrics); - this.threadPool = InitThreadPool(threadPool, this.threadPoolKey, threadPoolOptionsDefaults); - - //Strategies from plugins - this.eventNotifier = HystrixPlugins.EventNotifier; - this.concurrencyStrategy = HystrixPlugins.ConcurrencyStrategy; - HystrixMetricsPublisherFactory.CreateOrRetrievePublisherForCommand(this.commandKey, this.commandGroup, this.metrics, this.circuitBreaker, this.options); + this._threadPool = InitThreadPool(threadPool, this.threadPoolKey, threadPoolOptionsDefaults); - this.executionHook = InitExecutionHook(executionHook); + // Strategies from plugins + this._eventNotifier = HystrixPlugins.EventNotifier; + this._concurrencyStrategy = HystrixPlugins.ConcurrencyStrategy; + HystrixMetricsPublisherFactory.CreateOrRetrievePublisherForCommand(this.commandKey, this.commandGroup, this._metrics, this._circuitBreaker, this.options); + + this._executionHook = InitExecutionHook(executionHook); + + this._requestCache = HystrixRequestCache.GetInstance(this.commandKey); + this._currentRequestLog = InitRequestLog(this.options.RequestLogEnabled); - this.requestCache = HystrixRequestCache.GetInstance(this.commandKey); - this.currentRequestLog = InitRequestLog(this.options.RequestLogEnabled); - /* fallback semaphore override if applicable */ - this.fallbackSemaphoreOverride = fallbackSemaphore; + this._fallbackSemaphoreOverride = fallbackSemaphore; /* execution semaphore override if applicable */ - this.executionSemaphoreOverride = executionSemaphore; - + this._executionSemaphoreOverride = executionSemaphore; } #endregion Constructors + internal void MarkAsCollapsedCommand(IHystrixCollapserKey collapserKey, int sizeOfBatch) + { + MarkCollapsedCommand(collapserKey, sizeOfBatch); + } + + protected internal SemaphoreSlim GetExecutionSemaphore() + { + if (options.ExecutionIsolationStrategy == ExecutionIsolationStrategy.SEMAPHORE) + { + if (_executionSemaphoreOverride == null) + { + return _executionSemaphorePerCircuit.GetOrAddEx(commandKey.Name, (k) => new SemaphoreSlim(options.ExecutionIsolationSemaphoreMaxConcurrentRequests)); + } + else + { + return _executionSemaphoreOverride; + } + } + else + { + // return NoOp implementation since we're not using SEMAPHORE isolation + return null; + } + } + + protected internal SemaphoreSlim GetFallbackSemaphore() + { + if (_fallbackSemaphoreOverride == null) + { + return _fallbackSemaphorePerCircuit.GetOrAddEx(commandKey.Name, (k) => new SemaphoreSlim(options.FallbackIsolationSemaphoreMaxConcurrentRequests)); + } + else + { + return _fallbackSemaphoreOverride; + } + } + #region Init protected static IHystrixCommandGroupKey InitGroupKey(IHystrixCommandGroupKey fromConstructor) { @@ -327,7 +386,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix protected static IHystrixCommandKey InitCommandKey(IHystrixCommandKey fromConstructor, Type clazz) { - if (fromConstructor == null || fromConstructor.Name.Trim().Equals("")) + if (fromConstructor == null || fromConstructor.Name.Trim().Equals(string.Empty)) { string keyName = clazz.Name; return HystrixCommandKeyDefault.AsKey(keyName); @@ -338,7 +397,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } - protected static IHystrixCommandOptions InitCommandOptions(IHystrixCommandKey commandKey, HystrixOptionsStrategy optionsStrategy, IHystrixCommandOptions commandOptionsDefault) + protected static IHystrixCommandOptions InitCommandOptions( + IHystrixCommandKey commandKey, + HystrixOptionsStrategy optionsStrategy, + IHystrixCommandOptions commandOptionsDefault) { if (optionsStrategy == null) { @@ -351,7 +413,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } - protected static IHystrixThreadPoolKey InitThreadPoolKey(IHystrixThreadPoolKey threadPoolKey, IHystrixCommandGroupKey groupKey, string threadPoolKeyOverride) + protected static IHystrixThreadPoolKey InitThreadPoolKey( + IHystrixThreadPoolKey threadPoolKey, + IHystrixCommandGroupKey groupKey, + string threadPoolKeyOverride) { if (threadPoolKeyOverride == null) { @@ -373,9 +438,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } - protected static HystrixCommandMetrics InitMetrics(HystrixCommandMetrics fromConstructor, IHystrixCommandGroupKey groupKey, - IHystrixThreadPoolKey threadPoolKey, IHystrixCommandKey commandKey, - IHystrixCommandOptions properties) + protected static HystrixCommandMetrics InitMetrics( + HystrixCommandMetrics fromConstructor, + IHystrixCommandGroupKey groupKey, + IHystrixThreadPoolKey threadPoolKey, + IHystrixCommandKey commandKey, + IHystrixCommandOptions properties) { if (fromConstructor == null) { @@ -387,9 +455,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } - protected static IHystrixCircuitBreaker InitCircuitBreaker(bool enabled, IHystrixCircuitBreaker fromConstructor, - IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, - IHystrixCommandOptions properties, HystrixCommandMetrics metrics) + protected static IHystrixCircuitBreaker InitCircuitBreaker( + bool enabled, + IHystrixCircuitBreaker fromConstructor, + IHystrixCommandGroupKey groupKey, + IHystrixCommandKey commandKey, + IHystrixCommandOptions properties, + HystrixCommandMetrics metrics) { if (enabled) { @@ -415,10 +487,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix { return HystrixPlugins.CommandExecutionHook; } + return fromConstructor; } - protected static IHystrixThreadPool InitThreadPool(IHystrixThreadPool fromConstructor, IHystrixThreadPoolKey threadPoolKey, IHystrixThreadPoolOptions threadPoolPropertiesDefaults) + protected static IHystrixThreadPool InitThreadPool( + IHystrixThreadPool fromConstructor, + IHystrixThreadPoolKey threadPoolKey, + IHystrixThreadPoolOptions threadPoolPropertiesDefaults) { if (fromConstructor == null) { @@ -447,49 +523,56 @@ namespace Steeltoe.CircuitBreaker.Hystrix protected void Setup() { - this.timeoutTcs = CancellationTokenSource.CreateLinkedTokenSource(this.usersToken); - this.token = timeoutTcs.Token; + this._timeoutTcs = CancellationTokenSource.CreateLinkedTokenSource(this._usersToken); + this._token = _timeoutTcs.Token; this.tcs = new HystrixCompletionSource(this); /* this is a stateful object so can only be used once */ if (!commandState.CompareAndSet(CommandState.NOT_STARTED, CommandState.OBSERVABLE_CHAIN_CREATED)) { - InvalidOperationException ex = new InvalidOperationException("This instance can only be executed once. Please instantiate a new instance."); - throw new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, this.GetType(), LogMessagePrefix + " command executed multiple times - this is not permitted.", ex, null); + InvalidOperationException ex = new InvalidOperationException( + "This instance can only be executed once. Please instantiate a new instance."); + throw new HystrixRuntimeException( + FailureType.BAD_REQUEST_EXCEPTION, + this.GetType(), + LogMessagePrefix + " command executed multiple times - this is not permitted.", + ex, + null); } - commandStartTimestamp = Time.CurrentTimeMillis; + _commandStartTimestamp = Time.CurrentTimeMillis; if (this.CommandOptions.RequestLogEnabled) { // log this command execution regardless of what happened - if (currentRequestLog != null) + if (_currentRequestLog != null) { - currentRequestLog.AddExecutedCommand(this); + _currentRequestLog.AddExecutedCommand(this); } } - } + protected bool PutInCacheIfAbsent(Task hystrixTask, out Task fromCache) { fromCache = null; if (IsRequestCachingEnabled && CacheKey != null) { // wrap it for caching - fromCache = requestCache.PutIfAbsent>(CacheKey, hystrixTask); + fromCache = _requestCache.PutIfAbsent>(CacheKey, hystrixTask); if (fromCache != null) { // another thread beat us so we'll use the cached value instead - isResponseFromCache = true; + _isResponseFromCache = true; HandleRequestCacheHitAndEmitValues(fromCache, this); return true; } } + return false; } + protected void ApplyHystrixSemantics() { - if (commandState.Value.Equals(CommandState.UNSUBSCRIBED)) { return; @@ -499,10 +582,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix { // mark that we're starting execution on the ExecutionHook // if this hook throws an exception, then a fast-fail occurs with no fallback. No state is left inconsistent - executionHook.OnStart(this); + _executionHook.OnStart(this); /* determine if we're allowed to execute */ - if (circuitBreaker.AllowRequest) + if (_circuitBreaker.AllowRequest) { SemaphoreSlim executionSemaphore = GetExecutionSemaphore(); @@ -511,10 +594,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix try { /* used to track userThreadExecutionTime */ - executionResult = executionResult.SetInvocationStartTime(Time.CurrentTimeMillis); + _executionResult = _executionResult.SetInvocationStartTime(Time.CurrentTimeMillis); ExecuteCommandWithSpecifiedIsolation(); if (tcs.IsFaulted) - eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); + { + _eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); + } } finally { @@ -525,17 +610,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix { HandleSemaphoreRejectionViaFallback(); } - } else { HandleShortCircuitViaFallback(); - if (tcs.IsFaulted) // ??????? - eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); - + if (tcs.IsFaulted) + { + _eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); + } } - } finally { @@ -546,609 +630,109 @@ namespace Steeltoe.CircuitBreaker.Hystrix TerminateCommandCleanup(); } } - } + protected void StartCommand() { - try { - this.execThreadTask.Start(this.threadPool.GetTaskScheduler()); - } catch(Exception e) + this._execThreadTask.Start(this._threadPool.GetTaskScheduler()); + } + catch (Exception e) { HandleFallback(e); - if (tcs.IsFaulted) - eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); + if (tcs.IsFaulted) + { + _eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); + } UnsubscribeCommandCleanup(); FireOnCompletedHook(); TerminateCommandCleanup(); - } - } + protected Exception DecomposeException(Exception e) { - if (e is HystrixBadRequestException) { return (HystrixBadRequestException)e; } + if (e.InnerException is HystrixBadRequestException) { return (HystrixBadRequestException)e.InnerException; } + if (e is HystrixRuntimeException) { return (HystrixRuntimeException)e; } + // if we have an exception we know about we'll throw it directly without the wrapper exception if (e.InnerException is HystrixRuntimeException) { return (HystrixRuntimeException)e.InnerException; } + // we don't know what kind of exception this is so create a generic message and throw a new HystrixRuntimeException - String message = LogMessagePrefix + " failed while executing. {0}"; + string message = LogMessagePrefix + " failed while executing. {0}"; logger?.LogDebug(message, e); // debug only since we're throwing the exception and someone higher will do something with it return new HystrixRuntimeException(FailureType.COMMAND_EXCEPTION, this.GetType(), message, e, null); } - private void TimeoutThreadAction() - { - if (!Time.WaitUntil(() => - { - return isCommandTimedOut.Value == TimedOutStatus.COMPLETED; - - }, options.ExecutionTimeoutInMilliseconds)) - { - if (this.isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) - { - timeoutTcs.Cancel(); - - // report timeout failure - this.eventNotifier.MarkEvent(HystrixEventType.TIMEOUT, this.commandKey); - - if (threadState.CompareAndSet(ThreadState.STARTED, ThreadState.UNSUBSCRIBED)) - { - HandleThreadEnd(); - } - threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.UNSUBSCRIBED); - - HandleFallback(new HystrixTimeoutException("timed out while executing run()")); - - if (tcs.IsFaulted) // ??????? - eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); - - UnsubscribeCommandCleanup(); - FireOnCompletedHook(); - TerminateCommandCleanup(); - } - } - } - private void ExecuteCommandWithThreadAction() - { - this.threadStartTimestamp = Time.CurrentTimeMillis; - - if (this.token.IsCancellationRequested) - { - tcs.TrySetCanceled(); - UnsubscribeCommandCleanup(); - threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.UNSUBSCRIBED); - TerminateCommandCleanup(); - return; - } - - try - { - executionResult = executionResult.SetExecutionOccurred(); - if (!commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) - { - tcs.TrySetException(new InvalidOperationException("execution attempted while in state : " + commandState.Value)); - return; - } - - metrics.MarkCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.THREAD); - - if (isCommandTimedOut.Value == TimedOutStatus.TIMED_OUT) - { - // the command timed out in the wrapping thread so we will return immediately - // and not increment any of the counters below or other such logic - tcs.TrySetException(new HystrixTimeoutException("timed out before executing run()")); - return; - } - if (threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.STARTED)) - { - //we have not been unsubscribed, so should proceed - HystrixCounters.IncrementGlobalConcurrentThreads(); - threadPool.MarkThreadExecution(); - // store the command that is being run - //endCurrentThreadExecutingCommand = Hystrix.StartCurrentThreadExecutingCommand(CommandKey); - executionResult = executionResult.SetExecutedInThread(); - /** - * If any of these hooks throw an exception, then it appears as if the actual execution threw an error - */ - try - { - - if (options.ExecutionTimeoutEnabled) - { - - Task timerTask = new Task(() => { TimeoutThreadAction(); }, TaskCreationOptions.LongRunning); - timerTask.Start(TaskScheduler.Default); - } - - executionHook.OnThreadStart(this); - //executionHook.OnRunStart(_cmd); Deprecated - executionHook.OnExecutionStart(this); - TResult result = ExecuteRun(); - if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) - { - MarkEmits(); - result = (TResult)WrapWithOnEmitHook(result); - tcs.TrySetResult(result); - WrapWithOnExecutionSuccess(); - if (threadState.CompareAndSet(ThreadState.STARTED, ThreadState.TERMINAL)) - { - HandleThreadEnd(); - } - threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.TERMINAL); - MarkCompleted(); - } - } - catch (Exception e) - { - - if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) - { - if (threadState.CompareAndSet(ThreadState.STARTED, ThreadState.TERMINAL)) - { - HandleThreadEnd(); - } - threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.TERMINAL); - HandleFallback(e); - } - } - } - else - { - //command has already been unsubscribed, so return immediately - tcs.TrySetException(new Exception("unsubscribed before executing run()")); - return; - } - } - finally - { - if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) - { - // applyHystrixSemantics.doOnError(markexceptionthrown) - if (tcs.IsFaulted) // ??????? - eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); - - UnsubscribeCommandCleanup(); - FireOnCompletedHook(); - TerminateCommandCleanup(); - } - } - - } - private void ExecuteCommandWithSpecifiedIsolation() - { - - if (options.ExecutionIsolationStrategy == ExecutionIsolationStrategy.THREAD) - { - Action threadExec = () => { ExecuteCommandWithThreadAction(); }; - execThreadTask = new Task(threadExec, CancellationToken.None, TaskCreationOptions.LongRunning); - - } - else - { - - executionResult = executionResult.SetExecutionOccurred(); - if (!commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) - { - throw new InvalidOperationException("execution attempted while in state : " + commandState.Value); - } - - metrics.MarkCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.SEMAPHORE); - - if (options.ExecutionTimeoutEnabled) - { - Task timerTask = new Task(() => { TimeoutThreadAction(); }, TaskCreationOptions.LongRunning); - timerTask.Start(TaskScheduler.Default); - } - - try - { - executionHook.OnExecutionStart(this); - TResult result = ExecuteRun(); //the getUserExecutionObservable method already wraps sync exceptions, so this shouldn't throw - if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) - { - MarkEmits(); - result = WrapWithOnEmitHook(result); - tcs.TrySetResult(result); - WrapWithOnExecutionSuccess(); - MarkCompleted(); - - } - } catch (Exception e) - { - if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) - { - HandleFallback(e); - } - } - } - } - private TResult ExecuteRun() - { - - try - { - - TResult result = DoRun(); - isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); - - if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) - result = WrapWithOnExecutionEmitHook(result); - else - result = default(TResult); - return result; - - } - catch (AggregateException e) - { - - isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); - - Exception flatten = GetException(e); - if (flatten.InnerException is TaskCanceledException && isCommandTimedOut.Value == TimedOutStatus.TIMED_OUT) - { - // End task pass - return default(TResult); - } - - - Exception ex = WrapWithOnExecutionErrorHook(flatten.InnerException); - if (ex == flatten.InnerException) - throw; - - throw ex; - } catch (OperationCanceledException e) - { - isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); - - if (isCommandTimedOut.Value == TimedOutStatus.TIMED_OUT) - { - // End task pass - return default(TResult); - } - - Exception ex = WrapWithOnExecutionErrorHook(e); - if (e == ex) - throw; - - throw ex; - - } - catch (Exception ex) - { - isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); - - Exception returned = WrapWithOnExecutionErrorHook(ex); - if (ex == returned) - throw; - throw returned; - } - } - private TResult ExecuteRunFallback() - { - try - { - return DoFallback(); - } catch (AggregateException ex) - { - Exception flatten = GetException(ex); - throw flatten.InnerException; - } - - } - private bool IsUnrecoverableError(Exception t) - { - - Exception cause = t; - - if (cause is OutOfMemoryException) - { - return true; - } - else if (cause is VerificationException) - { - return true; - } - else if (cause is InsufficientExecutionStackException) - { - return true; - } - else if (cause is BadImageFormatException) - { - return true; - } - return false; - } - private bool IsRecoverableError(Exception t) - { - return !IsUnrecoverableError(t); - } - private void UnsubscribeCommandCleanup() - { - if (tcs.IsCanceled) - { - if (commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.UNSUBSCRIBED)) - { - if (!executionResult.ContainsTerminalEvent) - { - eventNotifier.MarkEvent(HystrixEventType.CANCELLED, CommandKey); - executionResultAtTimeOfCancellation = executionResult - .AddEvent((int)(Time.CurrentTimeMillis - commandStartTimestamp), HystrixEventType.CANCELLED); - } - HandleCommandEnd(false); //user code never ran - } - else if (commandState.CompareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.UNSUBSCRIBED)) - { - if (!executionResult.ContainsTerminalEvent) - { - eventNotifier.MarkEvent(HystrixEventType.CANCELLED, CommandKey); - executionResultAtTimeOfCancellation = executionResult - .AddEvent((int)(Time.CurrentTimeMillis - commandStartTimestamp), HystrixEventType.CANCELLED); - } - HandleCommandEnd(true); //user code did run - } - } - } - private void TerminateCommandCleanup() - { - if (tcs.IsCompleted) - { - if (commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.TERMINAL)) - { - HandleCommandEnd(false); //user code never ran - } - else if (commandState.CompareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.TERMINAL)) - { - HandleCommandEnd(true); //user code did run - } - tcs.Commit(); - } - } - private void FireOnCompletedHook() - { - if (tcs.IsCompleted && !tcs.IsFaulted && !tcs.IsCanceled) - { - try - { - executionHook.OnSuccess(this); - } - catch (Exception hookEx) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onSuccess - {0}", hookEx); - } - } - } - private Exception GetException(AggregateException e) - { - return e.Flatten(); - } - protected internal SemaphoreSlim GetExecutionSemaphore() - { - if (options.ExecutionIsolationStrategy == ExecutionIsolationStrategy.SEMAPHORE) - { - if (executionSemaphoreOverride == null) - { - return executionSemaphorePerCircuit.GetOrAddEx(commandKey.Name, (k) => new SemaphoreSlim(options.ExecutionIsolationSemaphoreMaxConcurrentRequests)); - } - else - { - return executionSemaphoreOverride; - } - } - else - { - // return NoOp implementation since we're not using SEMAPHORE isolation - return null; - } - } - protected internal SemaphoreSlim GetFallbackSemaphore() - { - if (fallbackSemaphoreOverride == null) - { - return fallbackSemaphorePerCircuit.GetOrAddEx(commandKey.Name, (k) => new SemaphoreSlim(options.FallbackIsolationSemaphoreMaxConcurrentRequests)); - } - else - { - return fallbackSemaphoreOverride; - } - } protected abstract TResult DoRun(); + protected abstract TResult DoFallback(); - #region Marks - private void MarkFallbackEmit() - { - if (ShouldOutputOnNextEvents) - { - executionResult = executionResult.AddEvent(HystrixEventType.FALLBACK_EMIT); - eventNotifier.MarkEvent(HystrixEventType.FALLBACK_EMIT, commandKey); - } - } - private void MarkFallbackCompleted() - { - - long latency2 = Time.CurrentTimeMillis - executionResult.StartTimestamp; - eventNotifier.MarkEvent(HystrixEventType.FALLBACK_SUCCESS, commandKey); - executionResult = executionResult.AddEvent((int)latency2, HystrixEventType.FALLBACK_SUCCESS); - - } - private void MarkEmits() - { - if (ShouldOutputOnNextEvents) - { - executionResult = executionResult.AddEvent(HystrixEventType.EMIT); - eventNotifier.MarkEvent(HystrixEventType.EMIT, commandKey); - } - if (CommandIsScalar) - { - long latency = Time.CurrentTimeMillis - executionResult.StartTimestamp; - eventNotifier.MarkCommandExecution(CommandKey, options.ExecutionIsolationStrategy, (int)latency, executionResult.OrderedList); - eventNotifier.MarkEvent(HystrixEventType.SUCCESS, commandKey); - executionResult = executionResult.AddEvent((int)latency, HystrixEventType.SUCCESS); - circuitBreaker.MarkSuccess(); - } - } - private void MarkCompleted() - { - if (tcs.IsCompleted) - { - if (!CommandIsScalar) - { - long latency = Time.CurrentTimeMillis - executionResult.StartTimestamp; - eventNotifier.MarkCommandExecution(CommandKey, options.ExecutionIsolationStrategy, (int)latency, executionResult.OrderedList); - eventNotifier.MarkEvent(HystrixEventType.SUCCESS, commandKey); - executionResult = executionResult.AddEvent((int)latency, HystrixEventType.SUCCESS); - circuitBreaker.MarkSuccess(); - } - } - } - internal void MarkAsCollapsedCommand(IHystrixCollapserKey collapserKey, int sizeOfBatch) - { - eventNotifier.MarkEvent(HystrixEventType.COLLAPSED, this.commandKey); - executionResult = executionResult.MarkCollapsed(collapserKey, sizeOfBatch); - } - #endregion Marks - - #region Wraps - private void WrapWithOnFallbackSuccessHook() - { - try - { - executionHook.OnFallbackSuccess(this); - } - catch (Exception hookEx) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onFallbackSuccess - {0}", hookEx); - } - } - private TResult WrapWithOnFallbackEmitHook(TResult r) - { - try - { - return executionHook.OnFallbackEmit(this, r); - } - catch (Exception hookEx ) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onFallbackEmit - {0}", hookEx); - return r; - } - } - private void WrapWithOnFallbackStartHook() - { - try - { - executionHook.OnFallbackStart(this); - } - catch (Exception hookEx ) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.OnFallbackStart - {0}", hookEx); - } - } - private TResult WrapWithOnEmitHook(TResult result) - { - - try - { - return executionHook.OnEmit(this, result); - } - catch (Exception hookEx ) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onEmit - {0}", hookEx); - return result; - } - - - } - private Exception WrapWithOnErrorHook(FailureType failureType, Exception e) - { - try - { - return executionHook.OnError(this, failureType, e); - } - catch (Exception hookEx ) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onError - {0}", hookEx); - return e; - } - } - private void WrapWithOnExecutionSuccess() - { - try - { - executionHook.OnExecutionSuccess(this); - } - catch (Exception hookEx ) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onExecutionSuccess - {0}", hookEx); - } - } - private Exception WrapWithOnExecutionErrorHook(Exception e) - { - try - { - return executionHook.OnExecutionError(this, e); - } - catch (Exception hookEx ) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onExecutionError - {0}", hookEx); - return e; - } - } - private TResult WrapWithOnExecutionEmitHook(TResult r) - { - try - { - return executionHook.OnExecutionEmit(this, r); - } catch (Exception hookEx ) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onExecutionEmit - {0}", hookEx); - return r; - } - } - private Exception WrapWithOnFallbackErrorHook(Exception e) - { - try - { - if (IsFallbackUserDefined) - { - return executionHook.OnFallbackError(this, e); - } - else - { - return e; - } - } - catch (Exception hookEx) - { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onFallbackError - {0}", hookEx); - return e; - } - } - #endregion Wraps - #region Handlers + protected virtual void HandleCleanUpAfterResponseFromCache(bool commandExecutionStarted) + { + long latency = Time.CurrentTimeMillis - _commandStartTimestamp; + _executionResult = _executionResult.AddEvent(-1, HystrixEventType.RESPONSE_FROM_CACHE) + .MarkUserThreadCompletion(latency) + .SetNotExecutedInThread(); + ExecutionResult cacheOnlyForMetrics = ExecutionResult.From(HystrixEventType.RESPONSE_FROM_CACHE) + .MarkUserThreadCompletion(latency); + _metrics.MarkCommandDone(cacheOnlyForMetrics, commandKey, threadPoolKey, commandExecutionStarted); + _eventNotifier.MarkEvent(HystrixEventType.RESPONSE_FROM_CACHE, commandKey); + } + + protected virtual void HandleCommandEnd(bool commandExecutionStarted) + { + long userThreadLatency = Time.CurrentTimeMillis - _commandStartTimestamp; + _executionResult = _executionResult.MarkUserThreadCompletion((int)userThreadLatency); + if (_executionResultAtTimeOfCancellation == null) + { + _metrics.MarkCommandDone(_executionResult, commandKey, threadPoolKey, commandExecutionStarted); + } + else + { + _metrics.MarkCommandDone(_executionResultAtTimeOfCancellation, commandKey, threadPoolKey, commandExecutionStarted); + } + } + + protected virtual void HandleThreadEnd() + { + HystrixCounters.DecrementGlobalConcurrentThreads(); + _threadPool.MarkThreadCompletion(); + try + { + _executionHook.OnThreadComplete(this); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onThreadComplete: {0}", hookEx); + } + } + private void HandleFallbackOrThrowException(HystrixEventType eventType, FailureType failureType, string message, Exception originalException) { - long latency = Time.CurrentTimeMillis - executionResult.StartTimestamp; + long latency = Time.CurrentTimeMillis - _executionResult.StartTimestamp; + // record the executionResult // do this before executing fallback so it can be queried from within getFallback (see See https://github.com/Netflix/Hystrix/pull/144) - executionResult = executionResult.AddEvent((int)latency, eventType); + _executionResult = _executionResult.AddEvent((int)latency, eventType); if (IsUnrecoverableError(originalException)) { @@ -1174,7 +758,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix SemaphoreSlim fallbackSemaphore = GetFallbackSemaphore(); - TResult fallbackExecutionResult; // acquire a permit @@ -1189,9 +772,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix } else { - //same logic as above without the hook invocation + // same logic as above without the hook invocation fallbackExecutionResult = ExecuteRunFallback(); } + fallbackExecutionResult = WrapWithOnFallbackEmitHook(fallbackExecutionResult); MarkFallbackEmit(); fallbackExecutionResult = WrapWithOnEmitHook(fallbackExecutionResult); @@ -1203,7 +787,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix WrapWithOnFallbackErrorHook(ex); HandleFallbackError(ex, failureType, message, originalException); return; - } finally { @@ -1212,13 +795,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix tcs.TrySetResult((TResult)fallbackExecutionResult); return; - } else { HandleFallbackRejectionByEmittingError(); } - } else { @@ -1226,80 +807,113 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } } + private void HandleFallbackError(Exception fe, FailureType failureType, string message, Exception originalException) { Exception e = originalException; if (fe is InvalidOperationException) { - long latency = Time.CurrentTimeMillis - executionResult.StartTimestamp; + long latency = Time.CurrentTimeMillis - _executionResult.StartTimestamp; logger?.LogDebug("No fallback for HystrixCommand: {0} ", fe); // debug only since we're throwing the exception and someone higher will do something with it - eventNotifier.MarkEvent(HystrixEventType.FALLBACK_MISSING, commandKey); - executionResult = executionResult.AddEvent((int)latency, HystrixEventType.FALLBACK_MISSING); + _eventNotifier.MarkEvent(HystrixEventType.FALLBACK_MISSING, commandKey); + _executionResult = _executionResult.AddEvent((int)latency, HystrixEventType.FALLBACK_MISSING); /* executionHook for all errors */ e = WrapWithOnErrorHook(failureType, e); - tcs.TrySetException(new HystrixRuntimeException(failureType, this.GetType(), LogMessagePrefix + " " + message + " and no fallback available.", e, fe)); + tcs.TrySetException(new HystrixRuntimeException( + failureType, + this.GetType(), + LogMessagePrefix + " " + message + " and no fallback available.", + e, + fe)); } else { - long latency = Time.CurrentTimeMillis - executionResult.StartTimestamp; + long latency = Time.CurrentTimeMillis - _executionResult.StartTimestamp; logger?.LogDebug("HystrixCommand execution {0} and fallback failed: {1}", failureType.ToString(), fe); - eventNotifier.MarkEvent(HystrixEventType.FALLBACK_FAILURE, commandKey); - executionResult = executionResult.AddEvent((int)latency, HystrixEventType.FALLBACK_FAILURE); + _eventNotifier.MarkEvent(HystrixEventType.FALLBACK_FAILURE, commandKey); + _executionResult = _executionResult.AddEvent((int)latency, HystrixEventType.FALLBACK_FAILURE); /* executionHook for all errors */ e = WrapWithOnErrorHook(failureType, e); - tcs.TrySetException(new HystrixRuntimeException(failureType, this.GetType(), LogMessagePrefix + " " + message + " and fallback failed.", e, fe)); + tcs.TrySetException(new HystrixRuntimeException( + failureType, + this.GetType(), + LogMessagePrefix + " " + message + " and fallback failed.", + e, + fe)); } - } - private void HandleFallbackDisabledByEmittingError(Exception underlying, FailureType failureType, String message) + + private void HandleFallbackDisabledByEmittingError(Exception underlying, FailureType failureType, string message) { /* fallback is disabled so throw HystrixRuntimeException */ logger?.LogDebug("Fallback disabled for HystrixCommand so will throw HystrixRuntimeException: {0} ", underlying); // debug only since we're throwing the exception and someone higher will do something with it /* executionHook for all errors */ Exception wrapped = WrapWithOnErrorHook(failureType, underlying); - tcs.TrySetException(new HystrixRuntimeException(failureType, this.GetType(), LogMessagePrefix + " " + message + " and fallback disabled.", wrapped, null)); + tcs.TrySetException(new HystrixRuntimeException( + failureType, + this.GetType(), + LogMessagePrefix + " " + message + " and fallback disabled.", + wrapped, + null)); } + private void HandleFallbackRejectionByEmittingError() { - long latencyWithFallback = Time.CurrentTimeMillis - executionResult.StartTimestamp; - eventNotifier.MarkEvent(HystrixEventType.FALLBACK_REJECTION, commandKey); - executionResult = executionResult.AddEvent((int)latencyWithFallback, HystrixEventType.FALLBACK_REJECTION); + long latencyWithFallback = Time.CurrentTimeMillis - _executionResult.StartTimestamp; + _eventNotifier.MarkEvent(HystrixEventType.FALLBACK_REJECTION, commandKey); + _executionResult = _executionResult.AddEvent((int)latencyWithFallback, HystrixEventType.FALLBACK_REJECTION); logger?.LogDebug("HystrixCommand Fallback Rejection."); // debug only since we're throwing the exception and someone higher will do something with it // if we couldn't acquire a permit, we "fail fast" by throwing an exception - tcs.TrySetException(new HystrixRuntimeException(FailureType.REJECTED_SEMAPHORE_FALLBACK, this.GetType(), LogMessagePrefix + " fallback execution rejected.", null, null)); + tcs.TrySetException(new HystrixRuntimeException( + FailureType.REJECTED_SEMAPHORE_FALLBACK, + this.GetType(), + LogMessagePrefix + " fallback execution rejected.", + null, + null)); } + private void HandleSemaphoreRejectionViaFallback() { Exception semaphoreRejectionException = new Exception("could not acquire a semaphore for execution"); - executionResult = executionResult.SetExecutionException(semaphoreRejectionException); - eventNotifier.MarkEvent(HystrixEventType.SEMAPHORE_REJECTED, commandKey); + _executionResult = _executionResult.SetExecutionException(semaphoreRejectionException); + _eventNotifier.MarkEvent(HystrixEventType.SEMAPHORE_REJECTED, commandKey); logger?.LogDebug("HystrixCommand Execution Rejection by Semaphore."); // debug only since we're throwing the exception and someone higher will do something with it // retrieve a fallback or throw an exception if no fallback available - HandleFallbackOrThrowException(HystrixEventType.SEMAPHORE_REJECTED, FailureType.REJECTED_SEMAPHORE_EXECUTION, - "could not acquire a semaphore for execution", semaphoreRejectionException); + HandleFallbackOrThrowException( + HystrixEventType.SEMAPHORE_REJECTED, + FailureType.REJECTED_SEMAPHORE_EXECUTION, + "could not acquire a semaphore for execution", + semaphoreRejectionException); } + private void HandleShortCircuitViaFallback() { // record that we are returning a short-circuited fallback - eventNotifier.MarkEvent(HystrixEventType.SHORT_CIRCUITED, commandKey); + _eventNotifier.MarkEvent(HystrixEventType.SHORT_CIRCUITED, commandKey); + // short-circuit and go directly to fallback (or throw an exception if no fallback implemented) Exception shortCircuitException = new Exception("Hystrix circuit short-circuited and is OPEN"); - executionResult = executionResult.SetExecutionException(shortCircuitException); + _executionResult = _executionResult.SetExecutionException(shortCircuitException); try { - HandleFallbackOrThrowException(HystrixEventType.SHORT_CIRCUITED, FailureType.SHORTCIRCUIT, "short-circuited", shortCircuitException); + HandleFallbackOrThrowException( + HystrixEventType.SHORT_CIRCUITED, + FailureType.SHORTCIRCUIT, + "short-circuited", + shortCircuitException); } catch (Exception e) { tcs.TrySetException(e); } } + private void HandleFallback(Exception e) { if (e is TaskCanceledException || @@ -1309,11 +923,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix tcs.TrySetCanceled(); return; } + if (e is TaskSchedulerException) { e = e.InnerException; } - executionResult = executionResult.SetExecutionException(e); + + _executionResult = _executionResult.SetExecutionException(e); if (e is RejectedExecutionException) { HandleThreadPoolRejectionViaFallback(e); @@ -1331,28 +947,29 @@ namespace Steeltoe.CircuitBreaker.Hystrix HandleFailureViaFallback(e); } } + private void HandleFailureViaFallback(Exception underlying) { - logger?.LogDebug("Error executing HystrixCommand.Run(). Proceeding to fallback logic...: {0}", underlying); // report failure - eventNotifier.MarkEvent(HystrixEventType.FAILURE, commandKey); + _eventNotifier.MarkEvent(HystrixEventType.FAILURE, commandKey); // record the exception - executionResult = executionResult.SetException(underlying); + _executionResult = _executionResult.SetException(underlying); HandleFallbackOrThrowException(HystrixEventType.FAILURE, FailureType.COMMAND_EXCEPTION, "failed", underlying); } + private void HandleBadRequestByEmittingError(Exception underlying) { Exception toEmit = underlying; try { - long executionLatency = Time.CurrentTimeMillis - executionResult.StartTimestamp; - eventNotifier.MarkEvent(HystrixEventType.BAD_REQUEST, commandKey); - executionResult = executionResult.AddEvent((int)executionLatency, HystrixEventType.BAD_REQUEST); - Exception decorated = executionHook.OnError(this, FailureType.BAD_REQUEST_EXCEPTION, underlying); + long executionLatency = Time.CurrentTimeMillis - _executionResult.StartTimestamp; + _eventNotifier.MarkEvent(HystrixEventType.BAD_REQUEST, commandKey); + _executionResult = _executionResult.AddEvent((int)executionLatency, HystrixEventType.BAD_REQUEST); + Exception decorated = _executionHook.OnError(this, FailureType.BAD_REQUEST_EXCEPTION, underlying); if (decorated is HystrixBadRequestException) { @@ -1370,55 +987,60 @@ namespace Steeltoe.CircuitBreaker.Hystrix tcs.TrySetException(toEmit); } + private void HandleTimeoutViaFallback() { HandleFallbackOrThrowException(HystrixEventType.TIMEOUT, FailureType.TIMEOUT, "timed-out", new TimeoutException()); } + private void HandleThreadPoolRejectionViaFallback(Exception underlying) { - eventNotifier.MarkEvent(HystrixEventType.THREAD_POOL_REJECTED, commandKey); - threadPool.MarkThreadRejection(); + _eventNotifier.MarkEvent(HystrixEventType.THREAD_POOL_REJECTED, commandKey); + _threadPool.MarkThreadRejection(); + // use a fallback instead (or throw exception if not implemented) HandleFallbackOrThrowException(HystrixEventType.THREAD_POOL_REJECTED, FailureType.REJECTED_THREAD_EXECUTION, "could not be queued for execution", underlying); } - private void HandleRequestCacheHitAndEmitValues(Task fromCache, AbstractCommand _cmd) + + private void HandleRequestCacheHitAndEmitValues(Task fromCache, AbstractCommand cmd) { try { - executionHook.OnCacheHit(this); + _executionHook.OnCacheHit(this); } catch (Exception hookEx) { logger?.LogWarning("Error calling HystrixCommandExecutionHook.onCacheHit: {0}", hookEx); } - if (_cmd.token.IsCancellationRequested) + if (cmd._token.IsCancellationRequested) { - _cmd.executionResult = _cmd.executionResult.AddEvent(HystrixEventType.CANCELLED); - _cmd.executionResult = _cmd.executionResult.SetExecutionLatency(-1); + cmd._executionResult = cmd._executionResult.AddEvent(HystrixEventType.CANCELLED); + cmd._executionResult = cmd._executionResult.SetExecutionLatency(-1); } else { if (!fromCache.IsCompleted) { - fromCache.Wait(_cmd.token); + fromCache.Wait(cmd._token); } + AbstractCommand originalCommand = fromCache.AsyncState as AbstractCommand; if (originalCommand != null) { - _cmd.executionResult = originalCommand.executionResult; + cmd._executionResult = originalCommand._executionResult; } } - if (_cmd.token.IsCancellationRequested) + if (cmd._token.IsCancellationRequested) { if (commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.UNSUBSCRIBED)) { - HandleCleanUpAfterResponseFromCache(false); //user code never ran + HandleCleanUpAfterResponseFromCache(false); // user code never ran } else if (commandState.CompareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.UNSUBSCRIBED)) { - HandleCleanUpAfterResponseFromCache(true); //user code did run + HandleCleanUpAfterResponseFromCache(true); // user code did run } } @@ -1426,58 +1048,571 @@ namespace Steeltoe.CircuitBreaker.Hystrix { if (commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.TERMINAL)) { - HandleCleanUpAfterResponseFromCache(false); //user code never ran + HandleCleanUpAfterResponseFromCache(false); // user code never ran } else if (commandState.CompareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.TERMINAL)) { - HandleCleanUpAfterResponseFromCache(true); //user code did run + HandleCleanUpAfterResponseFromCache(true); // user code did run } } } - protected virtual void HandleCleanUpAfterResponseFromCache(bool commandExecutionStarted) - { - long latency = Time.CurrentTimeMillis - commandStartTimestamp; - executionResult = executionResult.AddEvent(-1, HystrixEventType.RESPONSE_FROM_CACHE) - .MarkUserThreadCompletion(latency) - .SetNotExecutedInThread(); - ExecutionResult cacheOnlyForMetrics = ExecutionResult.From(HystrixEventType.RESPONSE_FROM_CACHE) - .MarkUserThreadCompletion(latency); - metrics.MarkCommandDone(cacheOnlyForMetrics, commandKey, threadPoolKey, commandExecutionStarted); - eventNotifier.MarkEvent(HystrixEventType.RESPONSE_FROM_CACHE, commandKey); - } - protected virtual void HandleCommandEnd(bool commandExecutionStarted) - { + #endregion Handlers - long userThreadLatency = Time.CurrentTimeMillis - commandStartTimestamp; - executionResult = executionResult.MarkUserThreadCompletion((int)userThreadLatency); - if (executionResultAtTimeOfCancellation == null) + private void TimeoutThreadAction() + { + if (!Time.WaitUntil( + () => { - metrics.MarkCommandDone(executionResult, commandKey, threadPoolKey, commandExecutionStarted); + return isCommandTimedOut.Value == TimedOutStatus.COMPLETED; + }, options.ExecutionTimeoutInMilliseconds)) + { + if (isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) + { + _timeoutTcs.Cancel(); + + // report timeout failure + _eventNotifier.MarkEvent(HystrixEventType.TIMEOUT, commandKey); + + if (threadState.CompareAndSet(ThreadState.STARTED, ThreadState.UNSUBSCRIBED)) + { + HandleThreadEnd(); + } + + threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.UNSUBSCRIBED); + + HandleFallback(new HystrixTimeoutException("timed out while executing run()")); + + if (tcs.IsFaulted) + { + _eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); + } + + UnsubscribeCommandCleanup(); + FireOnCompletedHook(); + TerminateCommandCleanup(); + } + } + } + + private void ExecuteCommandWithThreadAction() + { + _threadStartTimestamp = Time.CurrentTimeMillis; + + if (_token.IsCancellationRequested) + { + tcs.TrySetCanceled(); + UnsubscribeCommandCleanup(); + threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.UNSUBSCRIBED); + TerminateCommandCleanup(); + return; + } + + try + { + _executionResult = _executionResult.SetExecutionOccurred(); + if (!commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) + { + tcs.TrySetException(new InvalidOperationException("execution attempted while in state : " + commandState.Value)); + return; + } + + _metrics.MarkCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.THREAD); + + if (isCommandTimedOut.Value == TimedOutStatus.TIMED_OUT) + { + // the command timed out in the wrapping thread so we will return immediately + // and not increment any of the counters below or other such logic + tcs.TrySetException(new HystrixTimeoutException("timed out before executing run()")); + return; + } + + if (threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.STARTED)) + { + // we have not been unsubscribed, so should proceed + HystrixCounters.IncrementGlobalConcurrentThreads(); + _threadPool.MarkThreadExecution(); + + // store the command that is being run + _executionResult = _executionResult.SetExecutedInThread(); + /** + * If any of these hooks throw an exception, then it appears as if the actual execution threw an error + */ + try + { + if (options.ExecutionTimeoutEnabled) + { + Task timerTask = new Task(() => { TimeoutThreadAction(); }, TaskCreationOptions.LongRunning); + timerTask.Start(TaskScheduler.Default); + } + + _executionHook.OnThreadStart(this); + _executionHook.OnExecutionStart(this); + TResult result = ExecuteRun(); + if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) + { + MarkEmits(); + result = WrapWithOnEmitHook(result); + tcs.TrySetResult(result); + WrapWithOnExecutionSuccess(); + if (threadState.CompareAndSet(ThreadState.STARTED, ThreadState.TERMINAL)) + { + HandleThreadEnd(); + } + + threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.TERMINAL); + MarkCompleted(); + } + } + catch (Exception e) + { + if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) + { + if (threadState.CompareAndSet(ThreadState.STARTED, ThreadState.TERMINAL)) + { + HandleThreadEnd(); + } + + threadState.CompareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.TERMINAL); + HandleFallback(e); + } + } + } + else + { + // command has already been unsubscribed, so return immediately + tcs.TrySetException(new Exception("unsubscribed before executing run()")); + return; + } + } + finally + { + if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) + { + // applyHystrixSemantics.doOnError(markexceptionthrown) + if (tcs.IsFaulted) + { + _eventNotifier.MarkEvent(HystrixEventType.EXCEPTION_THROWN, CommandKey); + } + + UnsubscribeCommandCleanup(); + FireOnCompletedHook(); + TerminateCommandCleanup(); + } + } + } + + private void ExecuteCommandWithSpecifiedIsolation() + { + if (options.ExecutionIsolationStrategy == ExecutionIsolationStrategy.THREAD) + { + void threadExec() + { + ExecuteCommandWithThreadAction(); + } + + _execThreadTask = new Task(threadExec, CancellationToken.None, TaskCreationOptions.LongRunning); } else { - metrics.MarkCommandDone(executionResultAtTimeOfCancellation, commandKey, threadPoolKey, commandExecutionStarted); - } + _executionResult = _executionResult.SetExecutionOccurred(); + if (!commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) + { + throw new InvalidOperationException("execution attempted while in state : " + commandState.Value); + } + _metrics.MarkCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.SEMAPHORE); + + if (options.ExecutionTimeoutEnabled) + { + Task timerTask = new Task(() => { TimeoutThreadAction(); }, TaskCreationOptions.LongRunning); + timerTask.Start(TaskScheduler.Default); + } + + try + { + _executionHook.OnExecutionStart(this); + TResult result = ExecuteRun(); + if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) + { + MarkEmits(); + result = WrapWithOnEmitHook(result); + tcs.TrySetResult(result); + WrapWithOnExecutionSuccess(); + MarkCompleted(); + } + } + catch (Exception e) + { + if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) + { + HandleFallback(e); + } + } + } } - protected virtual void HandleThreadEnd() + + private TResult ExecuteRun() { - HystrixCounters.DecrementGlobalConcurrentThreads(); - threadPool.MarkThreadCompletion(); try { - executionHook.OnThreadComplete(this); + TResult result = DoRun(); + isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); + + if (isCommandTimedOut.Value != TimedOutStatus.TIMED_OUT) + { + result = WrapWithOnExecutionEmitHook(result); + } + else + { + result = default(TResult); + } + + return result; + } + catch (AggregateException e) + { + isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); + + Exception flatten = GetException(e); + if (flatten.InnerException is TaskCanceledException && isCommandTimedOut.Value == TimedOutStatus.TIMED_OUT) + { + // End task pass + return default(TResult); + } + + Exception ex = WrapWithOnExecutionErrorHook(flatten.InnerException); + if (ex == flatten.InnerException) + { + throw; + } + + throw ex; + } + catch (OperationCanceledException e) + { + isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); + + if (isCommandTimedOut.Value == TimedOutStatus.TIMED_OUT) + { + // End task pass + return default(TResult); + } + + Exception ex = WrapWithOnExecutionErrorHook(e); + if (e == ex) + { + throw; + } + + throw ex; + } + catch (Exception ex) + { + isCommandTimedOut.CompareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); + + Exception returned = WrapWithOnExecutionErrorHook(ex); + if (ex == returned) + { + throw; + } + + throw returned; + } + } + + private TResult ExecuteRunFallback() + { + try + { + return DoFallback(); + } + catch (AggregateException ex) + { + Exception flatten = GetException(ex); + throw flatten.InnerException; + } + } + + private bool IsUnrecoverableError(Exception t) + { + Exception cause = t; + + if (cause is OutOfMemoryException) + { + return true; + } + else if (cause is VerificationException) + { + return true; + } + else if (cause is InsufficientExecutionStackException) + { + return true; + } + else if (cause is BadImageFormatException) + { + return true; + } + + return false; + } + + private bool IsRecoverableError(Exception t) + { + return !IsUnrecoverableError(t); + } + + private void UnsubscribeCommandCleanup() + { + if (tcs.IsCanceled) + { + if (commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.UNSUBSCRIBED)) + { + if (!_executionResult.ContainsTerminalEvent) + { + _eventNotifier.MarkEvent(HystrixEventType.CANCELLED, CommandKey); + _executionResultAtTimeOfCancellation = _executionResult + .AddEvent((int)(Time.CurrentTimeMillis - _commandStartTimestamp), HystrixEventType.CANCELLED); + } + + HandleCommandEnd(false); // user code never ran + } + else if (commandState.CompareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.UNSUBSCRIBED)) + { + if (!_executionResult.ContainsTerminalEvent) + { + _eventNotifier.MarkEvent(HystrixEventType.CANCELLED, CommandKey); + _executionResultAtTimeOfCancellation = _executionResult + .AddEvent((int)(Time.CurrentTimeMillis - _commandStartTimestamp), HystrixEventType.CANCELLED); + } + + HandleCommandEnd(true); // user code did run + } + } + } + + private void TerminateCommandCleanup() + { + if (tcs.IsCompleted) + { + if (commandState.CompareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.TERMINAL)) + { + HandleCommandEnd(false); // user code never ran + } + else if (commandState.CompareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.TERMINAL)) + { + HandleCommandEnd(true); // user code did run + } + + tcs.Commit(); + } + } + + private void FireOnCompletedHook() + { + if (tcs.IsCompleted && !tcs.IsFaulted && !tcs.IsCanceled) + { + try + { + _executionHook.OnSuccess(this); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onSuccess - {0}", hookEx); + } + } + } + + private Exception GetException(AggregateException e) + { + return e.Flatten(); + } + + #region Marks + + private void MarkCollapsedCommand(IHystrixCollapserKey collapserKey, int sizeOfBatch) + { + _eventNotifier.MarkEvent(HystrixEventType.COLLAPSED, this.commandKey); + _executionResult = _executionResult.MarkCollapsed(collapserKey, sizeOfBatch); + } + + private void MarkFallbackEmit() + { + if (ShouldOutputOnNextEvents) + { + _executionResult = _executionResult.AddEvent(HystrixEventType.FALLBACK_EMIT); + _eventNotifier.MarkEvent(HystrixEventType.FALLBACK_EMIT, commandKey); + } + } + + private void MarkFallbackCompleted() + { + long latency2 = Time.CurrentTimeMillis - _executionResult.StartTimestamp; + _eventNotifier.MarkEvent(HystrixEventType.FALLBACK_SUCCESS, commandKey); + _executionResult = _executionResult.AddEvent((int)latency2, HystrixEventType.FALLBACK_SUCCESS); + } + + private void MarkEmits() + { + if (ShouldOutputOnNextEvents) + { + _executionResult = _executionResult.AddEvent(HystrixEventType.EMIT); + _eventNotifier.MarkEvent(HystrixEventType.EMIT, commandKey); + } + + if (CommandIsScalar) + { + long latency = Time.CurrentTimeMillis - _executionResult.StartTimestamp; + _eventNotifier.MarkCommandExecution(CommandKey, options.ExecutionIsolationStrategy, (int)latency, _executionResult.OrderedList); + _eventNotifier.MarkEvent(HystrixEventType.SUCCESS, commandKey); + _executionResult = _executionResult.AddEvent((int)latency, HystrixEventType.SUCCESS); + _circuitBreaker.MarkSuccess(); + } + } + + private void MarkCompleted() + { + if (tcs.IsCompleted) + { + if (!CommandIsScalar) + { + long latency = Time.CurrentTimeMillis - _executionResult.StartTimestamp; + _eventNotifier.MarkCommandExecution(CommandKey, options.ExecutionIsolationStrategy, (int)latency, _executionResult.OrderedList); + _eventNotifier.MarkEvent(HystrixEventType.SUCCESS, commandKey); + _executionResult = _executionResult.AddEvent((int)latency, HystrixEventType.SUCCESS); + _circuitBreaker.MarkSuccess(); + } + } + } + + #endregion Marks + + #region Wraps + private void WrapWithOnFallbackSuccessHook() + { + try + { + _executionHook.OnFallbackSuccess(this); } catch (Exception hookEx) { - logger?.LogWarning("Error calling HystrixCommandExecutionHook.onThreadComplete: {0}", hookEx); + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onFallbackSuccess - {0}", hookEx); } } - #endregion Handlers + + private TResult WrapWithOnFallbackEmitHook(TResult r) + { + try + { + return _executionHook.OnFallbackEmit(this, r); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onFallbackEmit - {0}", hookEx); + return r; + } + } + + private void WrapWithOnFallbackStartHook() + { + try + { + _executionHook.OnFallbackStart(this); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.OnFallbackStart - {0}", hookEx); + } + } + + private TResult WrapWithOnEmitHook(TResult result) + { + try + { + return _executionHook.OnEmit(this, result); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onEmit - {0}", hookEx); + return result; + } + } + + private Exception WrapWithOnErrorHook(FailureType failureType, Exception e) + { + try + { + return _executionHook.OnError(this, failureType, e); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onError - {0}", hookEx); + return e; + } + } + + private void WrapWithOnExecutionSuccess() + { + try + { + _executionHook.OnExecutionSuccess(this); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onExecutionSuccess - {0}", hookEx); + } + } + + private Exception WrapWithOnExecutionErrorHook(Exception e) + { + try + { + return _executionHook.OnExecutionError(this, e); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onExecutionError - {0}", hookEx); + return e; + } + } + + private TResult WrapWithOnExecutionEmitHook(TResult r) + { + try + { + return _executionHook.OnExecutionEmit(this, r); + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onExecutionEmit - {0}", hookEx); + return r; + } + } + + private Exception WrapWithOnFallbackErrorHook(Exception e) + { + try + { + if (IsFallbackUserDefined) + { + return _executionHook.OnFallbackError(this, e); + } + else + { + return e; + } + } + catch (Exception hookEx) + { + logger?.LogWarning("Error calling HystrixCommandExecutionHook.onFallbackError - {0}", hookEx); + return e; + } + } + #endregion Wraps #region IHystrixInvokableInfo - protected readonly IHystrixCommandGroupKey commandGroup; + public IHystrixCommandGroupKey CommandGroup { get @@ -1485,7 +1620,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix return commandGroup; } } + protected readonly IHystrixCommandKey commandKey; + public IHystrixCommandKey CommandKey { get @@ -1493,7 +1630,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix return commandKey; } } + protected readonly IHystrixThreadPoolKey threadPoolKey; + public IHystrixThreadPoolKey ThreadPoolKey { get @@ -1501,7 +1640,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix return threadPoolKey; } } + protected readonly IHystrixCommandOptions options; + public IHystrixCommandOptions CommandOptions { get @@ -1514,7 +1655,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { - return executionResult.CommandRunStartTimeInNanos; + return _executionResult.CommandRunStartTimeInNanos; } } @@ -1546,7 +1687,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { - return executionResult.Exception; + return _executionResult.Exception; } } @@ -1554,7 +1695,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { - return options.CircuitBreakerForceOpen || (!options.CircuitBreakerForceClosed && circuitBreaker.IsOpen); + return options.CircuitBreakerForceOpen || (!options.CircuitBreakerForceClosed && _circuitBreaker.IsOpen); } } @@ -1586,7 +1727,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { - return isResponseFromCache; + return _isResponseFromCache; } } @@ -1650,7 +1791,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { - return metrics; + return _metrics; } } @@ -1682,7 +1823,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { - return executionResult.CollapserKey; + return _executionResult.CollapserKey; } } @@ -1699,20 +1840,28 @@ namespace Steeltoe.CircuitBreaker.Hystrix #region Properties protected bool _isFallbackUserDefined = false; + public virtual bool IsFallbackUserDefined { get { return _isFallbackUserDefined; } + set { _isFallbackUserDefined = value; } } + public Exception ExecutionException { - get { return executionResult.ExecutionException; } + get { return _executionResult.ExecutionException; } + } + + internal IHystrixCircuitBreaker CircuitBreaker + { + get { return this._circuitBreaker; } } protected virtual string CacheKey @@ -1724,6 +1873,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { return options.RequestCacheEnabled && CacheKey != null; } } + protected virtual string LogMessagePrefix { get @@ -1731,21 +1881,22 @@ namespace Steeltoe.CircuitBreaker.Hystrix return CommandKey.Name; } } + protected virtual ExecutionResult CommandResult { get { ExecutionResult resultToReturn; - if (executionResultAtTimeOfCancellation == null) + if (_executionResultAtTimeOfCancellation == null) { - resultToReturn = executionResult; + resultToReturn = _executionResult; } else { - resultToReturn = executionResultAtTimeOfCancellation; + resultToReturn = _executionResultAtTimeOfCancellation; } - if (isResponseFromCache) + if (_isResponseFromCache) { resultToReturn = resultToReturn.AddEvent(HystrixEventType.RESPONSE_FROM_CACHE); } @@ -1758,15 +1909,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix { get { return false; } } + protected virtual bool CommandIsScalar { get { return true; } } - - internal IHystrixCircuitBreaker CircuitBreaker - { - get { return this.circuitBreaker; } - } #endregion } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/HystrixCircuitBreakerFactory.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/HystrixCircuitBreakerFactory.cs similarity index 88% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/HystrixCircuitBreakerFactory.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/HystrixCircuitBreakerFactory.cs index 0d5774b..8f55ebd 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/HystrixCircuitBreakerFactory.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/HystrixCircuitBreakerFactory.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,16 @@ // 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. -// + using Steeltoe.CircuitBreaker.Hystrix.Util; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker { - public static class HystrixCircuitBreakerFactory { - private static ConcurrentDictionary circuitBreakersByCommand = new ConcurrentDictionary(); + public static IHystrixCircuitBreaker GetInstance(IHystrixCommandKey key, IHystrixCommandGroupKey group, IHystrixCommandOptions options, HystrixCommandMetrics metrics) { return circuitBreakersByCommand.GetOrAddEx(key.Name, (k) => new HystrixCircuitBreakerImpl(key, group, options, metrics)); @@ -31,8 +28,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker public static IHystrixCircuitBreaker GetInstance(IHystrixCommandKey key) { - IHystrixCircuitBreaker previouslyCached = null; - circuitBreakersByCommand.TryGetValue(key.Name, out previouslyCached); + circuitBreakersByCommand.TryGetValue(key.Name, out IHystrixCircuitBreaker previouslyCached); return previouslyCached; } @@ -40,6 +36,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker { circuitBreakersByCommand.Clear(); } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/HystrixCircuitBreakerImpl.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/HystrixCircuitBreakerImpl.cs similarity index 89% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/HystrixCircuitBreakerImpl.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/HystrixCircuitBreakerImpl.cs index d27d6fa..3cc1ef2 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/HystrixCircuitBreakerImpl.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/HystrixCircuitBreakerImpl.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,23 +11,21 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; - namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker { - class HystrixCircuitBreakerImpl : IHystrixCircuitBreaker + internal class HystrixCircuitBreakerImpl : IHystrixCircuitBreaker { - internal readonly IHystrixCommandOptions options; - internal readonly HystrixCommandMetrics metrics; + private readonly IHystrixCommandOptions options; + private readonly HystrixCommandMetrics metrics; /* track whether this circuit is open/closed at any given point in time (default to false==closed) */ - internal AtomicBoolean circuitOpen = new AtomicBoolean(false); + private AtomicBoolean circuitOpen = new AtomicBoolean(false); /* when the circuit was marked open or was last allowed to try a 'singleTest' */ - internal AtomicLong circuitOpenedOrLastTestedTime = new AtomicLong(); + private AtomicLong circuitOpenedOrLastTestedTime = new AtomicLong(); protected internal HystrixCircuitBreakerImpl(IHystrixCommandKey key, IHystrixCommandGroupKey commandGroup, IHystrixCommandOptions options, HystrixCommandMetrics metrics) { @@ -42,9 +39,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker { if (circuitOpen.CompareAndSet(true, false)) { - //win the thread race to reset metrics - //Unsubscribe from the current stream to reset the health counts stream. This only affects the health counts view, - //and all other metric consumers are unaffected by the reset + // win the thread race to reset metrics + // Unsubscribe from the current stream to reset the health counts stream. This only affects the health counts view, + // and all other metric consumers are unaffected by the reset metrics.ResetStream(); } } @@ -59,21 +56,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker // properties have asked us to force the circuit open so we will allow NO requests return false; } + if (options.CircuitBreakerForceClosed) { // we still want to allow isOpen() to perform it's calculations so we simulate normal behavior var isOpen = IsOpen; + // properties have asked us to ignore errors so we will ignore the results of isOpen and just allow all traffic through return true; } + return !IsOpen || AllowSingleTest(); } - } public virtual bool AllowSingleTest() { long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.Value; + // 1) if the circuit is open // 2) and it's been longer than 'sleepWindow' since we opened the circuit if (circuitOpen.Value && Time.CurrentTimeMillis > timeCircuitOpenedOrWasLastTested + options.CircuitBreakerSleepWindowInMilliseconds) @@ -87,8 +87,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker return true; } } - return false; + return false; } public bool IsOpen @@ -134,8 +134,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker } } } - } - } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/NoOpCircuitBreaker.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/NoOpCircuitBreaker.cs similarity index 89% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/NoOpCircuitBreaker.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/NoOpCircuitBreaker.cs index f3eca0a..28cf2ad 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/CircuitBreaker/NoOpCircuitBreaker.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/CircuitBreaker/NoOpCircuitBreaker.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using System; using System.Collections.Generic; @@ -21,9 +19,8 @@ using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker { - class NoOpCircuitBreaker : IHystrixCircuitBreaker + public class NoOpCircuitBreaker : IHystrixCircuitBreaker { - public void MarkSuccess() { } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/CollapsedRequest.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/CollapsedRequest.cs similarity index 98% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/CollapsedRequest.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/CollapsedRequest.cs index fca7537..9952a9d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/CollapsedRequest.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/CollapsedRequest.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using System; using System.Collections.Concurrent; @@ -24,23 +22,21 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser public class CollapsedRequest : ICollapsedRequest { private readonly RequestArgumentType argument; + private readonly CancellationToken token; + private readonly ConcurrentQueue linkedTokens = new ConcurrentQueue(); private RequestResponseType response; private Exception exception; private bool complete; private TaskCompletionSource tcs; - private readonly CancellationToken token; - private readonly ConcurrentQueue linkedTokens = new ConcurrentQueue(); internal CollapsedRequest(RequestArgumentType arg, CancellationToken token) { - argument = arg; this.token = token; tcs = null; response = default(RequestResponseType); exception = null; complete = false; - } internal void AddLinkedToken(CancellationToken token) @@ -59,11 +55,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { return tcs; } + set { tcs = value; } } + internal void SetExceptionIfResponseNotReceived(Exception e) { if (!complete) @@ -77,14 +75,15 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser foreach (var token in linkedTokens) { if (!token.IsCancellationRequested) + { return false; + } } // All linked tokens have been cancelled return Token.IsCancellationRequested; } - internal Exception SetExceptionIfResponseNotReceived(Exception e, string exceptionMessage) { Exception exception = e; @@ -95,8 +94,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { exception = new InvalidOperationException(exceptionMessage); } + SetExceptionIfResponseNotReceived(exception); } + // return any exception that was generated return exception; } @@ -112,6 +113,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser public bool Complete { + internal get + { + return complete; + } + set { complete = value; @@ -120,14 +126,15 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser Response = default(RequestResponseType); } } - internal get - { - return complete; - } } public Exception Exception { + internal get + { + return exception; + } + set { exception = value; @@ -136,16 +143,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { throw new InvalidOperationException("Task has already terminated so exectpion can not be set : " + value); } - - } - internal get - { - return exception; } } public RequestResponseType Response { + internal get + { + return response; + } + set { response = value; @@ -154,11 +161,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { throw new InvalidOperationException("Task has already terminated so response can not be set : " + value); } - - } - internal get - { - return response; } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/CollapsedTask.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/CollapsedTask.cs new file mode 100644 index 0000000..a878b03 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/CollapsedTask.cs @@ -0,0 +1,59 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using Steeltoe.CircuitBreaker.Hystrix.Util; +using System; + +namespace Steeltoe.CircuitBreaker.Hystrix.Collapser +{ + internal class CollapsedTask : ITimerListener + { + private readonly RequestCollapser rq; + + public CollapsedTask(RequestCollapser rq) + { + this.rq = rq; + } + + public void Tick() + { + try + { + // we fetch current so that when multiple threads race + // we can do compareAndSet with the expected/new to ensure only one happens + RequestBatch currentBatch = rq.Batch.Value; + + // 1) it can be null if it got shutdown + // 2) we don't execute this batch if it has no requests and let it wait until next tick to be executed + if (currentBatch != null && currentBatch.Size > 0) + { + // do execution within context of wrapped Callable + rq.CreateNewBatchAndExecutePreviousIfNeeded(currentBatch); + } + } + catch (Exception) + { + // logger.error("Error occurred trying to execute callable inside CollapsedTask from Timer.", e); + } + } + + public int IntervalTimeInMilliseconds + { + get + { + return rq.Properties.TimerDelayInMilliseconds; + } + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/ICollapserTimer.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/ICollapserTimer.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/ICollapserTimer.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/ICollapserTimer.cs index 067f6c7..d0a416d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/ICollapserTimer.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/ICollapserTimer.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,11 +11,9 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; - namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { public interface ICollapserTimer diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RealCollapserTimer.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RealCollapserTimer.cs similarity index 81% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RealCollapserTimer.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RealCollapserTimer.cs index 06ffbc3..adf5f81 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RealCollapserTimer.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RealCollapserTimer.cs @@ -1,6 +1,4 @@ -using System; -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; @@ -21,10 +18,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { public class RealCollapserTimer : ICollapserTimer { - private readonly static HystrixTimer timer = HystrixTimer.GetInstance(); + private static readonly HystrixTimer Timer = HystrixTimer.GetInstance(); + public TimerReference AddListener(ITimerListener collapseTask) { - return timer.AddTimerListener(collapseTask); + return Timer.AddTimerListener(collapseTask); } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestBatch.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestBatch.cs similarity index 83% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestBatch.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestBatch.cs index 53c6322..7ca4cde 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestBatch.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestBatch.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -42,9 +40,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser this.maxBatchSize = maxBatchSize; } - /** - * Return Observable if offer accepted, null if batch is full, already started or completed - */ public CollapsedRequest Offer(RequestArgumentType arg, CancellationToken token) { /* short-cut - if the batch is started we reject the offer */ @@ -72,7 +67,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } else { - CollapsedRequest collapsedRequest = new CollapsedRequest(arg, token); TaskCompletionSource tcs = new TaskCompletionSource(collapsedRequest); collapsedRequest.CompletionSource = tcs; @@ -87,6 +81,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { existing = argumentMap.GetOrAdd(arg, collapsedRequest); } + /** * If the argument already exists in the batch, then there are 2 options: * A) If request caching is ON (the default): only keep 1 argument in the batch and let all responses @@ -115,7 +110,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { return collapsedRequest; } - } } finally @@ -129,69 +123,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } } - internal CollapsedRequest GetOrAddNullArg(CollapsedRequest collapsedRequest) - { - if (nullArg.CompareAndSet(null, collapsedRequest)) - { - return collapsedRequest; - - } - return nullArg.Value; - } - - /** - * Best-effort attempt to remove an argument from a batch. This may get invoked when a cancellation occurs somewhere downstream. - * This method finds the argument in the batch, and removes it. - * - */ - - internal void Remove(RequestArgumentType arg) - { - if (batchStarted.Value) - { - //nothing we can do - return; - } - - if (batchLock.TryEnterReadLock(1)) - { - try - { - /* double-check now that we have the lock - if the batch is started, deleting is useless */ - if (batchStarted.Value) - { - return; - } - CollapsedRequest existing = null; - if (arg == null) - { - nullArg.Value = null; - } - - if (argumentMap.TryRemove(arg, out existing)) - { - // Log - } - } - finally - { - batchLock.ExitReadLock(); - } - } - } - - /** - * Collapsed requests are triggered for batch execution and the array of arguments is passed in. - *

- * IMPORTANT IMPLEMENTATION DETAILS => The expected contract (responsibilities) of this method implementation is: - *

- *

    - *
  • Do NOT block => Do the work on a separate worker thread. Do not perform inline otherwise it will block other requests.
  • - *
  • Set ALL CollapsedRequest response values => Set the response values T on each CollapsedRequest, even if the response is NULL otherwise the user thread waiting on the response will - * think a response was never received and will either block indefinitely or will timeout while waiting.
  • - *
- * - */ public void ExecuteBatchIfNotAlreadyStarted() { /* @@ -212,7 +143,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser if (!entry.Value.IsRequestCanceled()) { args.Add(entry.Value); - } } @@ -230,7 +160,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { // shard batches ICollection>> shards = commandCollapser.DoShardRequests(args); - // for each shard execute its requests + + // for each shard execute its requests foreach (ICollection> shardRequests in shards) { try @@ -245,12 +176,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } catch (Exception mapException) { - //logger.debug("Exception mapping responses to requests.", e); + // logger.debug("Exception mapping responses to requests.", e); foreach (CollapsedRequest request in args) { try { - request.SetExceptionIfResponseNotReceived(mapException); } catch (InvalidOperationException) @@ -258,7 +188,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser // if we have partial responses set in mapResponseToRequests // then we may get InvalidOperationException as we loop over them // so we'll log but continue to the rest - //logger.error("Partial success of 'mapResponseToRequests' resulted in InvalidOperationException while setting Exception. Continuing ... ", e2); + // logger.error("Partial success of 'mapResponseToRequests' resulted in InvalidOperationException while setting Exception. Continuing ... ", e2); } } } @@ -273,14 +203,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } catch (InvalidOperationException) { - //logger.debug("Partial success of 'mapResponseToRequests' resulted in InvalidOperationException while setting 'No response set' Exception. Continuing ... ", e2); + // logger.debug("Partial success of 'mapResponseToRequests' resulted in InvalidOperationException while setting 'No response set' Exception. Continuing ... ", e2); } } - } catch (Exception e) { - //logger.error("Exception while creating and queueing command with batch.", e); + // logger.error("Exception while creating and queueing command with batch.", e); // if a failure occurs we want to pass that exception to all of the Futures that we've returned foreach (CollapsedRequest request in shardRequests) { @@ -290,17 +219,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } catch (InvalidOperationException) { - //logger.debug("Failed trying to setException on CollapsedRequest", e2); + // logger.debug("Failed trying to setException on CollapsedRequest", e2); } } } } } - } catch (Exception e) { - //logger.error("Exception while sharding requests.", e); + // logger.error("Exception while sharding requests.", e); // same error handling as we do around the shards, but this is a wider net in case the shardRequest method fails foreach (ICollapsedRequest request in args) { @@ -310,7 +238,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } catch (InvalidOperationException) { - //logger.debug("Failed trying to setException on CollapsedRequest", e2); + // logger.debug("Failed trying to setException on CollapsedRequest", e2); } } } @@ -333,12 +261,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser // if we win the 'start' and once we have the lock we can now shut it down otherwise another thread will finish executing this batch if (argumentMap.Count > 0) { - //logger.warn("Requests still exist in queue but will not be executed due to RequestCollapser shutdown: " + argumentMap.size(), new InvalidOperationException()); + // logger.warn("Requests still exist in queue but will not be executed due to RequestCollapser shutdown: " + argumentMap.size(), new InvalidOperationException()); /* * In the event that there is a concurrency bug or thread scheduling prevents the timer from ticking we need to handle this so the Future.get() calls do not block. - * + * * I haven't been able to reproduce this use case on-demand but when stressing a machine saw this occur briefly right after the JVM paused (logs stopped scrolling). - * + * * This safety-net just prevents the CollapsedRequestFutureImpl.get() from waiting on the CountDownLatch until its max timeout. */ foreach (CollapsedRequest request in argumentMap.Values) @@ -349,14 +277,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } catch (Exception) { - //logger.debug("Failed to setException on CollapsedRequestFutureImpl instances.", e); + // logger.debug("Failed to setException on CollapsedRequestFutureImpl instances.", e); } - /** - * https://github.com/Netflix/Hystrix/issues/78 Include more info when collapsed requests remain in queue - */ - //logger.warn("Request still in queue but not be executed due to RequestCollapser shutdown. Argument => " + request.getArgument() + " Request Object => " + request, new InvalidOperationException()); - } + // https://github.com/Netflix/Hystrix/issues/78 Include more info when collapsed requests remain in queue + // logger.warn("Request still in queue but not be executed due to RequestCollapser shutdown. Argument => " + request.getArgument() + " Request Object => " + request, new InvalidOperationException()); + } } } finally @@ -375,10 +301,56 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { result++; } + return result; } } + + internal CollapsedRequest GetOrAddNullArg(CollapsedRequest collapsedRequest) + { + if (nullArg.CompareAndSet(null, collapsedRequest)) + { + return collapsedRequest; + } + + return nullArg.Value; + } + + // Best-effort attempt to remove an argument from a batch. This may get invoked when a cancellation occurs somewhere downstream. + // This method finds the argument in the batch, and removes it. + internal void Remove(RequestArgumentType arg) + { + if (batchStarted.Value) + { + // nothing we can do + return; + } + + if (batchLock.TryEnterReadLock(1)) + { + try + { + /* double-check now that we have the lock - if the batch is started, deleting is useless */ + if (batchStarted.Value) + { + return; + } + + if (arg == null) + { + nullArg.Value = null; + } + + if (argumentMap.TryRemove(arg, out CollapsedRequest existing)) + { + // Log + } + } + finally + { + batchLock.ExitReadLock(); + } + } + } } - - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestCollapser.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestCollapser.cs similarity index 63% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestCollapser.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestCollapser.cs index 7da3442..7749246 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestCollapser.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestCollapser.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,41 +11,40 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Threading; - namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { public class RequestCollapser { - //static readonly Logger logger = LoggerFactory.getLogger(RequestCollapser.class); - - //private readonly RequestArgumentType NULL_SENTINEL = default(RequestArgumentType); private readonly HystrixCollapser commandCollapser; + // batch can be null once shutdown - internal readonly AtomicReference> batch = new AtomicReference>(); + private readonly AtomicReference> batch = new AtomicReference>(); private readonly AtomicReference timerListenerReference = new AtomicReference(); private readonly AtomicBoolean timerListenerRegistered = new AtomicBoolean(); private readonly ICollapserTimer timer; - internal readonly IHystrixCollapserOptions properties; - internal readonly HystrixConcurrencyStrategy concurrencyStrategy; + private readonly IHystrixCollapserOptions properties; + private readonly HystrixConcurrencyStrategy concurrencyStrategy; + + public AtomicReference> Batch => batch; + + public IHystrixCollapserOptions Properties => properties; - internal RequestCollapser(HystrixCollapser commandCollapser, IHystrixCollapserOptions properties, ICollapserTimer timer, HystrixConcurrencyStrategy concurrencyStrategy) { - this.commandCollapser = commandCollapser; // the command with implementation of abstract methods we need + // the command with implementation of abstract methods we need + this.commandCollapser = commandCollapser; this.concurrencyStrategy = concurrencyStrategy; this.properties = properties; this.timer = timer; batch.Value = new RequestBatch(properties, commandCollapser, properties.MaxRequestsInBatch); } - public CollapsedRequest SubmitRequest(RequestArgumentType arg, CancellationToken token) { /* @@ -61,7 +59,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser // loop until succeed (compare-and-set spin-loop) while (true) { - RequestBatch b = batch.Value; + RequestBatch b = Batch.Value; if (b == null) { throw new InvalidOperationException("Submitting requests after collapser is shutdown"); @@ -82,21 +80,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } } - internal void CreateNewBatchAndExecutePreviousIfNeeded(RequestBatch previousBatch) - { - if (previousBatch == null) - { - throw new InvalidOperationException("Trying to start null batch which means it was shutdown already."); - } - if (batch.CompareAndSet(previousBatch, new RequestBatch(properties, commandCollapser, properties.MaxRequestsInBatch))) - { - previousBatch.ExecuteBatchIfNotAlreadyStarted(); - } - } - public void Shutdown() { - RequestBatch currentBatch = batch.GetAndSet(null); + RequestBatch currentBatch = Batch.GetAndSet(null); if (currentBatch != null) { currentBatch.Shutdown(); @@ -108,42 +94,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser timerListenerReference.Value.Dispose(); } } - } - class CollapsedTask : ITimerListener - { - private readonly RequestCollapser rq; - public CollapsedTask(RequestCollapser rq) + internal void CreateNewBatchAndExecutePreviousIfNeeded(RequestBatch previousBatch) { - this.rq = rq; - } - - public void Tick() - { - try + if (previousBatch == null) { - // we fetch current so that when multiple threads race - // we can do compareAndSet with the expected/new to ensure only one happens - RequestBatch currentBatch = rq.batch.Value; - // 1) it can be null if it got shutdown - // 2) we don't execute this batch if it has no requests and let it wait until next tick to be executed - if (currentBatch != null && currentBatch.Size > 0) - { - // do execution within context of wrapped Callable - rq.CreateNewBatchAndExecutePreviousIfNeeded(currentBatch); - } - + throw new InvalidOperationException("Trying to start null batch which means it was shutdown already."); } - catch (Exception) + + if (Batch.CompareAndSet(previousBatch, new RequestBatch(Properties, commandCollapser, Properties.MaxRequestsInBatch))) { - //logger.error("Error occurred trying to execute callable inside CollapsedTask from Timer.", e); - //e.printStackTrace(); - } - } - - public int IntervalTimeInMilliseconds { - get { - return rq.properties.TimerDelayInMilliseconds; + previousBatch.ExecuteBatchIfNotAlreadyStarted(); } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestCollapserFactory.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestCollapserFactory.cs similarity index 88% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestCollapserFactory.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestCollapserFactory.cs index 4368520..87fac78 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Collapser/RequestCollapserFactory.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Collapser/RequestCollapserFactory.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Strategy; using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; @@ -20,23 +18,16 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { - // public class RequestCollapserFactory public class RequestCollapserFactory { - - //private static readonly Logger logger = LoggerFactory.getLogger(RequestCollapserFactory.class); - private readonly ICollapserTimer timer; private readonly IHystrixCollapserKey collapserKey; private readonly IHystrixCollapserOptions properties; private readonly HystrixConcurrencyStrategy concurrencyStrategy; private readonly RequestCollapserScope scope; - - public RequestCollapserFactory(IHystrixCollapserKey collapserKey, RequestCollapserScope scope, ICollapserTimer timer, IHystrixCollapserOptions properties) { /* strategy: ConcurrencyStrategy */ @@ -45,7 +36,28 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser this.scope = scope; this.collapserKey = collapserKey; this.properties = properties; + } + public static void Reset() + { + globalScopedCollapsers.Clear(); + requestScopedCollapsers.Clear(); + HystrixTimer.Reset(); + } + + internal static void ResetRequest() + { + requestScopedCollapsers.Clear(); + } + + internal static RequestCollapserRequestVariable GetRequestVariable(string key) + { + if (!requestScopedCollapsers.TryGetValue(key, out object result)) + { + return null; + } + + return (RequestCollapserRequestVariable)result; } public IHystrixCollapserKey CollapserKey @@ -65,17 +77,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser public RequestCollapser GetRequestCollapser(HystrixCollapser commandCollapser) { - if (RequestCollapserScope.REQUEST == this.Scope) + if (this.Scope == RequestCollapserScope.REQUEST) { return GetCollapserForUserRequest(commandCollapser); } - else if (RequestCollapserScope.GLOBAL == this.Scope) + else if (this.Scope == RequestCollapserScope.GLOBAL) { return GetCollapserForGlobalScope(commandCollapser); } else { - //logger.warn("Invalid Scope: {} Defaulting to REQUEST scope.", getScope()); + // logger.warn("Invalid Scope: {} Defaulting to REQUEST scope.", getScope()); return GetCollapserForUserRequest(commandCollapser); } } @@ -89,7 +101,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser return (RequestCollapser)result; } - // String is HystrixCollapserKey.name() (we can't use HystrixCollapserKey directly as we can't guarantee it implements hashcode/equals correctly) private static ConcurrentDictionary requestScopedCollapsers = new ConcurrentDictionary(); @@ -97,37 +108,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser { return GetRequestVariableForCommand(commandCollapser).Value; } - private RequestCollapserRequestVariable GetRequestVariableForCommand(HystrixCollapser commandCollapser) { var result = requestScopedCollapsers.GetOrAddEx(commandCollapser.CollapserKey.Name, (k) => new RequestCollapserRequestVariable(commandCollapser, properties, timer, concurrencyStrategy)); - return (RequestCollapserRequestVariable < BatchReturnType, ResponseType, RequestArgumentType > )result; - } - - - public static void Reset() - { - globalScopedCollapsers.Clear(); - requestScopedCollapsers.Clear(); - HystrixTimer.Reset(); - } - - internal static void ResetRequest() - { - requestScopedCollapsers.Clear(); - } - internal static RequestCollapserRequestVariable GetRequestVariable(String key) - { - object result = null; - if(! requestScopedCollapsers.TryGetValue(key, out result)) - { - return null; - } return (RequestCollapserRequestVariable)result; } - internal class RequestCollapserRequestVariable : HystrixRequestVariableDefault> { public RequestCollapserRequestVariable(HystrixCollapser commandCollapser, IHystrixCollapserOptions properties, ICollapserTimer timer, HystrixConcurrencyStrategy concurrencyStrategy) @@ -137,5 +124,3 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser } } } - - \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/CollapserEventTypeHelper.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/CollapserEventTypeHelper.cs new file mode 100644 index 0000000..57f3d64 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/CollapserEventTypeHelper.cs @@ -0,0 +1,52 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using Steeltoe.CircuitBreaker.Hystrix.Util; +using System; +using System.Collections.Generic; + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public static class CollapserEventTypeHelper + { + private static readonly IList ValueList = new List(); + + public static IList Values + { + get { return ValueList; } + } + + static CollapserEventTypeHelper() + { + ValueList.Add(CollapserEventType.BATCH_EXECUTED); + ValueList.Add(CollapserEventType.ADDED_TO_BATCH); + ValueList.Add(CollapserEventType.RESPONSE_FROM_CACHE); + } + + public static CollapserEventType From(this HystrixRollingNumberEvent @event) + { + switch (@event) + { + case HystrixRollingNumberEvent.COLLAPSER_BATCH: + return CollapserEventType.BATCH_EXECUTED; + case HystrixRollingNumberEvent.COLLAPSER_REQUEST_BATCHED: + return CollapserEventType.ADDED_TO_BATCH; + case HystrixRollingNumberEvent.RESPONSE_FROM_CACHE: + return CollapserEventType.RESPONSE_FROM_CACHE; + default: + throw new ArgumentOutOfRangeException("Not an event that can be converted to HystrixEventType.Collapser : " + @event); + } + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixCollapserConfiguration.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixCollapserConfiguration.cs similarity index 86% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixCollapserConfiguration.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixCollapserConfiguration.cs index 4bdeeb2..90d53bb 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixCollapserConfiguration.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixCollapserConfiguration.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +11,6 @@ // 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. -// - namespace Steeltoe.CircuitBreaker.Hystrix.Config { @@ -25,8 +22,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly bool requestCacheEnabled; private readonly CollapserMetricsConfig collapserMetricsConfig; - public HystrixCollapserConfiguration(IHystrixCollapserKey collapserKey, int maxRequestsInBatch, int timerDelayInMilliseconds, - bool requestCacheEnabled, CollapserMetricsConfig collapserMetricsConfig) + public HystrixCollapserConfiguration( + IHystrixCollapserKey collapserKey, + int maxRequestsInBatch, + int timerDelayInMilliseconds, + bool requestCacheEnabled, + CollapserMetricsConfig collapserMetricsConfig) { this.collapserKey = collapserKey; this.maxRequestsInBatch = maxRequestsInBatch; @@ -42,16 +43,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config collapserProperties.MetricsRollingPercentileWindowInMilliseconds, collapserProperties.MetricsRollingPercentileEnabled, collapserProperties.MetricsRollingStatisticalWindowBuckets, - collapserProperties.MetricsRollingStatisticalWindowInMilliseconds - ); + collapserProperties.MetricsRollingStatisticalWindowInMilliseconds); return new HystrixCollapserConfiguration( collapserKey, collapserProperties.MaxRequestsInBatch, collapserProperties.TimerDelayInMilliseconds, collapserProperties.RequestCacheEnabled, - collapserMetricsConfig - ); + collapserMetricsConfig); } public IHystrixCollapserKey CollapserKey @@ -87,8 +86,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly int rollingCounterNumberOfBuckets; private readonly int rollingCounterBucketSizeInMilliseconds; - public CollapserMetricsConfig(int rollingPercentileNumberOfBuckets, int rollingPercentileBucketSizeInMilliseconds, bool rollingPercentileEnabled, - int rollingCounterNumberOfBuckets, int rollingCounterBucketSizeInMilliseconds) + public CollapserMetricsConfig( + int rollingPercentileNumberOfBuckets, + int rollingPercentileBucketSizeInMilliseconds, + bool rollingPercentileEnabled, + int rollingCounterNumberOfBuckets, + int rollingCounterBucketSizeInMilliseconds) { this.rollingPercentileNumberOfBuckets = rollingCounterNumberOfBuckets; this.rollingPercentileBucketSizeInMilliseconds = rollingPercentileBucketSizeInMilliseconds; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixCommandConfiguration.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixCommandConfiguration.cs similarity index 82% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixCommandConfiguration.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixCommandConfiguration.cs index e29d273..a312e60 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixCommandConfiguration.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixCommandConfiguration.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,16 +11,13 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Config { public class HystrixCommandConfiguration { - private readonly IHystrixCommandKey commandKey; private readonly IHystrixThreadPoolKey threadPoolKey; private readonly IHystrixCommandGroupKey groupKey; @@ -29,10 +25,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly HystrixCommandCircuitBreakerConfig circuitBreakerConfig; private readonly HystrixCommandMetricsConfig metricsConfig; - public HystrixCommandConfiguration(IHystrixCommandKey commandKey, IHystrixThreadPoolKey threadPoolKey, IHystrixCommandGroupKey groupKey, - HystrixCommandExecutionConfig executionConfig, - HystrixCommandCircuitBreakerConfig circuitBreakerConfig, - HystrixCommandMetricsConfig metricsConfig) + public HystrixCommandConfiguration( + IHystrixCommandKey commandKey, + IHystrixThreadPoolKey threadPoolKey, + IHystrixCommandGroupKey groupKey, + HystrixCommandExecutionConfig executionConfig, + HystrixCommandCircuitBreakerConfig circuitBreakerConfig, + HystrixCommandMetricsConfig metricsConfig) { this.commandKey = commandKey; this.threadPoolKey = threadPoolKey; @@ -42,8 +41,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config this.metricsConfig = metricsConfig; } - public static HystrixCommandConfiguration Sample(IHystrixCommandKey commandKey, IHystrixThreadPoolKey threadPoolKey, - IHystrixCommandGroupKey groupKey, IHystrixCommandOptions commandProperties) + public static HystrixCommandConfiguration Sample( + IHystrixCommandKey commandKey, + IHystrixThreadPoolKey threadPoolKey, + IHystrixCommandGroupKey groupKey, + IHystrixCommandOptions commandProperties) { HystrixCommandExecutionConfig executionConfig = new HystrixCommandExecutionConfig( commandProperties.ExecutionIsolationSemaphoreMaxConcurrentRequests, @@ -55,8 +57,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config commandProperties.FallbackEnabled, commandProperties.FallbackIsolationSemaphoreMaxConcurrentRequests, commandProperties.RequestCacheEnabled, - commandProperties.RequestLogEnabled - ); + commandProperties.RequestLogEnabled); HystrixCommandCircuitBreakerConfig circuitBreakerConfig = new HystrixCommandCircuitBreakerConfig( commandProperties.CircuitBreakerEnabled, @@ -64,8 +65,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config commandProperties.CircuitBreakerForceClosed, commandProperties.CircuitBreakerForceOpen, commandProperties.CircuitBreakerRequestVolumeThreshold, - commandProperties.CircuitBreakerSleepWindowInMilliseconds - ); + commandProperties.CircuitBreakerSleepWindowInMilliseconds); HystrixCommandMetricsConfig metricsConfig = new HystrixCommandMetricsConfig( commandProperties.MetricsHealthSnapshotIntervalInMilliseconds, @@ -73,8 +73,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config commandProperties.MetricsRollingPercentileWindowBuckets, commandProperties.MetricsRollingPercentileWindowInMilliseconds, commandProperties.MetricsRollingStatisticalWindowBuckets, - commandProperties.MetricsRollingStatisticalWindowInMilliseconds - ); + commandProperties.MetricsRollingStatisticalWindowInMilliseconds); return new HystrixCommandConfiguration( commandKey, threadPoolKey, groupKey, executionConfig, circuitBreakerConfig, metricsConfig); @@ -114,8 +113,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly int requestVolumeThreshold; private readonly int sleepWindowInMilliseconds; - public HystrixCommandCircuitBreakerConfig(bool enabled, int errorThresholdPercentage, bool forceClosed, - bool forceOpen, int requestVolumeThreshold, int sleepWindowInMilliseconds) + public HystrixCommandCircuitBreakerConfig( + bool enabled, + int errorThresholdPercentage, + bool forceClosed, + bool forceOpen, + int requestVolumeThreshold, + int sleepWindowInMilliseconds) { this.enabled = enabled; this.errorThresholdPercentage = errorThresholdPercentage; @@ -161,7 +165,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly int semaphoreMaxConcurrentRequests; private readonly ExecutionIsolationStrategy isolationStrategy; private readonly bool threadInterruptOnTimeout; - private readonly String threadPoolKeyOverride; + private readonly string threadPoolKeyOverride; private readonly bool timeoutEnabled; private readonly int timeoutInMilliseconds; private readonly bool fallbackEnabled; @@ -169,10 +173,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly bool requestCacheEnabled; private readonly bool requestLogEnabled; - public HystrixCommandExecutionConfig(int semaphoreMaxConcurrentRequests, ExecutionIsolationStrategy isolationStrategy, - bool threadInterruptOnTimeout, String threadPoolKeyOverride, bool timeoutEnabled, - int timeoutInMilliseconds, bool fallbackEnabled, int fallbackMaxConcurrentRequests, - bool requestCacheEnabled, bool requestLogEnabled) + public HystrixCommandExecutionConfig( + int semaphoreMaxConcurrentRequests, + ExecutionIsolationStrategy isolationStrategy, + bool threadInterruptOnTimeout, + string threadPoolKeyOverride, + bool timeoutEnabled, + int timeoutInMilliseconds, + bool fallbackEnabled, + int fallbackMaxConcurrentRequests, + bool requestCacheEnabled, + bool requestLogEnabled) { this.semaphoreMaxConcurrentRequests = semaphoreMaxConcurrentRequests; this.isolationStrategy = isolationStrategy; @@ -184,7 +195,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config this.fallbackMaxConcurrentRequest = fallbackMaxConcurrentRequests; this.requestCacheEnabled = requestCacheEnabled; this.requestLogEnabled = requestLogEnabled; - } public int SemaphoreMaxConcurrentRequests @@ -202,7 +212,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config get { return threadInterruptOnTimeout; } } - public String ThreadPoolKeyOverride + public string ThreadPoolKeyOverride { get { return threadPoolKeyOverride; } } @@ -247,9 +257,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly int rollingCounterNumberOfBuckets; private readonly int rollingCounterBucketSizeInMilliseconds; - public HystrixCommandMetricsConfig(int healthIntervalInMilliseconds, bool rollingPercentileEnabled, int rollingPercentileNumberOfBuckets, - int rollingPercentileBucketSizeInMilliseconds, int rollingCounterNumberOfBuckets, - int rollingCounterBucketSizeInMilliseconds) + public HystrixCommandMetricsConfig( + int healthIntervalInMilliseconds, + bool rollingPercentileEnabled, + int rollingPercentileNumberOfBuckets, + int rollingPercentileBucketSizeInMilliseconds, + int rollingCounterNumberOfBuckets, + int rollingCounterBucketSizeInMilliseconds) { this.healthIntervalInMilliseconds = healthIntervalInMilliseconds; this.rollingPercentileEnabled = rollingPercentileEnabled; @@ -290,5 +304,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config } } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixConfiguration.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixConfiguration.cs similarity index 69% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixConfiguration.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixConfiguration.cs index e04d51d..8557acb 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixConfiguration.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixConfiguration.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,11 +11,9 @@ // 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. -// using System.Collections.Generic; - namespace Steeltoe.CircuitBreaker.Hystrix.Config { public class HystrixConfiguration @@ -25,18 +22,20 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly Dictionary threadPoolConfig; private readonly Dictionary collapserConfig; - public HystrixConfiguration(Dictionary commandConfig, - Dictionary threadPoolConfig, - Dictionary collapserConfig) + public HystrixConfiguration( + Dictionary commandConfig, + Dictionary threadPoolConfig, + Dictionary collapserConfig) { this.commandConfig = commandConfig; this.threadPoolConfig = threadPoolConfig; this.collapserConfig = collapserConfig; } - public static HystrixConfiguration From(Dictionary commandConfig, - Dictionary threadPoolConfig, - Dictionary collapserConfig) + public static HystrixConfiguration From( + Dictionary commandConfig, + Dictionary threadPoolConfig, + Dictionary collapserConfig) { return new HystrixConfiguration(commandConfig, threadPoolConfig, collapserConfig); } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixConfigurationStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixConfigurationStream.cs similarity index 88% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixConfigurationStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixConfigurationStream.cs index 1884a6e..85c1474 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixConfigurationStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixConfigurationStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -20,46 +18,41 @@ using System.Collections.Generic; using System.Reactive.Linq; using System.Reactive.Observable.Aliases; - namespace Steeltoe.CircuitBreaker.Hystrix.Config { public class HystrixConfigurationStream { + private static int dataEmissionIntervalInMs = 5000; private readonly int intervalInMilliseconds; private readonly IObservable allConfigurationStream; private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false); - private static int dataEmissionIntervalInMs = 5000; - //private static readonly DynamicIntProperty dataEmissionIntervalInMs = - // DynamicPropertyFactory.getInstance().getIntProperty("hystrix.stream.config.intervalInMilliseconds", 5000); - - private static Func AllConfig { get; } = (long timestamp) => { return HystrixConfiguration.From( AllCommandConfig(timestamp), AllThreadPoolConfig(timestamp), - AllCollapserConfig(timestamp) - ); + AllCollapserConfig(timestamp)); }; - - public HystrixConfigurationStream(int intervalInMilliseconds) { this.intervalInMilliseconds = intervalInMilliseconds; this.allConfigurationStream = Observable.Interval(TimeSpan.FromMilliseconds(intervalInMilliseconds)) .Map(AllConfig) .OnSubscribe(() => - { isSourceCurrentlySubscribed.Value = true; }) + { + isSourceCurrentlySubscribed.Value = true; + }) .OnDispose(() => - { isSourceCurrentlySubscribed.Value = false; }) + { + isSourceCurrentlySubscribed.Value = false; + }) .Publish().RefCount(); - //.onBackpressureDrop(); } - //The data emission interval is looked up on startup only + // The data emission interval is looked up on startup only private static readonly HystrixConfigurationStream INSTANCE = new HystrixConfigurationStream(dataEmissionIntervalInMs); @@ -68,14 +61,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config return INSTANCE; } - internal static HystrixConfigurationStream GetNonSingletonInstanceOnlyUsedInUnitTests(int delayInMs) - { - return new HystrixConfigurationStream(delayInMs); - } - - /** - * Return a ref-counted stream that will only do work when at least one subscriber is present - */ + // Return a ref-counted stream that will only do work when at least one subscriber is present public IObservable Observe() { return allConfigurationStream; @@ -106,8 +92,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config get { return isSourceCurrentlySubscribed.Value; } } - private static HystrixCommandConfiguration SampleCommandConfiguration(IHystrixCommandKey commandKey, IHystrixThreadPoolKey threadPoolKey, - IHystrixCommandGroupKey groupKey, IHystrixCommandOptions commandProperties) + internal static HystrixConfigurationStream GetNonSingletonInstanceOnlyUsedInUnitTests(int delayInMs) + { + return new HystrixConfigurationStream(delayInMs); + } + + private static HystrixCommandConfiguration SampleCommandConfiguration( + IHystrixCommandKey commandKey, + IHystrixThreadPoolKey threadPoolKey, + IHystrixCommandGroupKey groupKey, + IHystrixCommandOptions commandProperties) { return HystrixCommandConfiguration.Sample(commandKey, threadPoolKey, groupKey, commandProperties); } @@ -133,10 +127,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config IHystrixCommandGroupKey groupKey = commandMetrics.CommandGroup; commandConfigPerKey.Add(commandKey, SampleCommandConfiguration(commandKey, threadPoolKey, groupKey, commandMetrics.Properties)); } + return commandConfigPerKey; }; - private static Func> AllThreadPoolConfig { get; } = (long timestamp) => { @@ -146,10 +140,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config IHystrixThreadPoolKey threadPoolKey = threadPoolMetrics.ThreadPoolKey; threadPoolConfigPerKey.Add(threadPoolKey, SampleThreadPoolConfiguration(threadPoolKey, threadPoolMetrics.Properties)); } + return threadPoolConfigPerKey; }; - private static Func> AllCollapserConfig { get; } = (long timestamp) => { @@ -159,17 +153,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config IHystrixCollapserKey collapserKey = collapserMetrics.CollapserKey; collapserConfigPerKey.Add(collapserKey, SampleCollapserConfiguration(collapserKey, collapserMetrics.Properties)); } + return collapserConfigPerKey; }; - - - private static Func> OnlyCommandConfig { get; } = (HystrixConfiguration hystrixConfiguration) => { return hystrixConfiguration.CommandConfig; - }; private static Func> OnlyThreadPoolConfig { get; } = @@ -182,9 +173,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config (HystrixConfiguration hystrixConfiguration) => { return hystrixConfiguration.CollapserConfig; - }; - } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixThreadPoolConfiguration.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixThreadPoolConfiguration.cs similarity index 89% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixThreadPoolConfiguration.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixThreadPoolConfiguration.cs index 7b19743..998347b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Config/HystrixThreadPoolConfiguration.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Config/HystrixThreadPoolConfiguration.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,16 +11,13 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Config { public class HystrixThreadPoolConfiguration { - private readonly IHystrixThreadPoolKey threadPoolKey; private readonly int coreSize; private readonly int maximumSize; @@ -32,9 +28,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config private readonly int rollingCounterNumberOfBuckets; private readonly int rollingCounterBucketSizeInMilliseconds; - public HystrixThreadPoolConfiguration(IHystrixThreadPoolKey threadPoolKey, int coreSize, int maximumSize, int maxQueueSize, int queueRejectionThreshold, - int keepAliveTimeInMinutes, bool allowMaximumSizeToDivergeFromCoreSize, int rollingCounterNumberOfBuckets, - int rollingCounterBucketSizeInMilliseconds) + public HystrixThreadPoolConfiguration( + IHystrixThreadPoolKey threadPoolKey, + int coreSize, + int maximumSize, + int maxQueueSize, + int queueRejectionThreshold, + int keepAliveTimeInMinutes, + bool allowMaximumSizeToDivergeFromCoreSize, + int rollingCounterNumberOfBuckets, + int rollingCounterBucketSizeInMilliseconds) { this.threadPoolKey = threadPoolKey; this.coreSize = coreSize; @@ -116,5 +119,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config get { return rollingCounterBucketSizeInMilliseconds; } } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/FailureType.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/FailureType.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/FailureType.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/FailureType.cs index de49859..a878d6f 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/FailureType.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/FailureType.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +11,6 @@ // 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. -// - namespace Steeltoe.CircuitBreaker.Hystrix.Exceptions { @@ -21,5 +18,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Exceptions { BAD_REQUEST_EXCEPTION, COMMAND_EXCEPTION, TIMEOUT, SHORTCIRCUIT, REJECTED_THREAD_EXECUTION, REJECTED_SEMAPHORE_EXECUTION, REJECTED_SEMAPHORE_FALLBACK } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixBadRequestException.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixBadRequestException.cs similarity index 81% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixBadRequestException.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixBadRequestException.cs index 97d3d47..41fc148 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixBadRequestException.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixBadRequestException.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,20 +11,20 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Exceptions { public class HystrixBadRequestException : Exception { - public HystrixBadRequestException(string message) : base(message) + public HystrixBadRequestException(string message) + : base(message) { } - public HystrixBadRequestException(string message, Exception cause) : base(message, cause) + public HystrixBadRequestException(string message, Exception cause) + : base(message, cause) { } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixRuntimeException.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixRuntimeException.cs similarity index 90% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixRuntimeException.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixRuntimeException.cs index 54a5443..38cb760 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixRuntimeException.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixRuntimeException.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +11,6 @@ // 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. -// - using System; @@ -25,18 +22,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Exceptions private readonly Exception fallbackException; private readonly FailureType failureCause; - public HystrixRuntimeException(FailureType failureCause, Type commandClass, string message) : - base(message) + public HystrixRuntimeException(FailureType failureCause, Type commandClass, string message) + : base(message) { - this.failureCause = failureCause; this.commandClass = commandClass; this.fallbackException = null; } - public HystrixRuntimeException(FailureType failureCause, Type commandClass, string message, Exception cause, Exception fallbackException) : - base(message, cause) - { + public HystrixRuntimeException(FailureType failureCause, Type commandClass, string message, Exception cause, Exception fallbackException) + : base(message, cause) + { this.failureCause = failureCause; this.commandClass = commandClass; this.fallbackException = fallbackException; @@ -51,6 +47,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Exceptions { get { return fallbackException; } } + public Type ImplementingClass { get { return commandClass; } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixTimeoutException.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixTimeoutException.cs similarity index 81% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixTimeoutException.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixTimeoutException.cs index e6826ce..23d7979 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/HystrixTimeoutException.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/HystrixTimeoutException.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,19 +11,20 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Exceptions { public class HystrixTimeoutException : Exception { - public HystrixTimeoutException(string message) : base(message) + public HystrixTimeoutException(string message) + : base(message) { } - public HystrixTimeoutException(string message, Exception inner) : base(message, inner) + + public HystrixTimeoutException(string message, Exception inner) + : base(message, inner) { } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/RejectedExecutionException.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/RejectedExecutionException.cs similarity index 83% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/RejectedExecutionException.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/RejectedExecutionException.cs index 3e8d761..28dd386 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Exceptions/RejectedExecutionException.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Exceptions/RejectedExecutionException.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,16 +11,15 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Exceptions { public class RejectedExecutionException : Exception { - public RejectedExecutionException(string message) : base(message) + public RejectedExecutionException(string message) + : base(message) { } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ExecutionResult.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/ExecutionResult.cs similarity index 69% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/ExecutionResult.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/ExecutionResult.cs index baabf97..9bd8bcf 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ExecutionResult.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/ExecutionResult.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,29 +18,32 @@ using System.Collections.Generic; namespace Steeltoe.CircuitBreaker.Hystrix { - public class ExecutionResult { - private readonly EventCounts eventCounts; - private readonly Exception failedExecutionException; - private readonly Exception executionException; - private readonly long startTimestamp; - private readonly int executionLatency; //time spent in run() method - private readonly int userThreadLatency; //time elapsed between caller thread submitting request and response being visible to it - private readonly bool executionOccurred; - private readonly bool isExecutedInThread; - private readonly IHystrixCollapserKey collapserKey; private static readonly IList ALL_EVENT_TYPES = HystrixEventTypeHelper.Values; private static readonly int NUM_EVENT_TYPES = ALL_EVENT_TYPES.Count; private static readonly BitArray EXCEPTION_PRODUCING_EVENTS = new BitArray(NUM_EVENT_TYPES); private static readonly BitArray TERMINAL_EVENTS = new BitArray(NUM_EVENT_TYPES); - static ExecutionResult() { - foreach (HystrixEventType eventType in HystrixEventTypeHelper.EXCEPTION_PRODUCING_EVENT_TYPES) { + private readonly EventCounts eventCounts; + private readonly Exception failedExecutionException; + private readonly Exception executionException; + private readonly long startTimestamp; + private readonly int executionLatency; // time spent in run() method + private readonly int userThreadLatency; // time elapsed between caller thread submitting request and response being visible to it + private readonly bool executionOccurred; + private readonly bool isExecutedInThread; + private readonly IHystrixCollapserKey collapserKey; + + static ExecutionResult() + { + foreach (HystrixEventType eventType in HystrixEventTypeHelper.EXCEPTION_PRODUCING_EVENT_TYPES) + { EXCEPTION_PRODUCING_EVENTS.Set((int)eventType, true); } - foreach (HystrixEventType eventType in HystrixEventTypeHelper.TERMINAL_EVENT_TYPES) { + foreach (HystrixEventType eventType in HystrixEventTypeHelper.TERMINAL_EVENT_TYPES) + { TERMINAL_EVENTS.Set((int)eventType, true); } } @@ -96,12 +98,107 @@ namespace Steeltoe.CircuitBreaker.Hystrix break; } } + this.events = newBitSet; this.numEmissions = localNumEmits; this.numFallbackEmissions = localNumFallbackEmits; this.numCollapsed = localNumCollapsed; } + public bool Contains(HystrixEventType eventType) + { + return events.Get((int)eventType); + } + + public bool ContainsAnyOf(BitArray other) + { + if (other == null) + { + return false; + } + + for (int i = 0; i < other.Length; i++) + { + if (i >= events.Length) + { + return false; + } + + if (other[i]) + { + if (events[i]) + { + return true; + } + } + } + + return false; + } + + public int GetCount(HystrixEventType eventType) + { + switch (eventType) + { + case HystrixEventType.EMIT: return numEmissions; + case HystrixEventType.FALLBACK_EMIT: return numFallbackEmissions; + case HystrixEventType.EXCEPTION_THROWN: return ContainsAnyOf(EXCEPTION_PRODUCING_EVENTS) ? 1 : 0; + case HystrixEventType.COLLAPSED: return numCollapsed; + default: return Contains(eventType) ? 1 : 0; + } + } + + public override bool Equals(object o) + { + if (this == o) + { + return true; + } + + if (o == null || this.GetType() != o.GetType()) + { + return false; + } + + EventCounts that = (EventCounts)o; + + if (numEmissions != that.numEmissions) + { + return false; + } + + if (numFallbackEmissions != that.numFallbackEmissions) + { + return false; + } + + if (numCollapsed != that.numCollapsed) + { + return false; + } + + return Equals(that.events); + } + + public override int GetHashCode() + { + int result = GetHashCode(events); + result = (31 * result) + numEmissions; + result = (31 * result) + numFallbackEmissions; + result = (31 * result) + numCollapsed; + return result; + } + + public override string ToString() + { + return "EventCounts{" + + "events=" + events + + ", numEmissions=" + numEmissions + + ", numFallbackEmissions=" + numFallbackEmissions + + ", numCollapsed=" + numCollapsed + + '}'; + } + internal EventCounts Plus(HystrixEventType eventType) { return Plus(eventType, 1); @@ -131,109 +228,53 @@ namespace Steeltoe.CircuitBreaker.Hystrix newBitSet.Set((int)eventType, true); break; } + return new EventCounts(newBitSet, localNumEmits, localNumFallbackEmits, localNumCollapsed); } - public bool Contains(HystrixEventType eventType) - { - return events.Get((int)eventType); - } - - public bool ContainsAnyOf(BitArray other) - { - if (other == null) - return false; - for(int i = 0; i < other.Length; i++ ) - { - if (i >= events.Length) - { - return false; - } - if (other[i]) - { - if (events[i]) return true; - } - } - return false; - } - - public int GetCount(HystrixEventType eventType) - { - switch (eventType) - { - case HystrixEventType.EMIT: return numEmissions; - case HystrixEventType.FALLBACK_EMIT: return numFallbackEmissions; - case HystrixEventType.EXCEPTION_THROWN: return ContainsAnyOf(EXCEPTION_PRODUCING_EVENTS) ? 1 : 0; - case HystrixEventType.COLLAPSED: return numCollapsed; - default: return Contains(eventType) ? 1 : 0; - } - } - - - public override bool Equals(Object o) - { - if (this == o) return true; - if (o == null || this.GetType() != o.GetType()) return false; - - EventCounts that = (EventCounts)o; - - if (numEmissions != that.numEmissions) return false; - if (numFallbackEmissions != that.numFallbackEmissions) return false; - if (numCollapsed != that.numCollapsed) return false; - return Equals(that.events); - - } - - public override int GetHashCode() - - { - int result = GetHashCode(events); - result = 31 * result + numEmissions; - result = 31 * result + numFallbackEmissions; - result = 31 * result + numCollapsed; - return result; - } - private bool Equals(BitArray other) { if (other.Length != events.Length) { return false; } - for(int i = 0; i < events.Length; i++) + + for (int i = 0; i < events.Length; i++) { if (events[i] != other[i]) + { return false; + } } + return true; } + private int GetHashCode(BitArray bits) { long h = 1234; int[] copy = new int[bits.Length]; ICollection asCollection = bits; asCollection.CopyTo(copy, 0); - for(int i = copy.Length; --i >= 0;) + for (int i = copy.Length; --i >= 0;) { h ^= copy[i] * (i + 1); } - return (int)((h >> 32) ^ h); - } - public override String ToString() - { - return "EventCounts{" + - "events=" + events + - ", numEmissions=" + numEmissions + - ", numFallbackEmissions=" + numFallbackEmissions + - ", numCollapsed=" + numCollapsed + - '}'; + return (int)((h >> 32) ^ h); } } - private ExecutionResult(EventCounts eventCounts, long startTimestamp, int executionLatency, - int userThreadLatency, Exception failedExecutionException, Exception executionException, - bool executionOccurred, bool isExecutedInThread, IHystrixCollapserKey collapserKey) + private ExecutionResult( + EventCounts eventCounts, + long startTimestamp, + int executionLatency, + int userThreadLatency, + Exception failedExecutionException, + Exception executionException, + bool executionOccurred, + bool isExecutedInThread, + IHystrixCollapserKey collapserKey) { this.eventCounts = eventCounts; this.startTimestamp = startTimestamp; @@ -259,68 +300,120 @@ namespace Steeltoe.CircuitBreaker.Hystrix didExecutionOccur = true; } } - return new ExecutionResult(new EventCounts(eventTypes), -1L, -1, -1, null, null, didExecutionOccur, false, null); - } - private static bool DidExecutionOccur(HystrixEventType eventType) - { - switch (eventType) - { - case HystrixEventType.SUCCESS: return true; - case HystrixEventType.FAILURE: return true; - case HystrixEventType.BAD_REQUEST: return true; - case HystrixEventType.TIMEOUT: return true; - case HystrixEventType.CANCELLED: return true; - default: return false; - } + return new ExecutionResult(new EventCounts(eventTypes), -1L, -1, -1, null, null, didExecutionOccur, false, null); } public ExecutionResult SetExecutionOccurred() { - return new ExecutionResult(eventCounts, startTimestamp, executionLatency, userThreadLatency, - failedExecutionException, executionException, true, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts, + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + true, + isExecutedInThread, + collapserKey); } public ExecutionResult SetExecutionLatency(int executionLatency) { - return new ExecutionResult(eventCounts, startTimestamp, executionLatency, userThreadLatency, - failedExecutionException, executionException, executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts, + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } public ExecutionResult SetException(Exception e) { - return new ExecutionResult(eventCounts, startTimestamp, executionLatency, userThreadLatency, e, - executionException, executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts, + startTimestamp, + executionLatency, + userThreadLatency, + e, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } public ExecutionResult SetExecutionException(Exception executionException) { - return new ExecutionResult(eventCounts, startTimestamp, executionLatency, userThreadLatency, - failedExecutionException, executionException, executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts, + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } public ExecutionResult SetInvocationStartTime(long inStartTimestamp) { - return new ExecutionResult(eventCounts, inStartTimestamp, executionLatency, userThreadLatency, - failedExecutionException, executionException, executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts, + inStartTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } public ExecutionResult SetExecutedInThread() { - return new ExecutionResult(eventCounts, startTimestamp, executionLatency, userThreadLatency, - failedExecutionException, executionException, executionOccurred, true, collapserKey); + return new ExecutionResult( + eventCounts, + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + true, + collapserKey); } public ExecutionResult SetNotExecutedInThread() { - return new ExecutionResult(eventCounts, startTimestamp, executionLatency, userThreadLatency, - failedExecutionException, executionException, executionOccurred, false, collapserKey); + return new ExecutionResult( + eventCounts, + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + false, + collapserKey); } public ExecutionResult MarkCollapsed(IHystrixCollapserKey collapserKey, int sizeOfBatch) { - return new ExecutionResult(eventCounts.Plus(HystrixEventType.COLLAPSED, sizeOfBatch), startTimestamp, executionLatency, userThreadLatency, - failedExecutionException, executionException, executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts.Plus(HystrixEventType.COLLAPSED, sizeOfBatch), + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } public ExecutionResult MarkUserThreadCompletion(long userThreadLatency) @@ -328,8 +421,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix if (startTimestamp > 0 && !IsResponseRejected) { /* execution time (must occur before terminal state otherwise a race condition can occur if requested by client) */ - return new ExecutionResult(eventCounts, startTimestamp, executionLatency, (int)userThreadLatency, - failedExecutionException, executionException, executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts, + startTimestamp, + executionLatency, + (int)userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } else { @@ -337,26 +438,34 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } - /** - * Creates a new ExecutionResult by adding the defined 'event' to the ones on the current instance. - * - * @param eventType event to add - * @return new {@link ExecutionResult} with event added - */ public ExecutionResult AddEvent(HystrixEventType eventType) { - return new ExecutionResult(eventCounts.Plus(eventType), startTimestamp, executionLatency, - userThreadLatency, failedExecutionException, executionException, - executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts.Plus(eventType), + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } public ExecutionResult AddEvent(int executionLatency, HystrixEventType eventType) { if (startTimestamp >= 0 && !IsResponseRejected) { - return new ExecutionResult(eventCounts.Plus(eventType), startTimestamp, executionLatency, - userThreadLatency, failedExecutionException, executionException, - executionOccurred, isExecutedInThread, collapserKey); + return new ExecutionResult( + eventCounts.Plus(eventType), + startTimestamp, + executionLatency, + userThreadLatency, + failedExecutionException, + executionException, + executionOccurred, + isExecutedInThread, + collapserKey); } else { @@ -421,7 +530,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix public List OrderedList { - get { + get + { List eventList = new List(); foreach (HystrixEventType eventType in ALL_EVENT_TYPES) { @@ -430,6 +540,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix eventList.Add(eventType); } } + return eventList; } } @@ -449,7 +560,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return eventCounts.ContainsAnyOf(TERMINAL_EVENTS); } } - public override String ToString() + public override string ToString() { return "ExecutionResult{" + "eventCounts=" + eventCounts + @@ -463,5 +574,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix ", collapserKey=" + collapserKey + '}'; } + + private static bool DidExecutionOccur(HystrixEventType eventType) + { + switch (eventType) + { + case HystrixEventType.SUCCESS: return true; + case HystrixEventType.FAILURE: return true; + case HystrixEventType.BAD_REQUEST: return true; + case HystrixEventType.TIMEOUT: return true; + case HystrixEventType.CANCELLED: return true; + default: return false; + } + } } } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/HealthCounts.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HealthCounts.cs new file mode 100644 index 0000000..ccd545c --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HealthCounts.cs @@ -0,0 +1,80 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public class HealthCounts + { + private readonly long totalCount; + private readonly long errorCount; + private readonly int errorPercentage; + + internal HealthCounts(long total, long error) + { + this.totalCount = total; + this.errorCount = error; + if (totalCount > 0) + { + this.errorPercentage = (int)((errorCount * 100) / totalCount); + } + else + { + this.errorPercentage = 0; + } + } + + private static readonly HealthCounts EMPTY = new HealthCounts(0, 0); + + public long TotalRequests + { + get { return totalCount; } + } + + public long ErrorCount + { + get { return errorCount; } + } + + public int ErrorPercentage + { + get { return errorPercentage; } + } + + public HealthCounts Plus(long[] eventTypeCounts) + { + long updatedTotalCount = totalCount; + long updatedErrorCount = errorCount; + + long successCount = eventTypeCounts[(int)HystrixEventType.SUCCESS]; + long failureCount = eventTypeCounts[(int)HystrixEventType.FAILURE]; + long timeoutCount = eventTypeCounts[(int)HystrixEventType.TIMEOUT]; + long threadPoolRejectedCount = eventTypeCounts[(int)HystrixEventType.THREAD_POOL_REJECTED]; + long semaphoreRejectedCount = eventTypeCounts[(int)HystrixEventType.SEMAPHORE_REJECTED]; + + updatedTotalCount += successCount + failureCount + timeoutCount + threadPoolRejectedCount + semaphoreRejectedCount; + updatedErrorCount += failureCount + timeoutCount + threadPoolRejectedCount + semaphoreRejectedCount; + return new HealthCounts(updatedTotalCount, updatedErrorCount); + } + + public static HealthCounts Empty + { + get { return EMPTY; } + } + + public override string ToString() + { + return "HealthCounts[" + errorCount + " / " + totalCount + " : " + ErrorPercentage + "%]"; + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixBaseOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixBaseOptions.cs new file mode 100644 index 0000000..71bf5b9 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixBaseOptions.cs @@ -0,0 +1,64 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options; + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public abstract class HystrixBaseOptions + { + protected internal IHystrixDynamicOptions _dynamic; + + protected HystrixBaseOptions(IHystrixDynamicOptions dynamicOptions) + { + this._dynamic = dynamicOptions; + } + + protected virtual bool GetBoolean(string prefix, string key, string property, bool globalDefault, bool? instanceDefaultFromCode) + { + bool result = globalDefault; + result = (_dynamic != null) ? _dynamic.GetBoolean(prefix + ":default:" + property, result) : result; // dynamic global default + result = instanceDefaultFromCode ?? result; // instance default from code + result = (_dynamic != null) ? _dynamic.GetBoolean(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value + return result; + } + + protected virtual int GetInteger(string prefix, string key, string property, int globalDefault, int? instanceDefaultFromCode) + { + int result = globalDefault; + result = (_dynamic != null) ? _dynamic.GetInteger(prefix + ":default:" + property, result) : result; // dynamic global default + result = instanceDefaultFromCode ?? result; // instance default from code + result = (_dynamic != null) ? _dynamic.GetInteger(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value + return result; + } + + protected virtual long GetLong(string prefix, string key, string property, long globalDefault, long? instanceDefaultFromCode) + { + long result = globalDefault; + result = (_dynamic != null) ? _dynamic.GetLong(prefix + ":default:" + property, result) : result; // dynamic global default + result = instanceDefaultFromCode ?? result; // instance default from code + result = (_dynamic != null) ? _dynamic.GetLong(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value + return result; + } + + protected virtual string GetString(string prefix, string key, string property, string globalDefault, string instanceDefaultFromCode) + { + string result = globalDefault; + result = (_dynamic != null) ? _dynamic.GetString(prefix + ":default:" + property, result) : result; // dynamic global default + result = instanceDefaultFromCode ?? result; // instance default from code + result = (_dynamic != null) ? _dynamic.GetString(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value + return result; + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCachedTask.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCachedTask.cs similarity index 64% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCachedTask.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCachedTask.cs index 22ee84f..b40d112 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCachedTask.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCachedTask.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,24 +20,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix { public HystrixCachedTask() { - } public Task CachedTask { get; set; } - - //public override bool Equals(object obj) - //{ - // HystrixCachedTask ct = obj as HystrixCachedTask; - // if (ct == null) - // return false; - // if (ct.CachedTask == null) - // { - // return this.CachedTask == null; - // } - // return ct.CachedTask.Equals(this.CachedTask); - //} } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapser.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapser.cs similarity index 84% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapser.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapser.cs index 2516808..f9ce5ff 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapser.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapser.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,29 +29,27 @@ namespace Steeltoe.CircuitBreaker.Hystrix public enum RequestCollapserScope { REQUEST, - GLOBAL + GLOBAL } public abstract class HystrixCollapser : IHystrixExecutable, IHystrixObservable { - //static readonly Logger logger = LoggerFactory.getLogger(HystrixCollapser.class); + protected internal CancellationToken _token; private readonly RequestCollapserFactory collapserFactory; private readonly HystrixRequestCache requestCache; private readonly HystrixCollapserMetrics metrics; - internal protected CancellationToken token; - protected HystrixCollapser() : this(null, RequestCollapserScope.REQUEST) - { + { } - protected HystrixCollapser(IHystrixCollapserKey collapserKey) - : this(collapserKey, RequestCollapserScope.REQUEST) - { + : this(collapserKey, RequestCollapserScope.REQUEST) + { } + protected HystrixCollapser(IHystrixCollapserKey collapserKey, RequestCollapserScope scope) : this(new HystrixCollapserOptions(collapserKey, scope)) { @@ -60,21 +57,22 @@ namespace Steeltoe.CircuitBreaker.Hystrix protected HystrixCollapser(IHystrixCollapserOptions options) : this(options.CollapserKey, options.Scope, new RealCollapserTimer(), options, null) - { + { } protected HystrixCollapser(IHystrixCollapserKey collapserKey, RequestCollapserScope scope, ICollapserTimer timer, IHystrixCollapserOptions options) : this(collapserKey, scope, timer, options, null) - { + { } protected HystrixCollapser(IHystrixCollapserKey collapserKey, RequestCollapserScope scope, ICollapserTimer timer, IHystrixCollapserOptions optionsDefault, HystrixCollapserMetrics metrics) { - if (collapserKey == null || collapserKey.Name.Trim().Equals("")) + if (collapserKey == null || collapserKey.Name.Trim().Equals(string.Empty)) { string defaultKeyName = GetDefaultNameFromClass(GetType()); collapserKey = HystrixCollapserKeyDefault.AsKey(defaultKeyName); } + IHystrixCollapserOptions options = HystrixOptionsFactory.GetCollapserOptions(collapserKey, optionsDefault); this.collapserFactory = new RequestCollapserFactory(collapserKey, scope, timer, options); this.requestCache = HystrixRequestCache.GetInstance(collapserKey); @@ -89,15 +87,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } HystrixMetricsPublisherFactory.CreateOrRetrievePublisherForCollapser(collapserKey, this.metrics, options); - } - private IHystrixCollapserOptions Properties - { - get { return collapserFactory.Properties; } - } - - public virtual IHystrixCollapserKey CollapserKey { get { return collapserFactory.CollapserKey; } @@ -115,16 +106,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix public abstract RequestArgumentType RequestArgument { get; } - protected abstract HystrixCommand CreateCommand(ICollection> requests); - - protected abstract void MapResponseToRequests(BatchReturnType batchResponse, ICollection> requests); - - protected virtual ICollection>> ShardRequests(ICollection> requests) + private IHystrixCollapserOptions Properties { - return new List>>() { requests }; + get { return collapserFactory.Properties; } } - public RequestResponseType Execute() { try @@ -133,7 +119,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix var result = task.Result; return result; } - catch (Exception e) { throw DecomposeException(e); @@ -147,67 +132,57 @@ namespace Steeltoe.CircuitBreaker.Hystrix public Task ExecuteAsync(CancellationToken token) { - this.token = token; + this._token = token; Task toStart = ToTask(); return toStart; } + public Task ToTask() { - RequestCollapser requestCollapser = collapserFactory.GetRequestCollapser(this); CollapsedRequest request = null; HystrixCachedTask entry = null; - - if (AddCacheEntryIfAbsent(CacheKey, out entry)) // Returns true if entry already present + + if (AddCacheEntryIfAbsent(CacheKey, out entry)) { metrics.MarkResponseFromCache(); - var origTask = entry.CachedTask; + var origTask = entry.CachedTask; request = entry.CachedTask.AsyncState as CollapsedRequest; - request.AddLinkedToken(token); - var continued = origTask.ContinueWith((parent) => - { - CollapsedRequest req = parent.AsyncState as CollapsedRequest; - if (req != null) + request.AddLinkedToken(_token); + var continued = origTask.ContinueWith( + (parent) => { - if (req.Exception != null) + CollapsedRequest req = + parent.AsyncState as CollapsedRequest; + if (req != null) { - throw req.Exception; + if (req.Exception != null) + { + throw req.Exception; + } + return req.Response; } - return req.Response; - } else - { - throw new InvalidOperationException("Missing AsyncState from parent task"); - } - - },token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current); + else + { + throw new InvalidOperationException("Missing AsyncState from parent task"); + } + }, + _token, + TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Current); return continued; } try { - request = requestCollapser.SubmitRequest(RequestArgument, token); + request = requestCollapser.SubmitRequest(RequestArgument, _token); entry.CachedTask = request.CompletionSource.Task; return entry.CachedTask; - } catch (Exception ex) + } + catch (Exception ex) { return Task.FromException(ex); } - - } - protected bool AddCacheEntryIfAbsent(string cacheKey, out HystrixCachedTask entry) - { - entry = null; - var newEntry = new HystrixCachedTask (); - if (Properties.RequestCacheEnabled && cacheKey != null) - { - entry = requestCache.PutIfAbsent>(cacheKey, newEntry); - if (entry != null) - { - return true; - } - } - entry = newEntry; - return false; } public IObservable Observe() @@ -220,36 +195,48 @@ namespace Steeltoe.CircuitBreaker.Hystrix public IObservable Observe(CancellationToken token) { - ReplaySubject subject = new ReplaySubject(); IObservable observable = ToObservable(); observable.Subscribe(subject, token); return observable; } - //public IObservable Observe() - //{ - // return ExecuteAsync().ToObservable(); - //} - - public IObservable ToObservable() { - IObservable observable = Observable.FromAsync((ct) => { - this.token = ct; + this._token = ct; Task toStart = ToTask(); return toStart; }); return observable; - } - //public IObservable ToObservable() - //{ - // Task task = ToTask(); - // return task.ToObservable(); - //} + + protected abstract HystrixCommand CreateCommand(ICollection> requests); + + protected abstract void MapResponseToRequests(BatchReturnType batchResponse, ICollection> requests); + + protected virtual ICollection>> ShardRequests(ICollection> requests) + { + return new List>>() { requests }; + } + + protected bool AddCacheEntryIfAbsent(string cacheKey, out HystrixCachedTask entry) + { + entry = null; + var newEntry = new HystrixCachedTask(); + if (Properties.RequestCacheEnabled && cacheKey != null) + { + entry = requestCache.PutIfAbsent>(cacheKey, newEntry); + if (entry != null) + { + return true; + } + } + + entry = newEntry; + return false; + } protected virtual string CacheKey { @@ -263,8 +250,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix private static string GetDefaultNameFromClass(Type cls) { - string fromCache = null; - if (defaultNameCache.TryGetValue(cls, out fromCache)) + if (defaultNameCache.TryGetValue(cls, out string fromCache)) { return fromCache; } @@ -274,9 +260,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix return name; } - - - // this is a micro-optimization but saves about 1-2microseconds (on 2011 MacBook Pro) + // this is a micro-optimization but saves about 1-2microseconds (on 2011 MacBook Pro) // on the repetitive string processing that will occur on the same classes over and over again private static ConcurrentDictionary defaultNameCache = new ConcurrentDictionary(); @@ -309,18 +293,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix { return (HystrixRuntimeException)e; } + // if we have an exception we know about we'll throw it directly without the wrapper exception if (e.InnerException is HystrixRuntimeException) { return (HystrixRuntimeException)e.InnerException; } - String message = GetType() + " HystrixCollapser failed while executing."; - //logger.debug(message, e); // debug only since we're throwing the exception and someone higher will do something with it - + + string message = GetType() + " HystrixCollapser failed while executing."; + + // logger.debug(message, e); // debug only since we're throwing the exception and someone higher will do something with it return new HystrixRuntimeException(FailureType.COMMAND_EXCEPTION, this.GetType(), message, e, null); - } - } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapserMetrics.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapserMetrics.cs similarity index 84% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapserMetrics.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapserMetrics.cs index 241a441..547943f 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCollapserMetrics.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapserMetrics.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,57 +23,51 @@ namespace Steeltoe.CircuitBreaker.Hystrix { public class HystrixCollapserMetrics : HystrixMetrics { - //private static final Logger logger = LoggerFactory.getLogger(HystrixCollapserMetrics.class); - - private static readonly ConcurrentDictionary metrics = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Metrics = new ConcurrentDictionary(); public static HystrixCollapserMetrics GetInstance(IHystrixCollapserKey key, IHystrixCollapserOptions properties) { - return metrics.GetOrAddEx(key.Name, (k) => new HystrixCollapserMetrics(key, properties)); + return Metrics.GetOrAddEx(key.Name, (k) => new HystrixCollapserMetrics(key, properties)); } - public static ICollection GetInstances() { List collapserMetrics = new List(); - foreach (HystrixCollapserMetrics tpm in metrics.Values) + foreach (HystrixCollapserMetrics tpm in Metrics.Values) { - collapserMetrics.Add(tpm); - } + return collapserMetrics.AsReadOnly(); } private static readonly IList ALL_EVENT_TYPES = CollapserEventTypeHelper.Values; public static Func AppendEventToBucket { get; } = (initialCountArray, collapserEvent) => - { - - { - CollapserEventType eventType = collapserEvent.EventType; - int count = collapserEvent.Count; - initialCountArray[(int)eventType] += count; - return initialCountArray; - } + { + { + CollapserEventType eventType = collapserEvent.EventType; + int count = collapserEvent.Count; + initialCountArray[(int)eventType] += count; + return initialCountArray; + } }; public static Func BucketAggregator { get; } = (cumulativeEvents, bucketEventCounts) => { - { foreach (CollapserEventType eventType in ALL_EVENT_TYPES) { cumulativeEvents[(int)eventType] += bucketEventCounts[(int)eventType]; } + return cumulativeEvents; } }; - internal static void Reset() { - metrics.Clear(); + Metrics.Clear(); } private readonly IHystrixCollapserKey collapserKey; @@ -84,7 +77,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix private readonly CumulativeCollapserEventCounterStream cumulativeCollapserEventCounterStream; private readonly RollingCollapserBatchSizeDistributionStream rollingCollapserBatchSizeDistributionStream; - HystrixCollapserMetrics(IHystrixCollapserKey key, IHystrixCollapserOptions properties) : base(null) + internal HystrixCollapserMetrics(IHystrixCollapserKey key, IHystrixCollapserOptions properties) + : base(null) { this.collapserKey = key; this.properties = properties; @@ -94,7 +88,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix rollingCollapserBatchSizeDistributionStream = RollingCollapserBatchSizeDistributionStream.GetInstance(key, properties); } - public IHystrixCollapserKey CollapserKey { get { return collapserKey; } @@ -115,19 +108,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix return cumulativeCollapserEventCounterStream.GetLatest(collapserEventType); } - public override long GetCumulativeCount(HystrixRollingNumberEvent @event) { return GetCumulativeCount(CollapserEventTypeHelper.From(@event)); } - public override long GetRollingCount(HystrixRollingNumberEvent @event) { return GetRollingCount(CollapserEventTypeHelper.From(@event)); } - public int GetBatchSizePercentile(double percentile) { return rollingCollapserBatchSizeDistributionStream.GetLatestPercentile(percentile); @@ -138,17 +128,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return rollingCollapserBatchSizeDistributionStream.LatestMean; } } - public int GetShardSizePercentile(double percentile) { return 0; - //return rollingCollapserUsageDistributionStream.getLatestBatchSizePercentile(percentile); } public int ShardSizeMean { get { return 0; } - //return percentileShardSize.getMean(); } public void MarkRequestBatched() @@ -170,4 +157,3 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } } - diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapserOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapserOptions.cs new file mode 100644 index 0000000..e588950 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCollapserOptions.cs @@ -0,0 +1,79 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options; + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public class HystrixCollapserOptions : HystrixBaseOptions, IHystrixCollapserOptions + { + internal const int DEFAULT_MAX_REQUESTS_IN_BATCH = int.MaxValue; + internal const int DEFAULT_TIMER_DELAY_IN_MILLISECONDS = 10; + internal const bool DEFAULT_REQUEST_CACHE_ENABLED = true; + internal const int DEFAULT_METRICS_ROLLING_STATISTICAL_WINDOW = 10000; // default => statisticalWindow: 10000 = 10 seconds (and default of 10 buckets so each bucket is 1 second) + internal const int DEFAULT_METRICS_ROLLING_STATISTICAL_WINDOW_BUCKETS = 10; // default => statisticalWindowBuckets: 10 = 10 buckets in a 10 second window so each bucket is 1 second + internal const bool DEFAULT_METRICS_ROLLING_PERCENTILE_ENABLED = true; + internal const int DEFAULT_METRICS_ROLLING_PERCENTILE_WINDOW = 60000; // default to 1 minute for RollingPercentile + internal const int DEFAULT_METRICS_ROLLING_PERCENTILE_WINDOW_BUCKETS = 6; // default to 6 buckets (10 seconds each in 60 second window) + internal const int DEFAULT_METRICS_ROLLING_PERCENTILE_BUCKET_SIZE = 100; // default to 100 values max per bucket + + protected const string HYSTRIX_COLLAPSER_PREFIX = "hystrix:collapser"; + private IHystrixCollapserOptions defaults; + + public HystrixCollapserOptions(IHystrixCollapserKey collapserKey, IHystrixCollapserOptions defaults = null, IHystrixDynamicOptions dynamic = null) + : this(collapserKey, RequestCollapserScope.REQUEST, defaults, dynamic) + { + } + + public HystrixCollapserOptions(IHystrixCollapserKey key, RequestCollapserScope scope, IHystrixCollapserOptions defaults = null, IHystrixDynamicOptions dynamic = null) + : base(dynamic) + { + this.CollapserKey = key; + this.Scope = scope; + this.defaults = defaults; + + MaxRequestsInBatch = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "maxRequestsInBatch", DEFAULT_MAX_REQUESTS_IN_BATCH, defaults?.MaxRequestsInBatch); + TimerDelayInMilliseconds = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "timerDelayInMilliseconds", DEFAULT_TIMER_DELAY_IN_MILLISECONDS, defaults?.TimerDelayInMilliseconds); + RequestCacheEnabled = GetBoolean(HYSTRIX_COLLAPSER_PREFIX, key.Name, "requestCache.enabled", DEFAULT_REQUEST_CACHE_ENABLED, defaults?.RequestCacheEnabled); + MetricsRollingStatisticalWindowInMilliseconds = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingStats.timeInMilliseconds", DEFAULT_METRICS_ROLLING_STATISTICAL_WINDOW, defaults?.MetricsRollingStatisticalWindowInMilliseconds); + MetricsRollingStatisticalWindowBuckets = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingStats.numBuckets", DEFAULT_METRICS_ROLLING_STATISTICAL_WINDOW_BUCKETS, defaults?.MetricsRollingStatisticalWindowBuckets); + MetricsRollingPercentileEnabled = GetBoolean(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.enabled", DEFAULT_METRICS_ROLLING_PERCENTILE_ENABLED, defaults?.MetricsRollingPercentileEnabled); + MetricsRollingPercentileWindowInMilliseconds = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.timeInMilliseconds", DEFAULT_METRICS_ROLLING_PERCENTILE_WINDOW, defaults?.MetricsRollingPercentileWindowInMilliseconds); + MetricsRollingPercentileWindowBuckets = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.numBuckets", DEFAULT_METRICS_ROLLING_PERCENTILE_WINDOW_BUCKETS, defaults?.MetricsRollingPercentileWindowBuckets); + MetricsRollingPercentileBucketSize = GetInteger(HYSTRIX_COLLAPSER_PREFIX, key.Name, "metrics.rollingPercentile.bucketSize", DEFAULT_METRICS_ROLLING_PERCENTILE_BUCKET_SIZE, defaults?.MetricsRollingPercentileBucketSize); + } + + public IHystrixCollapserKey CollapserKey { get; set; } + + public RequestCollapserScope Scope { get; set; } + + public bool RequestCacheEnabled { get; set; } + + public int MaxRequestsInBatch { get; set; } + + public int TimerDelayInMilliseconds { get; set; } + + public int MetricsRollingStatisticalWindowInMilliseconds { get; set; } + + public int MetricsRollingStatisticalWindowBuckets { get; set; } + + public bool MetricsRollingPercentileEnabled { get; set; } + + public int MetricsRollingPercentileWindowInMilliseconds { get; set; } + + public int MetricsRollingPercentileWindowBuckets { get; set; } + + public int MetricsRollingPercentileBucketSize { get; set; } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommand.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommand.cs similarity index 56% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommand.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommand.cs index 8b5c658..c29f0b1 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommand.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommand.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,49 +27,69 @@ namespace Steeltoe.CircuitBreaker.Hystrix { public class HystrixCommand : HystrixCommand, IHystrixExecutable { - protected new readonly Action _run; protected new readonly Action _fallback; - public HystrixCommand(IHystrixCommandGroupKey group, Action run = null, Action fallback = null, ILogger logger = null) : - this(group, null, null, null, null, null, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, Action run = null, Action fallback = null, ILogger logger = null) + : this(group, null, null, null, null, null, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, Action run = null, Action fallback = null, ILogger logger = null) : - this(group, null, threadPool, null, null, null, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, Action run = null, Action fallback = null, ILogger logger = null) + : this(group, null, threadPool, null, null, null, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds, Action run = null, Action fallback = null, ILogger logger = null) : - this(group, null, null, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds, Action run = null, Action fallback = null, ILogger logger = null) + : this(group, null, null, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds, Action run = null, Action fallback = null, ILogger logger = null) : - this(group, null, threadPool, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds, Action run = null, Action fallback = null, ILogger logger = null) + : this(group, null, threadPool, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandOptions commandOptions, Action run = null, Action fallback = null, ILogger logger = null) : - this(commandOptions.GroupKey, commandOptions.CommandKey, commandOptions.ThreadPoolKey, null, null, commandOptions, commandOptions.ThreadPoolOptions, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandOptions commandOptions, Action run = null, Action fallback = null, ILogger logger = null) + : this(commandOptions.GroupKey, commandOptions.CommandKey, commandOptions.ThreadPoolKey, null, null, commandOptions, commandOptions.ThreadPoolOptions, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, IHystrixCommandKey key, IHystrixThreadPoolKey threadPoolKey, IHystrixCircuitBreaker circuitBreaker, IHystrixThreadPool threadPool, - IHystrixCommandOptions commandOptionsDefaults, IHystrixThreadPoolOptions threadPoolOptionsDefaults, HystrixCommandMetrics metrics, SemaphoreSlim fallbackSemaphore, SemaphoreSlim executionSemaphore, - HystrixOptionsStrategy optionsStrategy, HystrixCommandExecutionHook executionHook, Action run, Action fallback, ILogger logger = null) : - base(group, key, threadPoolKey, circuitBreaker, threadPool, commandOptionsDefaults, threadPoolOptionsDefaults, metrics, fallbackSemaphore, executionSemaphore, optionsStrategy, executionHook, null, null, logger) + public HystrixCommand( + IHystrixCommandGroupKey group, + IHystrixCommandKey key, + IHystrixThreadPoolKey threadPoolKey, + IHystrixCircuitBreaker circuitBreaker, + IHystrixThreadPool threadPool, + IHystrixCommandOptions commandOptionsDefaults, + IHystrixThreadPoolOptions threadPoolOptionsDefaults, + HystrixCommandMetrics metrics, + SemaphoreSlim fallbackSemaphore, + SemaphoreSlim executionSemaphore, + HystrixOptionsStrategy optionsStrategy, + HystrixCommandExecutionHook executionHook, + Action run, + Action fallback, + ILogger logger = null) + : base(group, key, threadPoolKey, circuitBreaker, threadPool, commandOptionsDefaults, threadPoolOptionsDefaults, metrics, fallbackSemaphore, executionSemaphore, optionsStrategy, executionHook, null, null, logger) { if (run == null) + { _run = () => Run(); + } else + { _run = run; + } if (fallback == null) + { _fallback = () => RunFallback(); + } else + { _fallback = fallback; + } } public new void Execute() @@ -104,108 +123,114 @@ namespace Steeltoe.CircuitBreaker.Hystrix { _run(); return Unit.Default; - } protected override Unit DoFallback() { RunFallback(); return Unit.Default; - } - } +#pragma warning disable SA1402 // File may only contain a single class public class HystrixCommand : AbstractCommand, IHystrixExecutable +#pragma warning restore SA1402 // File may only contain a single class { - protected readonly Func _run; protected readonly Func _fallback; - public HystrixCommand(IHystrixCommandGroupKey group, Func run = null, Func fallback = null, ILogger logger = null) : - this(group, null, null, null, null, null, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, Func run = null, Func fallback = null, ILogger logger = null) + : this(group, null, null, null, null, null, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, Func run = null, Func fallback = null, ILogger logger = null) : - this(group, null, threadPool, null, null, null, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, Func run = null, Func fallback = null, ILogger logger = null) + : this(group, null, threadPool, null, null, null, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds, Func run = null, Func fallback = null, ILogger logger = null) : - this(group, null, null, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds, Func run = null, Func fallback = null, ILogger logger = null) + : this(group, null, null, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds, Func run = null, Func fallback = null, ILogger logger = null) : - this(group, null, threadPool, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandGroupKey group, IHystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds, Func run = null, Func fallback = null, ILogger logger = null) + : this(group, null, threadPool, null, null, new HystrixCommandOptions() { ExecutionTimeoutInMilliseconds = executionIsolationThreadTimeoutInMilliseconds }, null, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandOptions commandOptions, Func run = null, Func fallback = null, ILogger logger = null) : - this(commandOptions.GroupKey, commandOptions.CommandKey, commandOptions.ThreadPoolKey, null, null, commandOptions, commandOptions.ThreadPoolOptions, null, null, null, null, null, run, fallback) + public HystrixCommand(IHystrixCommandOptions commandOptions, Func run = null, Func fallback = null, ILogger logger = null) + : this(commandOptions.GroupKey, commandOptions.CommandKey, commandOptions.ThreadPoolKey, null, null, commandOptions, commandOptions.ThreadPoolOptions, null, null, null, null, null, run, fallback) { } - public HystrixCommand(IHystrixCommandGroupKey group, IHystrixCommandKey key, IHystrixThreadPoolKey threadPoolKey, IHystrixCircuitBreaker circuitBreaker, IHystrixThreadPool threadPool, - IHystrixCommandOptions commandOptionsDefaults, IHystrixThreadPoolOptions threadPoolOptionsDefaults, HystrixCommandMetrics metrics, SemaphoreSlim fallbackSemaphore, SemaphoreSlim executionSemaphore, - HystrixOptionsStrategy optionsStrategy, HystrixCommandExecutionHook executionHook, Func run, Func fallback, ILogger logger = null) : - base(group, key, threadPoolKey, circuitBreaker, threadPool, commandOptionsDefaults, threadPoolOptionsDefaults, metrics, fallbackSemaphore, executionSemaphore, optionsStrategy, executionHook, logger) + public HystrixCommand( + IHystrixCommandGroupKey group, + IHystrixCommandKey key, + IHystrixThreadPoolKey threadPoolKey, + IHystrixCircuitBreaker circuitBreaker, + IHystrixThreadPool threadPool, + IHystrixCommandOptions commandOptionsDefaults, + IHystrixThreadPoolOptions threadPoolOptionsDefaults, + HystrixCommandMetrics metrics, + SemaphoreSlim fallbackSemaphore, + SemaphoreSlim executionSemaphore, + HystrixOptionsStrategy optionsStrategy, + HystrixCommandExecutionHook executionHook, + Func run, + Func fallback, + ILogger logger = null) + : base(group, key, threadPoolKey, circuitBreaker, threadPool, commandOptionsDefaults, threadPoolOptionsDefaults, metrics, fallbackSemaphore, executionSemaphore, optionsStrategy, executionHook, logger) { if (run == null) + { _run = () => Run(); + } else + { _run = run; + } if (fallback == null) + { _fallback = () => RunFallback(); + } else + { _fallback = fallback; + } } - public TResult Execute() { + public TResult Execute() + { try { var task = ExecuteAsync(); var result = task.Result; return result; - } catch (AggregateException e) { + } + catch (AggregateException e) + { throw e.Flatten().InnerException; - } catch (Exception e) + } + catch (Exception e) { throw DecomposeException(e); } } - internal Task ToTask() - { - - Setup(); - - Task fromCache = null; - if (PutInCacheIfAbsent(tcs.Task, out fromCache)) - { - var task = fromCache; - return task; - - } - - ApplyHystrixSemantics(); - - return tcs.Task; - } - public Task ExecuteAsync(CancellationToken token) { - this.usersToken = token; - + _usersToken = token; + Task toStart = ToTask(); if (!toStart.IsCompleted) { - if (this.execThreadTask != null) + if (_execThreadTask != null) { StartCommand(); - } else + } + else { tcs.TrySetException(new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, GetType(), "Thread task missing")); tcs.Commit(); @@ -230,7 +255,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix public IObservable Observe(CancellationToken token) { - ReplaySubject subject = new ReplaySubject(); IObservable observable = ToObservable(); observable.Subscribe(subject, token); @@ -238,27 +262,41 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public IObservable ToObservable() - { - + { IObservable observable = Observable.FromAsync((ct) => - { - this.usersToken = ct; - Task toStart = ToTask(); - if (!toStart.IsCompleted) - { - if (this.execThreadTask != null) - { - StartCommand(); - } else - { - tcs.TrySetException(new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, GetType(), "Thread task missing")); - tcs.Commit(); - } - } - return toStart; - }); + { + this._usersToken = ct; + Task toStart = ToTask(); + if (!toStart.IsCompleted) + { + if (this._execThreadTask != null) + { + StartCommand(); + } + else + { + tcs.TrySetException(new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, GetType(), "Thread task missing")); + tcs.Commit(); + } + } + return toStart; + }); return observable; + } + internal Task ToTask() + { + Setup(); + + if (PutInCacheIfAbsent(tcs.Task, out Task fromCache)) + { + var task = fromCache; + return task; + } + + ApplyHystrixSemantics(); + + return tcs.Task; } protected virtual TResult Run() @@ -285,10 +323,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix { return _run(); } + protected override TResult DoFallback() { - return _fallback(); + return _fallback(); } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommandMetrics.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommandMetrics.cs similarity index 76% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommandMetrics.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommandMetrics.cs index 00eee5c..ceb2b2d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommandMetrics.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommandMetrics.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,37 +21,32 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; - namespace Steeltoe.CircuitBreaker.Hystrix { public class HystrixCommandMetrics : HystrixMetrics { - //private static final Logger logger = LoggerFactory.getLogger(HystrixCommandMetrics.class); - private static readonly IList ALL_EVENT_TYPES = HystrixEventTypeHelper.Values; public static Func AppendEventToBucket { get; } = (initialCountArray, execution) => { - ExecutionResult.EventCounts eventCounts = execution.Eventcounts; foreach (HystrixEventType eventType in ALL_EVENT_TYPES) { switch (eventType) { - case HystrixEventType.EXCEPTION_THROWN: break; //this is just a sum of other anyway - don't do the work here + case HystrixEventType.EXCEPTION_THROWN: break; // this is just a sum of other anyway - don't do the work here default: var ordinal = (int)eventType; initialCountArray[ordinal] += eventCounts.GetCount(eventType); break; } } + return initialCountArray; - }; public static Func BucketAggregator { get; } = (cumulativeEvents, bucketEventCounts) => { - foreach (HystrixEventType eventType in ALL_EVENT_TYPES) { switch (eventType) @@ -64,6 +58,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix var ordinal2 = (int)exceptionEventType; cumulativeEvents[ordinal1] += bucketEventCounts[ordinal2]; } + break; default: var ordinal = (int)eventType; @@ -71,12 +66,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix break; } } + return cumulativeEvents; - }; - private static readonly ConcurrentDictionary metrics = new ConcurrentDictionary(); - + private static readonly ConcurrentDictionary Metrics = new ConcurrentDictionary(); public static HystrixCommandMetrics GetInstance(IHystrixCommandKey key, IHystrixCommandGroupKey commandGroup, IHystrixCommandOptions properties) { @@ -96,35 +90,34 @@ namespace Steeltoe.CircuitBreaker.Hystrix nonNullThreadPoolKey = threadPoolKey; } - return metrics.GetOrAddEx(key.Name, (k) => new HystrixCommandMetrics(key, commandGroup, nonNullThreadPoolKey, properties, HystrixPlugins.EventNotifier)); + return Metrics.GetOrAddEx(key.Name, (k) => new HystrixCommandMetrics(key, commandGroup, nonNullThreadPoolKey, properties, HystrixPlugins.EventNotifier)); } public static HystrixCommandMetrics GetInstance(IHystrixCommandKey key) { - HystrixCommandMetrics result = null; - metrics.TryGetValue(key.Name, out result); + Metrics.TryGetValue(key.Name, out HystrixCommandMetrics result); return result; } public static ICollection GetInstances() { List commandMetrics = new List(); - foreach (HystrixCommandMetrics tpm in metrics.Values) + foreach (HystrixCommandMetrics tpm in Metrics.Values) { commandMetrics.Add(tpm); } + return commandMetrics.AsReadOnly(); } - - internal static void Reset() { foreach (HystrixCommandMetrics metricsInstance in GetInstances()) { metricsInstance.UnsubscribeAll(); } - metrics.Clear(); + + Metrics.Clear(); } private readonly IHystrixCommandOptions properties; @@ -133,15 +126,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix private readonly IHystrixThreadPoolKey threadPoolKey; private readonly AtomicInteger concurrentExecutionCount = new AtomicInteger(); - private HealthCountsStream healthCountsStream; private readonly RollingCommandEventCounterStream rollingCommandEventCounterStream; private readonly CumulativeCommandEventCounterStream cumulativeCommandEventCounterStream; private readonly RollingCommandLatencyDistributionStream rollingCommandLatencyDistributionStream; private readonly RollingCommandUserLatencyDistributionStream rollingCommandUserLatencyDistributionStream; private readonly RollingCommandMaxConcurrencyStream rollingCommandMaxConcurrencyStream; - private readonly Object _syncLock = new object(); - HystrixCommandMetrics(IHystrixCommandKey key, IHystrixCommandGroupKey commandGroup, IHystrixThreadPoolKey threadPoolKey, IHystrixCommandOptions properties, HystrixEventNotifier eventNotifier) : base(null) + private readonly object _syncLock = new object(); + + private HealthCountsStream healthCountsStream; + + internal HystrixCommandMetrics(IHystrixCommandKey key, IHystrixCommandGroupKey commandGroup, IHystrixThreadPoolKey threadPoolKey, IHystrixCommandOptions properties, HystrixEventNotifier eventNotifier) + : base(null) { this.key = key; this.group = commandGroup; @@ -173,7 +169,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return key; } } - public IHystrixCommandGroupKey CommandGroup { get { return group; } @@ -184,7 +179,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return threadPoolKey; } } - public IHystrixCommandOptions Properties { get { return properties; } @@ -210,25 +204,21 @@ namespace Steeltoe.CircuitBreaker.Hystrix return GetRollingCount(HystrixEventTypeHelper.From(@event)); } - public int GetExecutionTimePercentile(double percentile) { return rollingCommandLatencyDistributionStream.GetLatestPercentile(percentile); } - public int ExecutionTimeMean { get { return rollingCommandLatencyDistributionStream.LatestMean; } } - public int GetTotalTimePercentile(double percentile) { return rollingCommandUserLatencyDistributionStream.GetLatestPercentile(percentile); } - public int TotalTimeMean { get { return rollingCommandUserLatencyDistributionStream.LatestMean; } @@ -239,17 +229,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return rollingCommandMaxConcurrencyStream.LatestRollingMax; } } - public int CurrentConcurrentExecutionCount { get { return concurrentExecutionCount.Value; } } - + internal void MarkCommandStart(IHystrixCommandKey commandKey, IHystrixThreadPoolKey threadPoolKey, ExecutionIsolationStrategy isolationStrategy) { int currentCount = concurrentExecutionCount.IncrementAndGet(); HystrixThreadEventStream.GetInstance().CommandExecutionStarted(commandKey, threadPoolKey, isolationStrategy, currentCount); } + internal void MarkCommandDone(ExecutionResult executionResult, IHystrixCommandKey commandKey, IHystrixThreadPoolKey threadPoolKey, bool executionStarted) { HystrixThreadEventStream.GetInstance().ExecutionDone(executionResult, commandKey, threadPoolKey); @@ -259,7 +249,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix } } - public HealthCounts Healthcounts { get { return healthCountsStream.Latest; } @@ -274,72 +263,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix rollingCommandUserLatencyDistributionStream.Unsubscribe(); rollingCommandMaxConcurrencyStream.Unsubscribe(); } - - - } - - - public class HealthCounts - { - private readonly long totalCount; - private readonly long errorCount; - private readonly int errorPercentage; - - HealthCounts(long total, long error) - { - this.totalCount = total; - this.errorCount = error; - if (totalCount > 0) - { - this.errorPercentage = (int)((errorCount * 100) / totalCount); - } - else - { - this.errorPercentage = 0; - } - } - - private static readonly HealthCounts EMPTY = new HealthCounts(0, 0); - - public long TotalRequests - { - get { return totalCount; } - } - - public long ErrorCount - { - get { return errorCount; } - } - - public int ErrorPercentage - { - get { return errorPercentage; } - } - - public HealthCounts Plus(long[] eventTypeCounts) - { - long updatedTotalCount = totalCount; - long updatedErrorCount = errorCount; - - long successCount = eventTypeCounts[(int)HystrixEventType.SUCCESS]; - long failureCount = eventTypeCounts[(int)HystrixEventType.FAILURE]; - long timeoutCount = eventTypeCounts[(int)HystrixEventType.TIMEOUT]; - long threadPoolRejectedCount = eventTypeCounts[(int)HystrixEventType.THREAD_POOL_REJECTED]; - long semaphoreRejectedCount = eventTypeCounts[(int)HystrixEventType.SEMAPHORE_REJECTED]; - - updatedTotalCount += (successCount + failureCount + timeoutCount + threadPoolRejectedCount + semaphoreRejectedCount); - updatedErrorCount += (failureCount + timeoutCount + threadPoolRejectedCount + semaphoreRejectedCount); - return new HealthCounts(updatedTotalCount, updatedErrorCount); - } - - public static HealthCounts Empty - { - get { return EMPTY; } - } - - public override string ToString() - { - return "HealthCounts[" + errorCount + " / " + totalCount + " : " + ErrorPercentage + "%]"; - } } } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommandOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommandOptions.cs similarity index 55% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommandOptions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommandOptions.cs index 2eb756c..32c975b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCommandOptions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCommandOptions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,7 +17,6 @@ using System; namespace Steeltoe.CircuitBreaker.Hystrix { - public enum ExecutionIsolationStrategy { THREAD, @@ -27,17 +25,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix public class HystrixCommandOptions : HystrixBaseOptions, IHystrixCommandOptions { - protected const string HYSTRIX_COMMAND_PREFIX = "hystrix:command"; - - protected IHystrixCommandOptions defaults = null; - internal const int Default_MetricsRollingStatisticalWindow = 10000; // default => statisticalWindow: 10000 = 10 seconds (and default of 10 buckets so each bucket is 1 second) internal const int Default_MetricsRollingStatisticalWindowBuckets = 10; // default => statisticalWindowBuckets: 10 = 10 buckets in a 10 second window so each bucket is 1 second internal const int Default_CircuitBreakerRequestVolumeThreshold = 20; // default => statisticalWindowVolumeThreshold: 20 requests in 10 seconds must occur before statistics matter internal const int Default_CircuitBreakerSleepWindowInMilliseconds = 5000; // default => sleepWindow: 5000 = 5 seconds that we will sleep before trying again after tripping the circuit internal const int Default_CircuitBreakerErrorThresholdPercentage = 50; // default => errorThresholdPercentage = 50 = if 50%+ of requests in 10 seconds are failures or latent then we will trip the circuit internal const bool Default_CircuitBreakerForceOpen = false; // default => forceCircuitOpen = false (we want to allow traffic) - /* package */ internal const bool Default_CircuitBreakerForceClosed = false; // default => ignoreErrors = false internal const int Default_ExecutionTimeoutInMilliseconds = 1000; // default => executionTimeoutInMilliseconds: 1000 = 1 second internal const bool Default_ExecutionTimeoutEnabled = true; @@ -54,6 +47,53 @@ namespace Steeltoe.CircuitBreaker.Hystrix internal const int Default_MetricsRollingPercentileBucketSize = 100; // default to 100 values max per bucket internal const int Default_MetricsHealthSnapshotIntervalInMilliseconds = 500; // default to 500ms as max frequency between allowing snapshots of health (error percentage etc) + protected const string HYSTRIX_COMMAND_PREFIX = "hystrix:command"; + + protected IHystrixCommandOptions defaults = null; + + public HystrixCommandOptions( + IHystrixCommandGroupKey groupKey, + IHystrixCommandKey key, + IHystrixCommandOptions defaults = null, + IHystrixDynamicOptions dynamic = null) + : this(key, defaults, dynamic) + { + GroupKey = groupKey; + } + + public HystrixCommandOptions( + IHystrixCommandKey key, + IHystrixCommandOptions defaults = null, + IHystrixDynamicOptions dynamic = null) + : this(defaults, dynamic) + { + CommandKey = key; + CircuitBreakerEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker.enabled", Default_CircuitBreakerEnabled, defaults?.CircuitBreakerEnabled); + CircuitBreakerRequestVolumeThreshold = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:requestVolumeThreshold", Default_CircuitBreakerRequestVolumeThreshold, defaults?.CircuitBreakerRequestVolumeThreshold); + CircuitBreakerSleepWindowInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:sleepWindowInMilliseconds", Default_CircuitBreakerSleepWindowInMilliseconds, defaults?.CircuitBreakerSleepWindowInMilliseconds); + CircuitBreakerErrorThresholdPercentage = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:errorThresholdPercentage", Default_CircuitBreakerErrorThresholdPercentage, defaults?.CircuitBreakerErrorThresholdPercentage); + CircuitBreakerForceOpen = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:forceOpen", Default_CircuitBreakerForceOpen, defaults?.CircuitBreakerForceOpen); + CircuitBreakerForceClosed = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:forceClosed", Default_CircuitBreakerForceClosed, defaults?.CircuitBreakerForceClosed); + ExecutionIsolationStrategy = GetIsolationStrategy(key); + ExecutionTimeoutInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "execution:isolation:thread:timeoutInMilliseconds", Default_ExecutionTimeoutInMilliseconds, defaults?.ExecutionTimeoutInMilliseconds); + ExecutionTimeoutEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "execution:timeout:enabled", Default_ExecutionTimeoutEnabled, defaults?.ExecutionTimeoutEnabled); + ExecutionIsolationSemaphoreMaxConcurrentRequests = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "execution:isolation:semaphore:maxConcurrentRequests", Default_ExecutionIsolationSemaphoreMaxConcurrentRequests, defaults?.ExecutionIsolationSemaphoreMaxConcurrentRequests); + FallbackIsolationSemaphoreMaxConcurrentRequests = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "fallback:isolation:semaphore:maxConcurrentRequests", Default_FallbackIsolationSemaphoreMaxConcurrentRequests, defaults?.FallbackIsolationSemaphoreMaxConcurrentRequests); + FallbackEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "fallback:enabled", Default_FallbackEnabled, defaults?.FallbackEnabled); + + MetricsRollingStatisticalWindowInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingStats:timeInMilliseconds", Default_MetricsRollingStatisticalWindow, defaults?.MetricsRollingStatisticalWindowInMilliseconds); + MetricsRollingStatisticalWindowBuckets = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingStats:numBuckets", Default_MetricsRollingStatisticalWindowBuckets, defaults?.MetricsRollingStatisticalWindowBuckets); + MetricsRollingPercentileEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:enabled", Default_MetricsRollingPercentileEnabled, defaults?.MetricsRollingPercentileEnabled); + MetricsRollingPercentileWindowInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:timeInMilliseconds", Default_MetricsRollingPercentileWindow, defaults?.MetricsRollingPercentileWindowInMilliseconds); + MetricsRollingPercentileWindowBuckets = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:numBuckets", Default_MetricsRollingPercentileWindowBuckets, defaults?.MetricsRollingPercentileWindowBuckets); + MetricsRollingPercentileBucketSize = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:bucketSize", Default_MetricsRollingPercentileBucketSize, defaults?.MetricsRollingPercentileBucketSize); + MetricsHealthSnapshotIntervalInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:healthSnapshot:intervalInMilliseconds", Default_MetricsHealthSnapshotIntervalInMilliseconds, defaults?.MetricsHealthSnapshotIntervalInMilliseconds); + + RequestCacheEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "requestCache:enabled", Default_RequestCacheEnabled, defaults?.RequestCacheEnabled); + RequestLogEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "requestLog:enabled", Default_RequestLogEnabled, defaults?.RequestLogEnabled); + + ExecutionIsolationThreadPoolKeyOverride = GetThreadPoolKeyOverride(HYSTRIX_COMMAND_PREFIX, key.Name, "threadPoolKeyOverride", null, defaults?.ExecutionIsolationThreadPoolKeyOverride); + } internal HystrixCommandOptions(IHystrixCommandOptions defaults = null, IHystrixDynamicOptions dynamic = null) : base(dynamic) @@ -84,272 +124,56 @@ namespace Steeltoe.CircuitBreaker.Hystrix RequestLogEnabled = Default_RequestLogEnabled; } - public HystrixCommandOptions(IHystrixCommandGroupKey groupKey, IHystrixCommandKey key, IHystrixCommandOptions defaults = null, IHystrixDynamicOptions dynamic = null) - : this(key, defaults, dynamic) - { - GroupKey = groupKey; - } - - public HystrixCommandOptions(IHystrixCommandKey key, IHystrixCommandOptions defaults = null, IHystrixDynamicOptions dynamic = null) - : this(defaults, dynamic) - { - CommandKey = key; - CircuitBreakerEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker.enabled", Default_CircuitBreakerEnabled, defaults?.CircuitBreakerEnabled); - CircuitBreakerRequestVolumeThreshold = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:requestVolumeThreshold", Default_CircuitBreakerRequestVolumeThreshold, defaults?.CircuitBreakerRequestVolumeThreshold); - CircuitBreakerSleepWindowInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:sleepWindowInMilliseconds", Default_CircuitBreakerSleepWindowInMilliseconds, defaults?.CircuitBreakerSleepWindowInMilliseconds); - CircuitBreakerErrorThresholdPercentage = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:errorThresholdPercentage", Default_CircuitBreakerErrorThresholdPercentage, defaults?.CircuitBreakerErrorThresholdPercentage); - CircuitBreakerForceOpen = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:forceOpen", Default_CircuitBreakerForceOpen, defaults?.CircuitBreakerForceOpen); - CircuitBreakerForceClosed = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "circuitBreaker:forceClosed", Default_CircuitBreakerForceClosed, defaults?.CircuitBreakerForceClosed); - ExecutionIsolationStrategy = GetIsolationStrategy(key); - ExecutionTimeoutInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "execution:isolation:thread:timeoutInMilliseconds", Default_ExecutionTimeoutInMilliseconds, defaults?.ExecutionTimeoutInMilliseconds); - ExecutionTimeoutEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "execution:timeout:enabled", Default_ExecutionTimeoutEnabled, defaults?.ExecutionTimeoutEnabled); - ExecutionIsolationSemaphoreMaxConcurrentRequests = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "execution:isolation:semaphore:maxConcurrentRequests", Default_ExecutionIsolationSemaphoreMaxConcurrentRequests, defaults?.ExecutionIsolationSemaphoreMaxConcurrentRequests); - FallbackIsolationSemaphoreMaxConcurrentRequests = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "fallback:isolation:semaphore:maxConcurrentRequests", Default_FallbackIsolationSemaphoreMaxConcurrentRequests, defaults?.FallbackIsolationSemaphoreMaxConcurrentRequests); - FallbackEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "fallback:enabled", Default_FallbackEnabled, defaults?.FallbackEnabled); - - MetricsRollingStatisticalWindowInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingStats:timeInMilliseconds", Default_MetricsRollingStatisticalWindow, defaults?.MetricsRollingStatisticalWindowInMilliseconds); - MetricsRollingStatisticalWindowBuckets = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingStats:numBuckets", Default_MetricsRollingStatisticalWindowBuckets, defaults?.MetricsRollingStatisticalWindowBuckets); - MetricsRollingPercentileEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:enabled", Default_MetricsRollingPercentileEnabled, defaults?.MetricsRollingPercentileEnabled); - MetricsRollingPercentileWindowInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:timeInMilliseconds", Default_MetricsRollingPercentileWindow, defaults?.MetricsRollingPercentileWindowInMilliseconds); - MetricsRollingPercentileWindowBuckets = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:numBuckets", Default_MetricsRollingPercentileWindowBuckets, defaults?.MetricsRollingPercentileWindowBuckets); - MetricsRollingPercentileBucketSize = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:rollingPercentile:bucketSize", Default_MetricsRollingPercentileBucketSize, defaults?.MetricsRollingPercentileBucketSize); - MetricsHealthSnapshotIntervalInMilliseconds = GetInteger(HYSTRIX_COMMAND_PREFIX, key.Name, "metrics:healthSnapshot:intervalInMilliseconds", Default_MetricsHealthSnapshotIntervalInMilliseconds, defaults?.MetricsHealthSnapshotIntervalInMilliseconds); - - RequestCacheEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "requestCache:enabled", Default_RequestCacheEnabled, defaults?.RequestCacheEnabled); - RequestLogEnabled = GetBoolean(HYSTRIX_COMMAND_PREFIX, key.Name, "requestLog:enabled", Default_RequestLogEnabled, defaults?.RequestLogEnabled); - - ExecutionIsolationThreadPoolKeyOverride = GetThreadPoolKeyOverride(HYSTRIX_COMMAND_PREFIX, key.Name, "threadPoolKeyOverride", null, defaults?.ExecutionIsolationThreadPoolKeyOverride); - } - - public IHystrixCommandGroupKey GroupKey { get; set; } public IHystrixCommandKey CommandKey { get; set; } public IHystrixThreadPoolKey ThreadPoolKey { get; set; } - /// - /// Whether to use a or not. If false no circuit-breaker logic will be used and all requests permitted. - /// - /// This is similar in effect to except that continues tracking metrics and knowing whether it - /// should be open/closed, this property results in not even instantiating a circuit-breaker. - /// - /// - /// - /// {@code Boolean>} public virtual bool CircuitBreakerEnabled { get; set; } - /// - /// Error percentage threshold (as whole number such as 50) at which point the circuit breaker will trip open and reject requests. - /// - /// It will stay tripped for the duration defined in ; - /// - /// - /// The error percentage this is compared against comes from . - /// - /// - /// - /// {@code Integer>} public virtual int CircuitBreakerErrorThresholdPercentage { get; set; } - - /// - /// If true the will always return true to allow requests regardless of the error percentage from . - /// - /// The property takes precedence so if it set to true this property does nothing. - /// - /// - /// - /// {@code Boolean>} public virtual bool CircuitBreakerForceClosed { get; set; } - /// - /// If true the will always return false, causing the circuit to be open (tripped) and reject all requests. - /// - /// This property takes precedence over ; - /// - /// - /// - /// {@code Boolean>} public virtual bool CircuitBreakerForceOpen { get; set; } - /// - /// Minimum number of requests in the that must exist before the will trip. - /// - /// If below this number the circuit will not trip regardless of error percentage. - /// - /// - /// - /// {@code Integer>} public virtual int CircuitBreakerRequestVolumeThreshold { get; set; } - /// - /// The time in milliseconds after a trips open that it should wait before trying requests again. - /// - /// {@code Integer>} public virtual int CircuitBreakerSleepWindowInMilliseconds { get; set; } - /// - /// Number of concurrent requests permitted to . Requests beyond the concurrent limit will be rejected. - /// - /// Applicable only when == SEMAPHORE. - /// - /// - /// - /// {@code Integer>} public virtual int ExecutionIsolationSemaphoreMaxConcurrentRequests { get; set; } - /// - /// What isolation strategy will be executed with. - /// - /// If then it will be executed on a separate thread and concurrent requests limited by the number of threads in the thread-pool. - /// - /// - /// If then it will be executed on the calling thread and concurrent requests limited by the semaphore count. - /// - /// - /// - /// {@code Boolean>} public virtual ExecutionIsolationStrategy ExecutionIsolationStrategy { get; set; } - - /// - /// Whether the execution thread should attempt an interrupt (using ) when a thread times out. - /// - /// Applicable only when == THREAD. - /// - /// - /// - /// {@code Boolean>} - //public virtual bool ExecutionIsolationThreadInterruptOnTimeout { get; set; } - - /// - /// Whether the execution thread should be interrupted if the execution observable is unsubscribed or the future is cancelled via ). - /// - /// Applicable only when == THREAD. - /// - /// - /// - /// {@code Boolean>} - //public virtual bool ExecutionIsolationThreadInterruptOnFutureCancel { get; set; } - - - /// - /// Allow a dynamic override of the that will dynamically change which a executes on. - /// - /// Typically this should return NULL which will cause it to use the injected into a or derived from the . - /// - /// - /// When set the injected or derived values will be ignored and a new created (if necessary) and the will begin using the newly defined pool. - /// - /// - /// - /// {@code String>} public virtual string ExecutionIsolationThreadPoolKeyOverride { get; set; } - /// - /// Time in milliseconds at which point the command will timeout and halt execution. - /// - /// If == true and the command is thread-isolated, the executing thread will be interrupted. - /// If the command is semaphore-isolated and a , that command will get unsubscribed. - /// - /// - /// - /// - /// - /// {@code Integer>} public virtual int ExecutionTimeoutInMilliseconds { get; set; } - - /// - /// Whether the timeout mechanism is enabled for this command - /// - /// {@code Boolean>} - /// - /// @since 1.4.4 public virtual bool ExecutionTimeoutEnabled { get; set; } - - /// - /// Number of concurrent requests permitted to . Requests beyond the concurrent limit will fail-fast and not attempt retrieving a fallback. - /// - /// {@code Integer>} public virtual int FallbackIsolationSemaphoreMaxConcurrentRequests { get; set; } - - /// - /// Whether should be attempted when failure occurs. - /// - /// {@code Boolean>} - /// - /// @since 1.2 public virtual bool FallbackEnabled { get; set; } - /// - /// Time in milliseconds to wait between allowing health snapshots to be taken that calculate success and error percentages and affect status. - /// - /// On high-volume circuits the continual calculation of error percentage can become CPU intensive thus this controls how often it is calculated. - /// - /// - /// - /// {@code Integer>} public virtual int MetricsHealthSnapshotIntervalInMilliseconds { get; set; } - - /// - /// Maximum number of values stored in each bucket of the rolling percentile. This is passed into inside . - /// - /// {@code Integer>} public virtual int MetricsRollingPercentileBucketSize { get; set; } - /// - /// Whether percentile metrics should be captured using inside . - /// - /// {@code Boolean>} public virtual bool MetricsRollingPercentileEnabled { get; set; } - /// - /// Duration of percentile rolling window in milliseconds. This is passed into inside . - /// - /// {@code Integer>} - /// @deprecated Use public virtual int MetricsRollingPercentileWindow { get; set; } - /// - /// Duration of percentile rolling window in milliseconds. This is passed into inside . - /// - /// {@code Integer>} public virtual int MetricsRollingPercentileWindowInMilliseconds { get; set; } - - /// - /// Number of buckets the rolling percentile window is broken into. This is passed into inside . - /// - /// {@code Integer>} public virtual int MetricsRollingPercentileWindowBuckets { get; set; } - /// - /// Duration of statistical rolling window in milliseconds. This is passed into inside . - /// - /// {@code Integer>} + public virtual int MetricsRollingStatisticalWindowInMilliseconds { get; set; } - - /// - /// Number of buckets the rolling statistical window is broken into. This is passed into inside . - /// - /// {@code Integer>} public virtual int MetricsRollingStatisticalWindowBuckets { get; set; } - /// - /// Whether should be used with to provide de-duplication functionality via request-scoped caching. - /// - /// {@code Boolean>} public virtual bool RequestCacheEnabled { get; set; } - /// - /// Whether execution and events should be logged to . - /// - /// {@code Boolean>} public virtual bool RequestLogEnabled { get; set; } protected virtual ExecutionIsolationStrategy GetIsolationStrategy(IHystrixCommandKey key) @@ -359,18 +183,20 @@ namespace Steeltoe.CircuitBreaker.Hystrix { return ExecutionIsolationStrategy.THREAD; } + if (ExecutionIsolationStrategy.SEMAPHORE.ToString().Equals(isolation, StringComparison.OrdinalIgnoreCase)) { return ExecutionIsolationStrategy.SEMAPHORE; } + throw new ArgumentOutOfRangeException("execution.isolation.strategy"); } protected virtual string GetThreadPoolKeyOverride(string prefix, string key, string property, string globalDefault, string instanceDefaultFromCode) { string result = globalDefault; - result = instanceDefaultFromCode != null ? instanceDefaultFromCode : result; // instance default from code - result = (dynamic != null) ? dynamic.GetString(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value + result = instanceDefaultFromCode ?? result; // instance default from code + result = (_dynamic != null) ? _dynamic.GetString(prefix + ":" + key + ":" + property, result) : result; // dynamic instance value return result; } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCounters.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCounters.cs similarity index 76% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCounters.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCounters.cs index e5fc6b0..6ff4563 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixCounters.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixCounters.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,37 +14,33 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; - namespace Steeltoe.CircuitBreaker.Hystrix { public static class HystrixCounters { - private static readonly AtomicInteger concurrentThreadsExecuting = new AtomicInteger(0); + private static readonly AtomicInteger _concurrentThreadsExecuting = new AtomicInteger(0); internal static int IncrementGlobalConcurrentThreads() { - return concurrentThreadsExecuting.IncrementAndGet(); + return _concurrentThreadsExecuting.IncrementAndGet(); } internal static int DecrementGlobalConcurrentThreads() { - return concurrentThreadsExecuting.DecrementAndGet(); + return _concurrentThreadsExecuting.DecrementAndGet(); } - public static int GlobalConcurrentThreadsExecuting { - get { return concurrentThreadsExecuting.Value; } + get { return _concurrentThreadsExecuting.Value; } } - public static int CommandCount { get { return HystrixCommandKeyDefault.CommandCount; } } - - public static int ThreadPoolCount + public static int ThreadPoolCount { get { return HystrixThreadPoolKeyDefault.ThreadPoolCount; } } @@ -55,5 +50,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return HystrixCommandGroupKeyDefault.GroupCount; } } } - } diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixEventType.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixEventType.cs new file mode 100644 index 0000000..ff0805b --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixEventType.cs @@ -0,0 +1,51 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public enum HystrixEventType + { + EMIT, + SUCCESS, + FAILURE, + TIMEOUT, + BAD_REQUEST, + SHORT_CIRCUITED, + THREAD_POOL_REJECTED, + SEMAPHORE_REJECTED, + FALLBACK_EMIT, + FALLBACK_SUCCESS, + FALLBACK_FAILURE, + FALLBACK_REJECTION, + FALLBACK_MISSING, + EXCEPTION_THROWN, + RESPONSE_FROM_CACHE, + CANCELLED, + COLLAPSED + } + + public enum ThreadPoolEventType + { + EXECUTED, + REJECTED, + UNKNOWN + } + + public enum CollapserEventType + { + BATCH_EXECUTED, + ADDED_TO_BATCH, + RESPONSE_FROM_CACHE + } +} \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixEventType.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixEventTypeHelper.cs similarity index 50% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixEventType.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixEventTypeHelper.cs index 9ecd539..6e53975 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixEventType.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixEventTypeHelper.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,82 +18,47 @@ using System.Collections.Generic; namespace Steeltoe.CircuitBreaker.Hystrix { - /// - /// Various states/events that execution can result in or have tracked. - /// - /// These are most often accessed via or . - /// - /// - public enum HystrixEventType - { - EMIT, - SUCCESS, - FAILURE, - TIMEOUT, - BAD_REQUEST, - SHORT_CIRCUITED, - THREAD_POOL_REJECTED, - SEMAPHORE_REJECTED, - FALLBACK_EMIT, - FALLBACK_SUCCESS, - FALLBACK_FAILURE, - FALLBACK_REJECTION, - FALLBACK_MISSING, - EXCEPTION_THROWN, - RESPONSE_FROM_CACHE, - CANCELLED, - COLLAPSED - }; - public static class HystrixEventTypeHelper { - - private static readonly IList valueList = new List(); - - /// - /// List of events that throw an Exception to the caller - /// public static readonly IList EXCEPTION_PRODUCING_EVENT_TYPES = new List(); - /// - /// List of events that are terminal - /// public static readonly IList TERMINAL_EVENT_TYPES = new List(); + private static readonly IList ValueList = new List(); + static HystrixEventTypeHelper() { EXCEPTION_PRODUCING_EVENT_TYPES.Add(HystrixEventType.BAD_REQUEST); EXCEPTION_PRODUCING_EVENT_TYPES.Add(HystrixEventType.FALLBACK_FAILURE); EXCEPTION_PRODUCING_EVENT_TYPES.Add(HystrixEventType.FALLBACK_MISSING); EXCEPTION_PRODUCING_EVENT_TYPES.Add(HystrixEventType.FALLBACK_REJECTION); - foreach (string evName in Enum.GetNames(typeof(HystrixEventType))) { - HystrixEventType e = (HystrixEventType) Enum.Parse(typeof(HystrixEventType), evName); + HystrixEventType e = (HystrixEventType)Enum.Parse(typeof(HystrixEventType), evName); if (e.IsTerminal()) { TERMINAL_EVENT_TYPES.Add(e); } } - valueList.Add(HystrixEventType.EMIT); - valueList.Add(HystrixEventType.SUCCESS); - valueList.Add(HystrixEventType.FAILURE); - valueList.Add(HystrixEventType.TIMEOUT); - valueList.Add(HystrixEventType.BAD_REQUEST); - valueList.Add(HystrixEventType.SHORT_CIRCUITED); - valueList.Add(HystrixEventType.THREAD_POOL_REJECTED); - valueList.Add(HystrixEventType.SEMAPHORE_REJECTED); - valueList.Add(HystrixEventType.FALLBACK_EMIT); - valueList.Add(HystrixEventType.FALLBACK_SUCCESS); - valueList.Add(HystrixEventType.FALLBACK_FAILURE); - valueList.Add(HystrixEventType.FALLBACK_REJECTION); - valueList.Add(HystrixEventType.FALLBACK_MISSING); - valueList.Add(HystrixEventType.EXCEPTION_THROWN); - valueList.Add(HystrixEventType.RESPONSE_FROM_CACHE); - valueList.Add(HystrixEventType.CANCELLED); - valueList.Add(HystrixEventType.COLLAPSED); + ValueList.Add(HystrixEventType.EMIT); + ValueList.Add(HystrixEventType.SUCCESS); + ValueList.Add(HystrixEventType.FAILURE); + ValueList.Add(HystrixEventType.TIMEOUT); + ValueList.Add(HystrixEventType.BAD_REQUEST); + ValueList.Add(HystrixEventType.SHORT_CIRCUITED); + ValueList.Add(HystrixEventType.THREAD_POOL_REJECTED); + ValueList.Add(HystrixEventType.SEMAPHORE_REJECTED); + ValueList.Add(HystrixEventType.FALLBACK_EMIT); + ValueList.Add(HystrixEventType.FALLBACK_SUCCESS); + ValueList.Add(HystrixEventType.FALLBACK_FAILURE); + ValueList.Add(HystrixEventType.FALLBACK_REJECTION); + ValueList.Add(HystrixEventType.FALLBACK_MISSING); + ValueList.Add(HystrixEventType.EXCEPTION_THROWN); + ValueList.Add(HystrixEventType.RESPONSE_FROM_CACHE); + ValueList.Add(HystrixEventType.CANCELLED); + ValueList.Add(HystrixEventType.COLLAPSED); } public static bool IsTerminal(this HystrixEventType evType) @@ -139,6 +103,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentOutOfRangeException(); } } + public static HystrixEventType From(this HystrixRollingNumberEvent @event) { switch (@event) @@ -179,107 +144,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentOutOfRangeException("Not an event that can be converted to HystrixEventType : " + @event); } } + public static IList Values { - get { return valueList; } - } - } - - - public enum ThreadPoolEventType - { - EXECUTED, - REJECTED, - UNKNOWN - }; - - public static class ThreadPoolEventTypeHelper - { - private static readonly IList valueList = new List(); - - public static IList Values - { - get { return valueList; } - } - - static ThreadPoolEventTypeHelper() - { - - valueList.Add(ThreadPoolEventType.EXECUTED); - valueList.Add(ThreadPoolEventType.REJECTED); - } - - public static ThreadPoolEventType From(this HystrixRollingNumberEvent @event) - { - switch (@event) - { - case HystrixRollingNumberEvent.THREAD_EXECUTION: - return ThreadPoolEventType.EXECUTED; - case HystrixRollingNumberEvent.THREAD_POOL_REJECTED: - return ThreadPoolEventType.REJECTED; - default: - throw new ArgumentOutOfRangeException("Not an event that can be converted to HystrixEventType.ThreadPool : " + @event); - } - } - - public static ThreadPoolEventType From(this HystrixEventType eventType) - { - switch (eventType) - { - case HystrixEventType.SUCCESS: - return ThreadPoolEventType.EXECUTED; - case HystrixEventType.FAILURE: - return ThreadPoolEventType.EXECUTED; - case HystrixEventType.TIMEOUT: - return ThreadPoolEventType.EXECUTED; - case HystrixEventType.BAD_REQUEST: - return ThreadPoolEventType.EXECUTED; - case HystrixEventType.THREAD_POOL_REJECTED: - return ThreadPoolEventType.REJECTED; - default: - return ThreadPoolEventType.UNKNOWN; - } - } - } - - - public enum CollapserEventType - { - BATCH_EXECUTED, - ADDED_TO_BATCH, - RESPONSE_FROM_CACHE - }; - - public static class CollapserEventTypeHelper { - - private static readonly IList valueList = new List(); - - public static IList Values - { - get { return valueList; } - } - - static CollapserEventTypeHelper() - { - - valueList.Add(CollapserEventType.BATCH_EXECUTED); - valueList.Add(CollapserEventType.ADDED_TO_BATCH); - valueList.Add(CollapserEventType.RESPONSE_FROM_CACHE); - } - public static CollapserEventType From(this HystrixRollingNumberEvent @event) - { - switch (@event) - { - case HystrixRollingNumberEvent.COLLAPSER_BATCH: - return CollapserEventType.BATCH_EXECUTED; - case HystrixRollingNumberEvent.COLLAPSER_REQUEST_BATCHED: - return CollapserEventType.ADDED_TO_BATCH; - case HystrixRollingNumberEvent.RESPONSE_FROM_CACHE: - return CollapserEventType.RESPONSE_FROM_CACHE; - default: - throw new ArgumentOutOfRangeException("Not an event that can be converted to HystrixEventType.Collapser : " + @event); - } + get { return ValueList; } } } } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixMetrics.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixMetrics.cs similarity index 75% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixMetrics.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixMetrics.cs index cb7006f..871c6af 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixMetrics.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixMetrics.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,29 +14,25 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; - namespace Steeltoe.CircuitBreaker.Hystrix { - public abstract class HystrixMetrics { - - protected internal readonly HystrixRollingNumber counter; + private readonly HystrixRollingNumber _counter; protected internal HystrixMetrics(HystrixRollingNumber counter) { - this.counter = counter; + this._counter = counter; } - public virtual long GetCumulativeCount(HystrixRollingNumberEvent @event) { - return counter.GetCumulativeSum(@event); + public virtual long GetCumulativeCount(HystrixRollingNumberEvent @event) + { + return _counter.GetCumulativeSum(@event); } - - public virtual long GetRollingCount(HystrixRollingNumberEvent @event) { - return counter.GetRollingSum(@event); + public virtual long GetRollingCount(HystrixRollingNumberEvent @event) + { + return _counter.GetRollingSum(@event); } - } - } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixRequestCache.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixRequestCache.cs similarity index 76% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixRequestCache.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixRequestCache.cs index e51eecc..065ec34 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixRequestCache.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixRequestCache.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,26 +17,26 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix { public class HystrixRequestCache { - // private static readonly Logger logger = LoggerFactory.getLogger(HystrixRequestCache.class); - // the String key must be: HystrixRequestCache.prefix + cacheKey - private readonly static ConcurrentDictionary caches = new ConcurrentDictionary(); - class HystrixRequestCacheVariable : HystrixRequestVariableDefault> + private static readonly ConcurrentDictionary Caches = new ConcurrentDictionary(); + + private class HystrixRequestCacheVariable : HystrixRequestVariableDefault> { public HystrixRequestCacheVariable() - : base(() => { + : base(() => + { return new ConcurrentDictionary(); }) { } } - private static readonly HystrixRequestCacheVariable requestVariableForCache = new HystrixRequestCacheVariable(); + private static readonly HystrixRequestCacheVariable RequestVariableForCache = new HystrixRequestCacheVariable(); + public static HystrixRequestCache GetInstance(IHystrixCommandKey key) { return GetInstance(new RequestCacheKey(key)); @@ -50,10 +49,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix private static HystrixRequestCache GetInstance(RequestCacheKey rcKey) { - return caches.GetOrAddEx(rcKey, (k) => new HystrixRequestCache(rcKey)); + return Caches.GetOrAddEx(rcKey, (k) => new HystrixRequestCache(rcKey)); } private readonly RequestCacheKey rcKey; + private HystrixRequestCache(RequestCacheKey rcKey) { this.rcKey = rcKey; @@ -65,28 +65,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix object result = null; if (key != null) { - var cacheInstance = requestVariableForCache.Value; + var cacheInstance = RequestVariableForCache.Value; /* look for the stored value */ if (cacheInstance.TryGetValue(key, out result)) + { return (T)result; + } } - return default(T); - } - internal T PutIfAbsent(string cacheKey, T f) - { - ValueCacheKey key = GetRequestCacheKey(cacheKey); - object result = null; - if (key != null) - { - var cacheInstance = requestVariableForCache.Value; - result = cacheInstance.GetOrAdd(key, f); - if (f.Equals(result)) - return default(T); - else - return (T)result; - - } return default(T); } @@ -96,12 +82,32 @@ namespace Steeltoe.CircuitBreaker.Hystrix if (key != null) { /* remove this cache key */ - object removed = null; - var cacheInstance = requestVariableForCache.Value; - cacheInstance.TryRemove(key, out removed); + var cacheInstance = RequestVariableForCache.Value; + cacheInstance.TryRemove(key, out object removed); } } + internal T PutIfAbsent(string cacheKey, T f) + { + ValueCacheKey key = GetRequestCacheKey(cacheKey); + object result = null; + if (key != null) + { + var cacheInstance = RequestVariableForCache.Value; + result = cacheInstance.GetOrAdd(key, f); + if (f.Equals(result)) + { + return default(T); + } + else + { + return (T)result; + } + } + + return default(T); + } + private ValueCacheKey GetRequestCacheKey(string cacheKey) { if (cacheKey != null) @@ -109,15 +115,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix /* create the cache key we will use to retrieve/store that include the type key prefix */ return new ValueCacheKey(rcKey, cacheKey); } + return null; } - class ValueCacheKey + private class ValueCacheKey { private readonly RequestCacheKey rvKey; private readonly string valueCacheKey; - public ValueCacheKey(RequestCacheKey rvKey, String valueCacheKey) + public ValueCacheKey(RequestCacheKey rvKey, string valueCacheKey) { this.rvKey = rvKey; this.valueCacheKey = valueCacheKey; @@ -127,41 +134,58 @@ namespace Steeltoe.CircuitBreaker.Hystrix { int prime = 31; int result = 1; - result = prime * result + ((rvKey == null) ? 0 : rvKey.GetHashCode()); - result = prime * result + ((valueCacheKey == null) ? 0 : valueCacheKey.GetHashCode()); + result = (prime * result) + ((rvKey == null) ? 0 : rvKey.GetHashCode()); + result = (prime * result) + ((valueCacheKey == null) ? 0 : valueCacheKey.GetHashCode()); return result; } - public override bool Equals(object obj) { if (this == obj) + { return true; + } + if (obj == null) + { return false; + } + if (GetType() != obj.GetType()) + { return false; + } + ValueCacheKey other = (ValueCacheKey)obj; if (rvKey == null) { if (other.rvKey != null) + { return false; + } } else if (!rvKey.Equals(other.rvKey)) + { return false; + } + if (valueCacheKey == null) { if (other.valueCacheKey != null) + { return false; + } } else if (!valueCacheKey.Equals(other.valueCacheKey)) + { return false; + } + return true; } - } - class RequestCacheKey + private class RequestCacheKey { private readonly short type; // used to differentiate between Collapser/Command if key is same between them private readonly string key; @@ -177,7 +201,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix { this.key = commandKey.Name; } - } public RequestCacheKey(IHystrixCollapserKey collapserKey) @@ -191,43 +214,54 @@ namespace Steeltoe.CircuitBreaker.Hystrix { this.key = collapserKey.Name; } - } - public override int GetHashCode() { int prime = 31; int result = 1; - result = prime * result + ((key == null) ? 0 : key.GetHashCode()); - result = prime * result + type; + result = (prime * result) + ((key == null) ? 0 : key.GetHashCode()); + result = (prime * result) + type; return result; } - public override bool Equals(object obj) { if (this == obj) + { return true; + } + if (obj == null) + { return false; + } + if (GetType() != obj.GetType()) + { return false; + } + RequestCacheKey other = (RequestCacheKey)obj; if (type != other.type) + { return false; + } + if (key == null) { if (other.key != null) + { return false; + } } else if (!key.Equals(other.key)) + { return false; + } + return true; } - } - } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixRequestLog.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixRequestLog.cs similarity index 65% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixRequestLog.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixRequestLog.cs index 4d571ec..7ac6387 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixRequestLog.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixRequestLog.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,50 +20,51 @@ using System.Collections.Generic; using System.Linq; using System.Text; - namespace Steeltoe.CircuitBreaker.Hystrix { public class HystrixRequestLog { - class HystrixRequestLogVariable : HystrixRequestVariableDefault + private class HystrixRequestLogVariable : HystrixRequestVariableDefault { public HystrixRequestLogVariable() - : base(() => new HystrixRequestLog(), (log) => { + : base(() => new HystrixRequestLog(), (log) => + { HystrixRequestEventsStream.GetInstance().Write(log.AllExecutedCommands); - - }) + }) { } } - private static readonly HystrixRequestLogVariable currentRequestLog = new HystrixRequestLogVariable(); + private static readonly HystrixRequestLogVariable RequestLog = new HystrixRequestLogVariable(); + public static HystrixRequestLog CurrentRequestLog { - get { + get + { if (HystrixRequestContext.IsCurrentThreadInitialized) - return currentRequestLog.Value; + { + return RequestLog.Value; + } else + { return null; + } } } - protected internal const int MAX_STORAGE = 1000; private BlockingCollection allExecutedCommands = new BlockingCollection(MAX_STORAGE); internal HystrixRequestLog() { - } - internal void AddExecutedCommand(IHystrixInvokableInfo command) { if (!allExecutedCommands.TryAdd(command)) { - //TODO // see RequestLog: Reduce Chance of Memory Leak https://github.com/Netflix/Hystrix/issues/53 - //logger.warn("RequestLog ignoring command after reaching limit of " + MAX_STORAGE + ". See https://github.com/Netflix/Hystrix/issues/53 for more information."); + // logger.warn("RequestLog ignoring command after reaching limit of " + MAX_STORAGE + ". See https://github.com/Netflix/Hystrix/issues/53 for more information."); } } @@ -73,11 +73,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return allExecutedCommands.ToList().AsReadOnly(); - } - } - + public string GetExecutedCommandsAsString() { try @@ -96,117 +94,126 @@ namespace Steeltoe.CircuitBreaker.Hystrix if (events.Count > 0) { events.Sort(); - //replicate functionality of Arrays.toString(events.toArray()) to append directly to existing StringBuilder + + // replicate functionality of Arrays.toString(events.toArray()) to append directly to existing StringBuilder builder.Append("["); - foreach (HystrixEventType ev in events) { - switch (ev) { + foreach (HystrixEventType ev in events) + { + switch (ev) + { case HystrixEventType.EMIT: int numEmissions = command.NumberEmissions; if (numEmissions > 1) { builder.Append(ev).Append("x").Append(numEmissions).Append(", "); - } else { + } + else + { builder.Append(ev).Append(", "); } + break; case HystrixEventType.FALLBACK_EMIT: int numFallbackEmissions = command.NumberFallbackEmissions; - if (numFallbackEmissions > 1) { + if (numFallbackEmissions > 1) + { builder.Append(ev).Append("x").Append(numFallbackEmissions).Append(", "); - } else { + } + else + { builder.Append(ev).Append(", "); } + break; + case HystrixEventType.SUCCESS: + case HystrixEventType.FAILURE: + case HystrixEventType.TIMEOUT: + case HystrixEventType.BAD_REQUEST: + case HystrixEventType.SHORT_CIRCUITED: + case HystrixEventType.THREAD_POOL_REJECTED: + case HystrixEventType.SEMAPHORE_REJECTED: + case HystrixEventType.FALLBACK_SUCCESS: + case HystrixEventType.FALLBACK_FAILURE: + case HystrixEventType.FALLBACK_REJECTION: + case HystrixEventType.FALLBACK_MISSING: + case HystrixEventType.EXCEPTION_THROWN: + case HystrixEventType.RESPONSE_FROM_CACHE: + case HystrixEventType.CANCELLED: + case HystrixEventType.COLLAPSED: default: builder.Append(ev).Append(", "); break; } } + builder[builder.Length - 2] = ']'; builder.Length = builder.Length - 1; - } else { + } + else + { builder.Append("[Executed]"); } string display = builder.ToString(); - estimatedLength += display.Length + 12; //add 12 chars to display length for appending totalExecutionTime and count below - int counter = 0; - if (aggregatedCommandsExecuted.TryGetValue(display, out counter)) + estimatedLength += display.Length + 12; // add 12 chars to display length for appending totalExecutionTime and count below + if (aggregatedCommandsExecuted.TryGetValue(display, out int counter)) { aggregatedCommandsExecuted[display] = counter + 1; - } else { + } + else + { // add it aggregatedCommandsExecuted.Add(display, 1); - } + } int executionTime = command.ExecutionTimeInMilliseconds; - if (executionTime< 0) { + if (executionTime < 0) + { // do this so we don't create negative values or subtract values executionTime = 0; } + counter = 0; - if(aggregatedCommandExecutionTime.TryGetValue(display, out counter)){ + if (aggregatedCommandExecutionTime.TryGetValue(display, out counter)) + { // add to the existing executionTime (sum of executionTimes for duplicate command displayNames) aggregatedCommandExecutionTime[display] = aggregatedCommandExecutionTime[display] + executionTime; - } else { + } + else + { // add it aggregatedCommandExecutionTime.Add(display, executionTime); } - } builder.Length = 0; builder.EnsureCapacity(estimatedLength); - foreach (string displayString in aggregatedCommandsExecuted.Keys) { - if (builder.Length > 0) { + foreach (string displayString in aggregatedCommandsExecuted.Keys) + { + if (builder.Length > 0) + { builder.Append(", "); } + builder.Append(displayString); int totalExecutionTime = aggregatedCommandExecutionTime[displayString]; builder.Append("[").Append(totalExecutionTime).Append("ms]"); int count = aggregatedCommandsExecuted[displayString]; - if (count > 1) { + if (count > 1) + { builder.Append("x").Append(count); } } + return builder.ToString(); - } catch (Exception ) { - //TODO - //logger.error("Failed to create HystrixRequestLog response header string.", e); + } + catch (Exception) + { + // logger.error("Failed to create HystrixRequestLog response header string.", e); // don't let this cause the entire app to fail so just return "Unknown" return "Unknown"; } } } - - //class HystrixRequestLogVariable: HystrixRequestVariableDefault - //{ - // public override HystrixRequestLog Value - // { - // get - // { - // if (!HystrixRequestContext.IsCurrentThreadInitialized) - // return null; - // return base.Value; - // } - // } - - // public override HystrixRequestLog InitialValue - // { - // get - // { - // return new HystrixRequestLog(); - // } - // } - - // public override void Dispose() - // { - // //write this value to the Request stream - // //HystrixRequestEventsStream.getInstance().write(value.getAllExecutedCommands()); - // //TODO: base.Dispose(); - // } - - - //} } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixThreadPoolMetrics.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixThreadPoolMetrics.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixThreadPoolMetrics.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixThreadPoolMetrics.cs index 2409fb4..93b30ec 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixThreadPoolMetrics.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixThreadPoolMetrics.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,7 +20,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; - namespace Steeltoe.CircuitBreaker.Hystrix { public class HystrixThreadPoolMetrics : HystrixMetrics @@ -31,30 +29,30 @@ namespace Steeltoe.CircuitBreaker.Hystrix private static readonly int NUMBER_THREADPOOL_EVENT_TYPES = ALL_THREADPOOL_EVENT_TYPES.Count; // String is HystrixThreadPoolKey.name() (we can't use HystrixThreadPoolKey directly as we can't guarantee it implements hashcode/equals correctly) - private static readonly ConcurrentDictionary metrics = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Metrics = new ConcurrentDictionary(); public static HystrixThreadPoolMetrics GetInstance(IHystrixThreadPoolKey key, IHystrixTaskScheduler taskScheduler, IHystrixThreadPoolOptions properties) { - return metrics.GetOrAddEx(key.Name, (k) => new HystrixThreadPoolMetrics(key, taskScheduler, properties)); + return Metrics.GetOrAddEx(key.Name, (k) => new HystrixThreadPoolMetrics(key, taskScheduler, properties)); } public static HystrixThreadPoolMetrics GetInstance(IHystrixThreadPoolKey key) { - HystrixThreadPoolMetrics result = null; - metrics.TryGetValue(key.Name, out result); + Metrics.TryGetValue(key.Name, out HystrixThreadPoolMetrics result); return result; } public static ICollection GetInstances() { List threadPoolMetrics = new List(); - foreach (HystrixThreadPoolMetrics tpm in metrics.Values) + foreach (HystrixThreadPoolMetrics tpm in Metrics.Values) { if (HasExecutedCommandsOnThread(tpm)) { threadPoolMetrics.Add(tpm); } } + return threadPoolMetrics.AsReadOnly(); } @@ -76,8 +74,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix initialCountArray[ordinal] += eventCount; } } - return initialCountArray; + return initialCountArray; }; public static Func CounterAggregator { get; } = (cumulativeEvents, bucketEventCounts) => @@ -86,13 +84,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix { cumulativeEvents[i] += bucketEventCounts[i]; } - return cumulativeEvents; + return cumulativeEvents; }; internal static void Reset() { - metrics.Clear(); + Metrics.Clear(); } private readonly IHystrixThreadPoolKey threadPoolKey; @@ -105,7 +103,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix private readonly CumulativeThreadPoolEventCounterStream cumulativeCounterStream; private readonly RollingThreadPoolMaxConcurrencyStream rollingThreadPoolMaxConcurrencyStream; - private HystrixThreadPoolMetrics(IHystrixThreadPoolKey threadPoolKey, IHystrixTaskScheduler threadPool, IHystrixThreadPoolOptions properties) : base(null) + private HystrixThreadPoolMetrics(IHystrixThreadPoolKey threadPoolKey, IHystrixTaskScheduler threadPool, IHystrixThreadPoolOptions properties) + : base(null) { this.threadPoolKey = threadPoolKey; this.threadPool = threadPool; @@ -116,25 +115,29 @@ namespace Steeltoe.CircuitBreaker.Hystrix rollingThreadPoolMaxConcurrencyStream = RollingThreadPoolMaxConcurrencyStream.GetInstance(threadPoolKey, properties); } + public static Func GetCurrentConcurrencyThunk(IHystrixThreadPoolKey threadPoolKey) + { + return () => + { + return HystrixThreadPoolMetrics.GetInstance(threadPoolKey).concurrentExecutionCount.Value; + }; + } public IHystrixTaskScheduler TaskScheduler { get { return threadPool; } } - public IHystrixThreadPoolKey ThreadPoolKey { get { return threadPoolKey; } } - public IHystrixThreadPoolOptions Properties { get { return properties; } } - public int CurrentActiveCount { get { return threadPool.CurrentActiveCount; } @@ -145,25 +148,21 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return threadPool.CurrentCompletedTaskCount; } } - public int CurrentCorePoolSize { get { return threadPool.CurrentCorePoolSize; } } - public int CurrentLargestPoolSize { get { return threadPool.CurrentLargestPoolSize; } } - public int CurrentMaximumPoolSize { get { return threadPool.CurrentMaximumPoolSize; } } - public int CurrentPoolSize { get { return threadPool.CurrentPoolSize; } @@ -174,13 +173,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return threadPool.CurrentTaskCount; } } - public int CurrentQueueSize { get { return threadPool.CurrentQueueSize; } } - public void MarkThreadExecution() { concurrentExecutionCount.IncrementAndGet(); @@ -191,7 +188,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return rollingCounterStream.GetLatestCount(ThreadPoolEventType.EXECUTED); } } - public long CumulativeCountThreadsExecuted { get { return cumulativeCounterStream.GetLatestCount(ThreadPoolEventType.EXECUTED); } @@ -202,7 +198,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return rollingCounterStream.GetLatestCount(ThreadPoolEventType.REJECTED); } } - public long CumulativeCountThreadsRejected { get { return cumulativeCounterStream.GetLatestCount(ThreadPoolEventType.REJECTED); } @@ -228,30 +223,19 @@ namespace Steeltoe.CircuitBreaker.Hystrix return rollingCounterStream.GetLatestCount(ThreadPoolEventTypeHelper.From(@event)); } - public void MarkThreadCompletion() { concurrentExecutionCount.DecrementAndGet(); } - public long RollingMaxActiveThreads { get { return rollingThreadPoolMaxConcurrencyStream.LatestRollingMax; } } - public void MarkThreadRejection() { concurrentExecutionCount.DecrementAndGet(); } - - public static Func GetCurrentConcurrencyThunk(IHystrixThreadPoolKey threadPoolKey) - { - return () => - { - return HystrixThreadPoolMetrics.GetInstance(threadPoolKey).concurrentExecutionCount.Value; - }; - } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixThreadPoolOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixThreadPoolOptions.cs similarity index 61% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixThreadPoolOptions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/HystrixThreadPoolOptions.cs index 972a0dc..c3c820d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/HystrixThreadPoolOptions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/HystrixThreadPoolOptions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,22 +18,35 @@ namespace Steeltoe.CircuitBreaker.Hystrix { public class HystrixThreadPoolOptions : HystrixBaseOptions, IHystrixThreadPoolOptions { - protected const string HYSTRIX_THREADPOOL_PREFIX = "hystrix:threadpool"; - internal const int Default_CoreSize = 10; // core size of thread pool internal const int Default_MaximumSize = 10; // maximum size of thread pool internal const int Default_KeepAliveTimeMinutes = 1; // minutes to keep a thread alive internal const int Default_MaxQueueSize = -1; // size of queue (this can't be dynamically changed so we use 'queueSizeRejectionThreshold' to artificially limit and reject) - // -1 turns it off and makes us use SynchronousQueue - internal const bool Default_AllowMaximumSizeToDivergeFromCoreSize = false; //should the maximumSize config value get read and used in configuring the threadPool - //turning this on should be a conscious decision by the user, so we default it to false - + // -1 turns it off and makes us use SynchronousQueue + internal const bool Default_AllowMaximumSizeToDivergeFromCoreSize = false; // should the maximumSize config value get read and used in configuring the threadPool + // turning this on should be a conscious decision by the user, so we default it to false internal const int Default_QueueSizeRejectionThreshold = 5; // number of items in queue internal const int Default_ThreadPoolRollingNumberStatisticalWindow = 10000; // milliseconds for rolling number internal const int Default_ThreadPoolRollingNumberStatisticalWindowBuckets = 10; // number of buckets in rolling number (10 1-second buckets) + protected const string HYSTRIX_THREADPOOL_PREFIX = "hystrix:threadpool"; + protected IHystrixThreadPoolOptions defaults; + public HystrixThreadPoolOptions(IHystrixThreadPoolKey key, IHystrixThreadPoolOptions defaults = null, IHystrixDynamicOptions dynamic = null) + : this(defaults, dynamic) + { + ThreadPoolKey = key; + AllowMaximumSizeToDivergeFromCoreSize = GetBoolean(HYSTRIX_THREADPOOL_PREFIX, key.Name, "allowMaximumSizeToDivergeFromCoreSize", Default_AllowMaximumSizeToDivergeFromCoreSize, defaults?.AllowMaximumSizeToDivergeFromCoreSize); + CoreSize = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "coreSize", Default_CoreSize, defaults?.CoreSize); + MaximumSize = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "maximumSize", Default_MaximumSize, defaults?.MaximumSize); + KeepAliveTimeMinutes = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "keepAliveTimeMinutes", Default_KeepAliveTimeMinutes, defaults?.KeepAliveTimeMinutes); + MaxQueueSize = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "maxQueueSize", Default_MaxQueueSize, defaults?.MaxQueueSize); + QueueSizeRejectionThreshold = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "queueSizeRejectionThreshold", Default_QueueSizeRejectionThreshold, defaults?.QueueSizeRejectionThreshold); + MetricsRollingStatisticalWindowInMilliseconds = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "metrics.rollingStats.timeInMilliseconds", Default_ThreadPoolRollingNumberStatisticalWindow, defaults?.MetricsRollingStatisticalWindowInMilliseconds); + MetricsRollingStatisticalWindowBuckets = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "metrics.rollingPercentile.numBuckets", Default_ThreadPoolRollingNumberStatisticalWindowBuckets, defaults?.MetricsRollingStatisticalWindowBuckets); + } + internal HystrixThreadPoolOptions(IHystrixThreadPoolOptions defaults = null, IHystrixDynamicOptions dynamic = null) : base(dynamic) { @@ -51,76 +63,22 @@ namespace Steeltoe.CircuitBreaker.Hystrix MetricsRollingStatisticalWindowBuckets = Default_ThreadPoolRollingNumberStatisticalWindowBuckets; } - public HystrixThreadPoolOptions(IHystrixThreadPoolKey key, IHystrixThreadPoolOptions defaults = null, IHystrixDynamicOptions dynamic = null) - : this(defaults, dynamic) - { - ThreadPoolKey = key; - AllowMaximumSizeToDivergeFromCoreSize = GetBoolean(HYSTRIX_THREADPOOL_PREFIX, key.Name, "allowMaximumSizeToDivergeFromCoreSize", Default_AllowMaximumSizeToDivergeFromCoreSize, defaults?.AllowMaximumSizeToDivergeFromCoreSize); - CoreSize = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "coreSize", Default_CoreSize, defaults?.CoreSize); - MaximumSize = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "maximumSize", Default_MaximumSize, defaults?.MaximumSize); - KeepAliveTimeMinutes = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "keepAliveTimeMinutes", Default_KeepAliveTimeMinutes, defaults?.KeepAliveTimeMinutes); - MaxQueueSize = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "maxQueueSize", Default_MaxQueueSize, defaults?.MaxQueueSize); - QueueSizeRejectionThreshold = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "queueSizeRejectionThreshold", Default_QueueSizeRejectionThreshold, defaults?.QueueSizeRejectionThreshold); - MetricsRollingStatisticalWindowInMilliseconds = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "metrics.rollingStats.timeInMilliseconds", Default_ThreadPoolRollingNumberStatisticalWindow, defaults?.MetricsRollingStatisticalWindowInMilliseconds); - MetricsRollingStatisticalWindowBuckets = GetInteger(HYSTRIX_THREADPOOL_PREFIX, key.Name, "metrics.rollingPercentile.numBuckets", Default_ThreadPoolRollingNumberStatisticalWindowBuckets, defaults?.MetricsRollingStatisticalWindowBuckets); - } + public IHystrixThreadPoolKey ThreadPoolKey { get; internal set; } - public IHystrixThreadPoolKey ThreadPoolKey { get; internal set;} - - /// - /// Core thread-pool size that gets passed to - /// - /// {@code HystrixProperty} public virtual int CoreSize { get; set; } - /// - /// Maximum thread-pool size that gets passed to - /// - /// {@code HystrixProperty} public virtual int MaximumSize { get; set; } - /// - /// Keep-alive time in minutes that gets passed to - /// - /// {@code HystrixProperty} public virtual int KeepAliveTimeMinutes { get; set; } - - /// - /// Max queue size that gets passed to in - /// - /// This should only affect the instantiation of a threadpool - it is not eliglible to change a queue size on the fly. - /// For that, use . - /// - /// {@code HystrixProperty} public virtual int MaxQueueSize { get; set; } - /// - /// Queue size rejection threshold is an artificial "max" size at which rejections will occur even if has not been reached. This is done because the of a - /// can not be dynamically changed and we want to support dynamically changing the queue size that affects rejections. - /// - /// This is used by when queuing a thread for execution. - /// - /// - /// - /// {@code HystrixProperty} public virtual int QueueSizeRejectionThreshold { get; set; } + public virtual bool AllowMaximumSizeToDivergeFromCoreSize { get; set; } - public virtual bool AllowMaximumSizeToDivergeFromCoreSize { get; set; } - - - /// - /// Duration of statistical rolling window in milliseconds. This is passed into inside each instance. - /// - /// {@code HystrixProperty} public virtual int MetricsRollingStatisticalWindowInMilliseconds { get; set; } - /// - /// Number of buckets the rolling statistical window is broken into. This is passed into inside each instance. - /// - /// {@code HystrixProperty} public virtual int MetricsRollingStatisticalWindowBuckets { get; set; } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ICollapsedRequest.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/ICollapsedRequest.cs similarity index 93% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/ICollapsedRequest.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/ICollapsedRequest.cs index 83bb156..d2d8570 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ICollapsedRequest.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/ICollapsedRequest.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,12 +14,10 @@ using System; - namespace Steeltoe.CircuitBreaker.Hystrix { public interface ICollapsedRequest { - RequestArgumentType Argument { get; } RequestResponseType Response { set; } @@ -28,6 +25,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix Exception Exception { set; } bool Complete { set; } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCircuitBreaker.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCircuitBreaker.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCircuitBreaker.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCircuitBreaker.cs index dc126ec..89496c5 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCircuitBreaker.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCircuitBreaker.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,14 +14,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix { - public interface IHystrixCircuitBreaker { - bool AllowRequest { get; } bool IsOpen { get; } - + void MarkSuccess(); } } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCollapserKey.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCollapserKey.cs similarity index 81% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCollapserKey.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCollapserKey.cs index f864caf..6f5e08d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCollapserKey.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCollapserKey.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,24 +14,22 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; - namespace Steeltoe.CircuitBreaker.Hystrix { - - public interface IHystrixCollapserKey : IHystrixKey { } public class HystrixCollapserKeyDefault : HystrixKeyDefault, IHystrixCollapserKey { - - internal HystrixCollapserKeyDefault(string name) : base(name) { } + internal HystrixCollapserKeyDefault(string name) + : base(name) + { + } public static IHystrixCollapserKey AsKey(string name) { - return intern.GetOrAddEx(name, k => new HystrixCollapserKeyDefault(k)); + return Intern.GetOrAddEx(name, k => new HystrixCollapserKeyDefault(k)); } - } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCollapserOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCollapserOptions.cs new file mode 100644 index 0000000..2002b29 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCollapserOptions.cs @@ -0,0 +1,41 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public interface IHystrixCollapserOptions + { + IHystrixCollapserKey CollapserKey { get; set; } + + RequestCollapserScope Scope { get; set; } + + bool RequestCacheEnabled { get; set; } + + int MaxRequestsInBatch { get; set; } + + int TimerDelayInMilliseconds { get; set; } + + int MetricsRollingStatisticalWindowInMilliseconds { get; set; } + + int MetricsRollingStatisticalWindowBuckets { get; set; } + + bool MetricsRollingPercentileEnabled { get; set; } + + int MetricsRollingPercentileWindowInMilliseconds { get; set; } + + int MetricsRollingPercentileWindowBuckets { get; set; } + + int MetricsRollingPercentileBucketSize { get; set; } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandGroupKey.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandGroupKey.cs similarity index 51% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandGroupKey.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandGroupKey.cs index 1a606d9..b0e316b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandGroupKey.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandGroupKey.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,43 +14,27 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; - namespace Steeltoe.CircuitBreaker.Hystrix { - - /// - /// A group name for a . This is used for grouping together commands such as for reporting, alerting, dashboards or team/library ownership. - /// - /// By default this will be used to define the unless a separate one is defined. - /// - /// public interface IHystrixCommandGroupKey : IHystrixKey { } - /// - /// Default implementation of the interface - /// public class HystrixCommandGroupKeyDefault : HystrixKeyDefault, IHystrixCommandGroupKey { + internal HystrixCommandGroupKeyDefault(string name) + : base(name) + { + } - internal HystrixCommandGroupKeyDefault(string name) : base(name) { } - - /// - /// Retrieve (or create) an interned IHystrixCommandGroupKey instance for a given name. - /// - /// command name - /// IHystrixCommandGroupKey instance that is interned (cached) so a given name will always retrieve the same instance. public static IHystrixCommandGroupKey AsKey(string name) { - return intern.GetOrAddEx(name, k => new HystrixCommandGroupKeyDefault(k)); + return Intern.GetOrAddEx(name, k => new HystrixCommandGroupKeyDefault(k)); } public static int GroupCount { get { return Count; } } - } - } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandKey.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandKey.cs similarity index 56% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandKey.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandKey.cs index 2e3c15c..cf1d5d0 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixCommandKey.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandKey.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,37 +16,25 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; namespace Steeltoe.CircuitBreaker.Hystrix { - - /// - /// A key to represent a for monitoring, circuit-breakers, metrics publishing, caching and other such uses. - /// public interface IHystrixCommandKey : IHystrixKey { - } - /// - /// Default implementation of the interface - /// public class HystrixCommandKeyDefault : HystrixKeyDefault, IHystrixCommandKey { - - internal HystrixCommandKeyDefault(string name) : base(name) { } + internal HystrixCommandKeyDefault(string name) + : base(name) + { + } - /// - /// Retrieve (or create) an interned IHystrixCommandKey instance for a given name. - /// - /// command name - /// IHystrixCommandKey instance that is interned (cached) so a given name will always retrieve the same instance. public static IHystrixCommandKey AsKey(string name) { - return intern.GetOrAddEx(name, k => new HystrixCommandKeyDefault(k)); + return Intern.GetOrAddEx(name, k => new HystrixCommandKeyDefault(k)); } public static int CommandCount { get { return Count; } } - } } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandOptions.cs new file mode 100644 index 0000000..df8e134 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixCommandOptions.cs @@ -0,0 +1,73 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public interface IHystrixCommandOptions + { + IHystrixCommandGroupKey GroupKey { get; set; } + + IHystrixCommandKey CommandKey { get; set; } + + IHystrixThreadPoolKey ThreadPoolKey { get; set; } + + bool CircuitBreakerEnabled { get; set; } + + int CircuitBreakerErrorThresholdPercentage { get; set; } + + bool CircuitBreakerForceClosed { get; set; } + + bool CircuitBreakerForceOpen { get; set; } + + int CircuitBreakerRequestVolumeThreshold { get; set; } + + int CircuitBreakerSleepWindowInMilliseconds { get; set; } + + int ExecutionIsolationSemaphoreMaxConcurrentRequests { get; set; } + + ExecutionIsolationStrategy ExecutionIsolationStrategy { get; set; } + + string ExecutionIsolationThreadPoolKeyOverride { get; set; } + + int ExecutionTimeoutInMilliseconds { get; set; } + + bool ExecutionTimeoutEnabled { get; set; } + + int FallbackIsolationSemaphoreMaxConcurrentRequests { get; set; } + + bool FallbackEnabled { get; set; } + + int MetricsHealthSnapshotIntervalInMilliseconds { get; set; } + + int MetricsRollingPercentileBucketSize { get; set; } + + bool MetricsRollingPercentileEnabled { get; set; } + + int MetricsRollingPercentileWindow { get; set; } + + int MetricsRollingPercentileWindowInMilliseconds { get; set; } + + int MetricsRollingPercentileWindowBuckets { get; set; } + + int MetricsRollingStatisticalWindowInMilliseconds { get; set; } + + int MetricsRollingStatisticalWindowBuckets { get; set; } + + bool RequestCacheEnabled { get; set; } + + bool RequestLogEnabled { get; set; } + + IHystrixThreadPoolOptions ThreadPoolOptions { get; set; } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixExecutable.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixExecutable.cs similarity index 87% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixExecutable.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixExecutable.cs index 6028835..0e88bb3 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixExecutable.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixExecutable.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,16 +16,17 @@ using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix { - public interface IHystrixExecutable : IHystrixObservable + public interface IHystrixExecutable : IHystrixObservable { void Execute(); - Task ExecuteAsync(); + Task ExecuteAsync(); } public interface IHystrixExecutable : IHystrixObservable { TResult Execute(); + Task ExecuteAsync(); } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixInvokable.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixInvokable.cs similarity index 83% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixInvokable.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixInvokable.cs index 4439dee..e927e92 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixInvokable.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixInvokable.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,15 +14,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { - public interface IHystrixInvokable { - } - - //public interface IHystrixInvokable - //{ - - //} - } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixInvokableInfo.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixInvokableInfo.cs similarity index 95% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixInvokableInfo.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixInvokableInfo.cs index ce3f02b..9677c50 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixInvokableInfo.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixInvokableInfo.cs @@ -1,6 +1,4 @@ - -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,14 +19,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix { public interface IHystrixInvokableInfo { - IHystrixCommandGroupKey CommandGroup { get; } IHystrixCommandKey CommandKey { get; } IHystrixThreadPoolKey ThreadPoolKey { get; } - string PublicCacheKey { get; } + string PublicCacheKey { get; } IHystrixCollapserKey OriginatingCollapserKey { get; } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixKey.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixKey.cs similarity index 75% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixKey.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixKey.cs index 5b74946..66cc34e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixKey.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixKey.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,18 +16,16 @@ using System.Collections.Concurrent; namespace Steeltoe.CircuitBreaker.Hystrix { - - public interface IHystrixKey { - string Name { get; } + string Name { get; } } public abstract class HystrixKeyDefault : IHystrixKey { - internal protected static readonly ConcurrentDictionary intern = new ConcurrentDictionary(); + protected internal static readonly ConcurrentDictionary Intern = new ConcurrentDictionary(); - internal protected readonly string name; + private readonly string name; public HystrixKeyDefault(string name) { @@ -37,7 +34,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix public string Name { - get { return name; } + get { return name; } } public override string ToString() @@ -47,9 +44,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix public static int Count { - get { return intern.Count; } + get { return Intern.Count; } } - } - } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixObservable.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixObservable.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixObservable.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixObservable.cs index d653b97..5709ac7 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixObservable.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixObservable.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,18 +15,19 @@ using System; using System.Reactive; - namespace Steeltoe.CircuitBreaker.Hystrix { public interface IHystrixObservable : IHystrixInvokable { IObservable Observe(); + IObservable ToObservable(); } public interface IHystrixObservable : IHystrixInvokable { IObservable Observe(); + IObservable ToObservable(); } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPool.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPool.cs similarity index 54% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPool.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPool.cs index 69e614d..7c41887 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPool.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPool.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,40 +16,20 @@ using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; using System; using System.Threading.Tasks; - namespace Steeltoe.CircuitBreaker.Hystrix { public interface IHystrixThreadPool : IDisposable { - IHystrixTaskScheduler GetScheduler(); TaskScheduler GetTaskScheduler(); - /// - /// Mark when a thread begins executing a command. - /// void MarkThreadExecution(); - /// - /// Mark when a thread completes executing a command. - /// void MarkThreadCompletion(); - /// - /// Mark when a command gets rejected from the threadpool - /// void MarkThreadRejection(); - /// - /// Whether the queue will allow adding an item to it. - /// - /// This allows dynamic control of the max queueSize versus whatever the actual max queueSize is so that dynamic changes can be done via property changes rather than needing an app - /// restart to adjust when commands should be rejected from queuing up. - /// - /// - /// - /// boolean whether there is space on the queue bool IsQueueSpaceAvailable { get; } bool IsShutdown { get; } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPoolKey.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPoolKey.cs similarity index 88% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPoolKey.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPoolKey.cs index 983dda4..e9129f1 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/IHystrixThreadPoolKey.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPoolKey.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +14,6 @@ using Steeltoe.CircuitBreaker.Hystrix.Util; - namespace Steeltoe.CircuitBreaker.Hystrix { /// @@ -30,7 +28,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix /// public class HystrixThreadPoolKeyDefault : HystrixKeyDefault, IHystrixThreadPoolKey { - internal HystrixThreadPoolKeyDefault(string name) : base(name) { } + internal HystrixThreadPoolKeyDefault(string name) + : base(name) + { + } /// /// Retrieve (or create) an interned IHystrixThreadPoolKey instance for a given name. @@ -39,7 +40,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix /// IHystrixThreadPoolKey instance that is interned (cached) so a given name will always retrieve the same instance. public static IHystrixThreadPoolKey AsKey(string name) { - return intern.GetOrAddEx(name, k => new HystrixThreadPoolKeyDefault(k)); + return Intern.GetOrAddEx(name, k => new HystrixThreadPoolKeyDefault(k)); } public static int ThreadPoolCount @@ -47,7 +48,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix get { return Count; } } } - - } - diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPoolOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPoolOptions.cs new file mode 100644 index 0000000..6480d6f --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/IHystrixThreadPoolOptions.cs @@ -0,0 +1,37 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public interface IHystrixThreadPoolOptions + { + IHystrixThreadPoolKey ThreadPoolKey { get; } + + int CoreSize { get; set; } + + int MaximumSize { get; set; } + + int KeepAliveTimeMinutes { get; set; } + + int MaxQueueSize { get; set; } + + int QueueSizeRejectionThreshold { get; set; } + + bool AllowMaximumSizeToDivergeFromCoreSize { get; set; } + + int MetricsRollingStatisticalWindowInMilliseconds { get; set; } + + int MetricsRollingStatisticalWindowBuckets { get; set; } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/CachedValuesHistogram.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/CachedValuesHistogram.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/CachedValuesHistogram.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/CachedValuesHistogram.cs index 053f6dd..2ad3a98 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/CachedValuesHistogram.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/CachedValuesHistogram.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,12 +11,10 @@ // 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. -// using HdrHistogram; using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public class CachedValuesHistogram @@ -54,6 +51,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric private readonly long totalCount; + public static LongHistogram GetNewHistogram() + { + LongHistogram histo = new LongHistogram(1, long.MaxValue, NUMBER_SIGNIFICANT_DIGITS); + histo.Reset(); + return histo; + } + public static CachedValuesHistogram BackedBy(LongHistogram underlying) { return new CachedValuesHistogram(underlying); @@ -100,21 +104,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric } } - /** - * Return the cached value only - * @return cached distribution mean - */ + // Return the cached value only public int GetMean() { return mean; } - /** - * Return the cached value if available. - * Otherwise, we need to synchronize access to the underlying {@link Histogram} - * @param percentile percentile of distribution - * @return value at percentile (from cache if possible) - */ + // Return the cached value if available. Otherwise, we need to synchronize access to the underlying {@link Histogram} public int GetValueAtPercentile(double percentile) { int permyriad = (int)percentile * 100; @@ -154,13 +150,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric { return totalCount; } - - public static LongHistogram GetNewHistogram() - { - LongHistogram histo = new LongHistogram(1, long.MaxValue, NUMBER_SIGNIFICANT_DIGITS); - histo.Reset(); - return histo; - } } - } diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/CommandAndCacheKey.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/CommandAndCacheKey.cs new file mode 100644 index 0000000..3bb6784 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/CommandAndCacheKey.cs @@ -0,0 +1,67 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using System; + +namespace Steeltoe.CircuitBreaker.Hystrix.Metric +{ + public class CommandAndCacheKey + { + private readonly string commandName; + private readonly string cacheKey; + + public CommandAndCacheKey(string commandName, string cacheKey) + { + this.commandName = commandName; + this.cacheKey = cacheKey; + } + + public override bool Equals(object o) + { + if (this == o) + { + return true; + } + + if (o == null || GetType() != o.GetType()) + { + return false; + } + + CommandAndCacheKey that = (CommandAndCacheKey)o; + + if (!commandName.Equals(that.commandName)) + { + return false; + } + + return cacheKey.Equals(that.cacheKey); + } + + public override int GetHashCode() + { + int result = commandName.GetHashCode(); + result = (31 * result) + cacheKey.GetHashCode(); + return result; + } + + public override string ToString() + { + return "CommandAndCacheKey{" + + "commandName='" + commandName + '\'' + + ", cacheKey='" + cacheKey + '\'' + + '}'; + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedCounterStream.cs similarity index 58% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedCounterStream.cs index d1b2789..7b62c68 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -22,19 +20,18 @@ using System.Reactive.Linq; namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { - public abstract class BucketedCounterStream where Event : IHystrixEvent + public abstract class BucketedCounterStream + where Event : IHystrixEvent { - // TODO: protected - public readonly int numBuckets; - public readonly int bucketSizeInMs; + protected readonly int numBuckets; + protected readonly int bucketSizeInMs; protected readonly IObservable bucketedStream; protected readonly AtomicReference subscription = new AtomicReference(null); private readonly Func, IObservable> reduceBucketToSummary; - //protected readonly BehaviorSubject counterSubject; + protected BucketedCounterStream(IHystrixEventStream inputEventStream, int numBuckets, int bucketSizeInMs, Func appendRawEventToBucket) { - //this.counterSubject = new BehaviorSubject(EmptyOutputValue); this.numBuckets = numBuckets; this.bucketSizeInMs = bucketSizeInMs; this.reduceBucketToSummary = (eventsObservable) => @@ -43,72 +40,31 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return result; }; - IList emptyEventCountsToStart = new List(); for (int i = 0; i < numBuckets; i++) { emptyEventCountsToStart.Add(EmptyBucketSummary); } + this.bucketedStream = Observable.Defer(() => { return inputEventStream .Observe() - .Window(TimeSpan.FromMilliseconds(bucketSizeInMs)) //bucket it by the counter window so we can emit to the next operator in time chunks, not on every OnNext + .Window(TimeSpan.FromMilliseconds(bucketSizeInMs)) // bucket it by the counter window so we can emit to the next operator in time chunks, not on every OnNext .SelectMany((b) => { return reduceBucketToSummary(b); }) - .StartWith(emptyEventCountsToStart); //start it with empty arrays to make consumer logic as generic as possible (windows are always full) + .StartWith(emptyEventCountsToStart); // start it with empty arrays to make consumer logic as generic as possible (windows are always full) }); - } public abstract Bucket EmptyBucketSummary { get; } public abstract Output EmptyOutputValue { get; } - public abstract IObservable Observe(); - //public void StartCachingStreamValuesIfUnstarted() - //{ - // if (subscription.Value == null) - // { - // //the stream is not yet started - // IDisposable candidateSubscription = Observe().Subscribe(counterSubject); - // if (subscription.CompareAndSet(null, candidateSubscription)) - // { - // //won the race to set the subscription - // } - // else - // { - // //lost the race to set the subscription, so we need to cancel this one - // candidateSubscription.Dispose(); - // } - // } - //} - - /** - * Synchronous call to retrieve the last calculated bucket without waiting for any emissions - * @return last calculated bucket - */ - //public Output Latest - //{ - // get - // { - // StartCachingStreamValuesIfUnstarted(); - // Output v = default(Output); - // if (counterSubject.TryGetValue(out v)) - // { - // return v; - // } - // else - // { - // return EmptyOutputValue; - // } - // } - //} - public void Unsubscribe() { IDisposable s = subscription.Value; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedCumulativeCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedCumulativeCounterStream.cs similarity index 70% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedCumulativeCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedCumulativeCounterStream.cs index fdd06b3..5daedff 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedCumulativeCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedCumulativeCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -22,64 +20,56 @@ using System.Reactive.Subjects; namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { - public abstract class BucketedCumulativeCounterStream : BucketedCounterStream where Event : IHystrixEvent + public abstract class BucketedCumulativeCounterStream : BucketedCounterStream + where Event : IHystrixEvent { - private IObservable sourceStream; private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false); - public readonly BehaviorSubject counterSubject; + private readonly BehaviorSubject counterSubject; + private IObservable sourceStream; protected BucketedCumulativeCounterStream(IHystrixEventStream stream, int numBuckets, int bucketSizeInMs, Func reduceCommandCompletion, Func reduceBucket) : base(stream, numBuckets, bucketSizeInMs, reduceCommandCompletion) { - this.counterSubject = new BehaviorSubject(EmptyOutputValue); this.sourceStream = bucketedStream .Scan(EmptyOutputValue, (arg1, arg2) => reduceBucket(arg1, arg2)) .Skip(numBuckets) .OnSubscribe(() => { isSourceCurrentlySubscribed.Value = true; }) .OnDispose(() => { isSourceCurrentlySubscribed.Value = false; }) - .Publish().RefCount(); //multiple subscribers should get same data - // TODO: .OnBackpressureDrop(); //if there are slow consumers, data should not buffer + .Publish().RefCount(); // multiple subscribers should get same data } - public override IObservable Observe() { return sourceStream; } - //private IDisposable connect; public void StartCachingStreamValuesIfUnstarted() { if (subscription.Value == null) { - //the stream is not yet started - //IConnectableObservable connectable = Observe() as IConnectableObservable; - //IDisposable candidateSubscription = connectable.Connect(); + // the stream is not yet started IDisposable candidateSubscription = Observe().Subscribe(this.counterSubject); if (subscription.CompareAndSet(null, candidateSubscription)) { - //won the race to set the subscription + // won the race to set the subscription } else { - //lost the race to set the subscription, so we need to cancel this one + // lost the race to set the subscription, so we need to cancel this one candidateSubscription.Dispose(); } } } - /** - * Synchronous call to retrieve the last calculated bucket without waiting for any emissions - * @return last calculated bucket - */ + // Synchronous call to retrieve the last calculated bucket without waiting for any emissions + // return last calculated bucket public Output Latest { get { StartCachingStreamValuesIfUnstarted(); - Output v = default(Output); - if (counterSubject.TryGetValue(out v)) + if (counterSubject.TryGetValue(out Output v)) { return v; } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedRollingCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedRollingCounterStream.cs similarity index 69% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedRollingCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedRollingCounterStream.cs index c733763..d181ab8 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/BucketedRollingCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/BucketedRollingCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -21,34 +19,31 @@ using System.Reactive.Linq; using System.Reactive.Observable.Aliases; using System.Reactive.Subjects; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { - public abstract class BucketedRollingCounterStream : BucketedCounterStream where Event : IHystrixEvent + public abstract class BucketedRollingCounterStream : BucketedCounterStream + where Event : IHystrixEvent { - private IObservable sourceStream; - private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false); - protected BehaviorSubject counterSubject; - //protected IDisposable counterSubscription; - + private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false); + private IObservable sourceStream; + protected BucketedRollingCounterStream(IHystrixEventStream stream, int numBuckets, int bucketSizeInMs, Func appendRawEventToBucket, Func reduceBucket) : base(stream, numBuckets, bucketSizeInMs, appendRawEventToBucket) { - - Func, IObservable> reduceWindowToSummary = (window) => { + Func, IObservable> reduceWindowToSummary = (window) => + { var result = window.Aggregate(EmptyOutputValue, (arg1, arg2) => reduceBucket(arg1, arg2)).Select(n => n); return result; }; - this.counterSubject = new BehaviorSubject(EmptyOutputValue); - this.sourceStream = bucketedStream //stream broken up into buckets + counterSubject = new BehaviorSubject(EmptyOutputValue); + sourceStream = bucketedStream // stream broken up into buckets - .Window(numBuckets, 1) //emit overlapping windows of buckets + .Window(numBuckets, 1) // emit overlapping windows of buckets + + .FlatMap((w) => + reduceWindowToSummary(w)) // convert a window of bucket-summaries into a single summary - .FlatMap((w) => - reduceWindowToSummary(w) - ) //convert a window of bucket-summaries into a single summary - .OnSubscribe(() => { isSourceCurrentlySubscribed.Value = true; @@ -57,17 +52,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { isSourceCurrentlySubscribed.Value = false; }) - .Publish().RefCount(); //multiple subscribers should get same data - // TODO: .OnBackpressureDrop(); //if there are slow consumers, data should not buffer + .Publish().RefCount(); // multiple subscribers should get same data } - public override IObservable Observe() { return sourceStream; } - internal bool IsSourceCurrentlySubscribed { get @@ -76,37 +68,30 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer } } - public void StartCachingStreamValuesIfUnstarted() { if (subscription.Value == null) { - //the stream is not yet started - + // the stream is not yet started IDisposable candidateSubscription = Observe().Subscribe(this.counterSubject); if (subscription.CompareAndSet(null, candidateSubscription)) { - } else { - //lost the race to set the subscription, so we need to cancel this one + // lost the race to set the subscription, so we need to cancel this one candidateSubscription.Dispose(); } } } - /** - * Synchronous call to retrieve the last calculated bucket without waiting for any emissions - * @return last calculated bucket - */ + // Synchronous call to retrieve the last calculated bucket without waiting for any emissions public Output Latest { get { StartCachingStreamValuesIfUnstarted(); - Output v = default(Output); - if (counterSubject.TryGetValue(out v)) + if (counterSubject.TryGetValue(out Output v)) { return v; } @@ -116,6 +101,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer } } } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeCollapserEventCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeCollapserEventCounterStream.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeCollapserEventCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeCollapserEventCounterStream.cs index 70e24dd..5e80d20 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeCollapserEventCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeCollapserEventCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,16 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class CumulativeCollapserEventCounterStream : BucketedCumulativeCounterStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static readonly int NUM_EVENT_TYPES = CollapserEventTypeHelper.Values.Count; @@ -38,19 +35,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static CumulativeCollapserEventCounterStream GetInstance(IHystrixCollapserKey collapserKey, int numBuckets, int bucketSizeInMs) { - return streams.GetOrAddEx(collapserKey.Name, (k) => new CumulativeCollapserEventCounterStream(collapserKey, numBuckets, bucketSizeInMs, HystrixCollapserMetrics.AppendEventToBucket, HystrixCollapserMetrics.BucketAggregator)); - + return Streams.GetOrAddEx(collapserKey.Name, (k) => new CumulativeCollapserEventCounterStream(collapserKey, numBuckets, bucketSizeInMs, HystrixCollapserMetrics.AppendEventToBucket, HystrixCollapserMetrics.BucketAggregator)); } public static void Reset() { - streams.Clear(); + Streams.Clear(); } private CumulativeCollapserEventCounterStream(IHystrixCollapserKey collapserKey, int numCounterBuckets, int counterBucketSizeInMs, Func appendEventToBucket, Func reduceBucket) : base(HystrixCollapserEventStream.GetInstance(collapserKey), numCounterBuckets, counterBucketSizeInMs, appendEventToBucket, reduceBucket) { - } public override long[] EmptyBucketSummary @@ -68,5 +63,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return Latest[(int)eventType]; } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeCommandEventCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeCommandEventCounterStream.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeCommandEventCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeCommandEventCounterStream.cs index 33f91f6..f482d45 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeCommandEventCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeCommandEventCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,16 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class CumulativeCommandEventCounterStream : BucketedCumulativeCounterStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static readonly int NUM_EVENT_TYPES = HystrixEventTypeHelper.Values.Count; @@ -38,13 +35,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static CumulativeCommandEventCounterStream GetInstance(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs) { - var result = streams.GetOrAddEx(commandKey.Name, (k) => new CumulativeCommandEventCounterStream(commandKey, numBuckets, bucketSizeInMs, HystrixCommandMetrics.AppendEventToBucket, HystrixCommandMetrics.BucketAggregator)); + var result = Streams.GetOrAddEx(commandKey.Name, (k) => new CumulativeCommandEventCounterStream(commandKey, numBuckets, bucketSizeInMs, HystrixCommandMetrics.AppendEventToBucket, HystrixCommandMetrics.BucketAggregator)); return result; } public static void Reset() { - streams.Clear(); + Streams.Clear(); } private CumulativeCommandEventCounterStream(IHystrixCommandKey commandKey, int numCounterBuckets, int counterBucketSizeInMs, Func reduceCommandCompletion, Func reduceBucket) @@ -57,7 +54,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer get { return new long[NUM_EVENT_TYPES]; } } - public override long[] EmptyOutputValue { get { return new long[NUM_EVENT_TYPES]; } @@ -68,5 +64,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return Latest[(int)eventType]; } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeThreadPoolEventCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeThreadPoolEventCounterStream.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeThreadPoolEventCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeThreadPoolEventCounterStream.cs index b31de68..5577775 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/CumulativeThreadPoolEventCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/CumulativeThreadPoolEventCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -22,7 +20,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class CumulativeThreadPoolEventCounterStream : BucketedCumulativeCounterStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static readonly int ALL_EVENT_TYPES_SIZE = ThreadPoolEventTypeHelper.Values.Count; @@ -37,20 +35,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static CumulativeThreadPoolEventCounterStream GetInstance(IHystrixThreadPoolKey threadPoolKey, int numBuckets, int bucketSizeInMs) { - return streams.GetOrAddEx(threadPoolKey.Name, (k) => new CumulativeThreadPoolEventCounterStream(threadPoolKey, numBuckets, bucketSizeInMs, HystrixThreadPoolMetrics.AppendEventToBucket, HystrixThreadPoolMetrics.CounterAggregator)); - + return Streams.GetOrAddEx(threadPoolKey.Name, (k) => new CumulativeThreadPoolEventCounterStream(threadPoolKey, numBuckets, bucketSizeInMs, HystrixThreadPoolMetrics.AppendEventToBucket, HystrixThreadPoolMetrics.CounterAggregator)); } public static void Reset() { - streams.Clear(); + Streams.Clear(); } - private CumulativeThreadPoolEventCounterStream(IHystrixThreadPoolKey threadPoolKey, int numCounterBuckets, int counterBucketSizeInMs, Func reduceCommandCompletion, Func reduceBucket) : base(HystrixThreadPoolCompletionStream.GetInstance(threadPoolKey), numCounterBuckets, counterBucketSizeInMs, reduceCommandCompletion, reduceBucket) { - } public override long[] EmptyBucketSummary diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/HealthCountsStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/HealthCountsStream.cs similarity index 90% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/HealthCountsStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/HealthCountsStream.cs index a72ffef..f76af77 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/HealthCountsStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/HealthCountsStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,16 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class HealthCountsStream : BucketedRollingCounterStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static readonly int NUM_EVENT_TYPES = HystrixEventTypeHelper.Values.Count; @@ -32,7 +29,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return healthCounts.Plus(bucketEventCounts); }; - public static HealthCountsStream GetInstance(IHystrixCommandKey commandKey, IHystrixCommandOptions properties) { int healthCountBucketSizeInMs = properties.MetricsHealthSnapshotIntervalInMilliseconds; @@ -40,6 +36,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { throw new ArgumentOutOfRangeException("You have set the bucket size to 0ms. Please set a positive number, so that the metric stream can be properly consumed"); } + int numHealthCountBuckets = properties.MetricsRollingStatisticalWindowInMilliseconds / healthCountBucketSizeInMs; return GetInstance(commandKey, numHealthCountBuckets, healthCountBucketSizeInMs); @@ -47,7 +44,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static HealthCountsStream GetInstance(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs) { - var result = streams.GetOrAddEx(commandKey.Name, (k) => + var result = Streams.GetOrAddEx(commandKey.Name, (k) => { var newStream = new HealthCountsStream(commandKey, numBuckets, bucketSizeInMs, HystrixCommandMetrics.AppendEventToBucket); newStream.StartCachingStreamValuesIfUnstarted(); @@ -59,19 +56,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static void Reset() { - streams.Clear(); + Streams.Clear(); } public static void RemoveByKey(IHystrixCommandKey key) { - HealthCountsStream old = null; - streams.TryRemove(key.Name, out old); + Streams.TryRemove(key.Name, out HealthCountsStream old); } private HealthCountsStream(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs, Func reduceCommandCompletion) : base(HystrixCommandCompletionStream.GetInstance(commandKey), numBuckets, bucketSizeInMs, reduceCommandCompletion, HealthCheckAccumulator) { - } public override long[] EmptyBucketSummary @@ -84,5 +79,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer get { return HealthCounts.Empty; } } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/HystrixDashboardStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/HystrixDashboardStream.cs similarity index 76% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/HystrixDashboardStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/HystrixDashboardStream.cs index a161a12..07b1be1 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/HystrixDashboardStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/HystrixDashboardStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -25,13 +23,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public class HystrixDashboardStream { private const int Default_Dashboard_IntervalInMilliseconds = 500; - readonly int delayInMs; - readonly IObservable singleSource; - readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false); - - //private static final DynamicIntProperty dataEmissionIntervalInMs = - // DynamicPropertyFactory.getInstance().getIntProperty("hystrix.stream.dashboard.intervalInMilliseconds", 500); - // TODO: + private readonly int delayInMs; + private readonly IObservable singleSource; + private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false); private HystrixDashboardStream(int delayInMs) { @@ -41,26 +35,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer .OnSubscribe(() => { isSourceCurrentlySubscribed.Value = true; }) .OnDispose(() => { isSourceCurrentlySubscribed.Value = false; }) .Publish().RefCount(); - //.onBackpressureDrop(); } - //The data emission interval is looked up on startup only - private static HystrixDashboardStream INSTANCE = + // The data emission interval is looked up on startup only + private static HystrixDashboardStream instance = new HystrixDashboardStream(Default_Dashboard_IntervalInMilliseconds); public static HystrixDashboardStream GetInstance() { - return INSTANCE; + return instance; } - internal static HystrixDashboardStream GetNonSingletonInstanceOnlyUsedInUnitTests(int delayInMs) - { - return new HystrixDashboardStream(delayInMs); - } - - /** - * Return a ref-counted stream that will only do work when at least one subscriber is present - */ + // Return a ref-counted stream that will only do work when at least one subscriber is present public IObservable Observe() { return singleSource; @@ -74,11 +60,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer } } + internal static HystrixDashboardStream GetNonSingletonInstanceOnlyUsedInUnitTests(int delayInMs) + { + return new HystrixDashboardStream(delayInMs); + } + public class DashboardData { - internal readonly ICollection commandMetrics; - internal readonly ICollection threadPoolMetrics; - internal readonly ICollection collapserMetrics; + private readonly ICollection commandMetrics; + private readonly ICollection threadPoolMetrics; + private readonly ICollection collapserMetrics; public DashboardData(ICollection commandMetrics, ICollection threadPoolMetrics, ICollection collapserMetrics) { @@ -112,5 +103,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer } } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCollapserBatchSizeDistributionStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCollapserBatchSizeDistributionStream.cs similarity index 70% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCollapserBatchSizeDistributionStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCollapserBatchSizeDistributionStream.cs index 63e868d..f102496 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCollapserBatchSizeDistributionStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCollapserBatchSizeDistributionStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using HdrHistogram; using Steeltoe.CircuitBreaker.Hystrix.Util; @@ -23,26 +21,26 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class RollingCollapserBatchSizeDistributionStream : RollingDistributionStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static Func AddValuesToBucket { get; } = (initialDistribution, @event) => + { + switch (@event.EventType) + { + case CollapserEventType.ADDED_TO_BATCH: + if (@event.Count > -1) + { + initialDistribution.RecordValue(@event.Count); + } - { - switch (@event.EventType) - { - case CollapserEventType.ADDED_TO_BATCH: - if (@event.Count > -1) - { - initialDistribution.RecordValue(@event.Count); - } - break; - default: - //do nothing - break; - } - return initialDistribution; - }; + break; + default: + // do nothing + break; + } + return initialDistribution; + }; public static RollingCollapserBatchSizeDistributionStream GetInstance(IHystrixCollapserKey collapserKey, IHystrixCollapserOptions properties) { @@ -55,20 +53,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingCollapserBatchSizeDistributionStream GetInstance(IHystrixCollapserKey collapserKey, int numBuckets, int bucketSizeInMs) { - return streams.GetOrAddEx(collapserKey.Name, (k) => new RollingCollapserBatchSizeDistributionStream(collapserKey, numBuckets, bucketSizeInMs)); - + return Streams.GetOrAddEx(collapserKey.Name, (k) => new RollingCollapserBatchSizeDistributionStream(collapserKey, numBuckets, bucketSizeInMs)); } public static void Reset() { - streams.Clear(); + Streams.Clear(); } - private RollingCollapserBatchSizeDistributionStream(IHystrixCollapserKey collapserKey, int numPercentileBuckets, int percentileBucketSizeInMs) : - base(HystrixCollapserEventStream.GetInstance(collapserKey), numPercentileBuckets, percentileBucketSizeInMs, AddValuesToBucket) + private RollingCollapserBatchSizeDistributionStream(IHystrixCollapserKey collapserKey, int numPercentileBuckets, int percentileBucketSizeInMs) + : base(HystrixCollapserEventStream.GetInstance(collapserKey), numPercentileBuckets, percentileBucketSizeInMs, AddValuesToBucket) { - } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCollapserEventCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCollapserEventCounterStream.cs similarity index 73% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCollapserEventCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCollapserEventCounterStream.cs index c49ac51..f5af62b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCollapserEventCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCollapserEventCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,20 +11,16 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { - public class RollingCollapserEventCounterStream : BucketedRollingCounterStream { - - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static readonly int NUM_EVENT_TYPES = CollapserEventTypeHelper.Values.Count; @@ -40,25 +35,25 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingCollapserEventCounterStream GetInstance(IHystrixCollapserKey collapserKey, int numBuckets, int bucketSizeInMs) { - var result = streams.GetOrAddEx(collapserKey.Name, (k) => new RollingCollapserEventCounterStream(collapserKey, numBuckets, bucketSizeInMs, HystrixCollapserMetrics.AppendEventToBucket, HystrixCollapserMetrics.BucketAggregator)); + var result = Streams.GetOrAddEx(collapserKey.Name, (k) => new RollingCollapserEventCounterStream(collapserKey, numBuckets, bucketSizeInMs, HystrixCollapserMetrics.AppendEventToBucket, HystrixCollapserMetrics.BucketAggregator)); return result; - - } public static void Reset() { - streams.Clear(); + Streams.Clear(); } - private RollingCollapserEventCounterStream(IHystrixCollapserKey collapserKey, int numCounterBuckets, int counterBucketSizeInMs, - Func appendEventToBucket, - Func reduceBucket) : - base(HystrixCollapserEventStream.GetInstance(collapserKey), numCounterBuckets, counterBucketSizeInMs, appendEventToBucket, reduceBucket) + private RollingCollapserEventCounterStream( + IHystrixCollapserKey collapserKey, + int numCounterBuckets, + int counterBucketSizeInMs, + Func appendEventToBucket, + Func reduceBucket) + : base(HystrixCollapserEventStream.GetInstance(collapserKey), numCounterBuckets, counterBucketSizeInMs, appendEventToBucket, reduceBucket) { } - public override long[] EmptyBucketSummary { get { return new long[NUM_EVENT_TYPES]; } @@ -74,8 +69,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return Latest[(int)eventType]; } } - } - - - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandEventCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandEventCounterStream.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandEventCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandEventCounterStream.cs index 8ffcc1b..43d9d21 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandEventCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandEventCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -22,7 +20,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class RollingCommandEventCounterStream : BucketedRollingCounterStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static readonly int NUM_EVENT_TYPES = HystrixEventTypeHelper.Values.Count; @@ -37,13 +35,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingCommandEventCounterStream GetInstance(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs) { - var result = streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandEventCounterStream(commandKey, numBuckets, bucketSizeInMs, HystrixCommandMetrics.AppendEventToBucket, HystrixCommandMetrics.BucketAggregator)); + var result = Streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandEventCounterStream(commandKey, numBuckets, bucketSizeInMs, HystrixCommandMetrics.AppendEventToBucket, HystrixCommandMetrics.BucketAggregator)); return result; } public static void Reset() { - streams.Clear(); + Streams.Clear(); } private RollingCommandEventCounterStream(IHystrixCommandKey commandKey, int numCounterBuckets, int counterBucketSizeInMs, Func reduceCommandCompletion, Func reduceBucket) @@ -66,5 +64,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return Latest[(int)eventType]; } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandLatencyDistributionStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandLatencyDistributionStream.cs similarity index 91% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandLatencyDistributionStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandLatencyDistributionStream.cs index daf1b6b..2e7b11d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandLatencyDistributionStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandLatencyDistributionStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,25 +11,25 @@ // 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. -// using HdrHistogram; using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class RollingCommandLatencyDistributionStream : RollingDistributionStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); + private static Func AddValuesToBucket { get; } = (initialDistribution, @event) => { if (@event.DidCommandExecute && @event.ExecutionLatency > -1) { initialDistribution.RecordValue(@event.ExecutionLatency); } + return initialDistribution; }; @@ -45,19 +44,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingCommandLatencyDistributionStream GetInstance(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs) { - var result = streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandLatencyDistributionStream(commandKey, numBuckets, bucketSizeInMs)); + var result = Streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandLatencyDistributionStream(commandKey, numBuckets, bucketSizeInMs)); return result; - } public static void Reset() { - streams.Clear(); + Streams.Clear(); } private RollingCommandLatencyDistributionStream(IHystrixCommandKey commandKey, int numPercentileBuckets, int percentileBucketSizeInMs) - : base(HystrixCommandCompletionStream.GetInstance(commandKey), numPercentileBuckets, percentileBucketSizeInMs, AddValuesToBucket) { + : base(HystrixCommandCompletionStream.GetInstance(commandKey), numPercentileBuckets, percentileBucketSizeInMs, AddValuesToBucket) + { } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandMaxConcurrencyStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandMaxConcurrencyStream.cs similarity index 90% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandMaxConcurrencyStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandMaxConcurrencyStream.cs index 35452db..8f0d9dc 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandMaxConcurrencyStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandMaxConcurrencyStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,17 +11,15 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class RollingCommandMaxConcurrencyStream : RollingConcurrencyStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); public static RollingCommandMaxConcurrencyStream GetInstance(IHystrixCommandKey commandKey, IHystrixCommandOptions properties) { @@ -35,13 +32,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingCommandMaxConcurrencyStream GetInstance(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs) { - var result = streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandMaxConcurrencyStream(commandKey, numBuckets, bucketSizeInMs)); + var result = Streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandMaxConcurrencyStream(commandKey, numBuckets, bucketSizeInMs)); return result; } public static void Reset() { - streams.Clear(); + Streams.Clear(); } private RollingCommandMaxConcurrencyStream(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs) @@ -49,5 +46,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandUserLatencyDistributionStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandUserLatencyDistributionStream.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandUserLatencyDistributionStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandUserLatencyDistributionStream.cs index 954a50b..5512cea 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingCommandUserLatencyDistributionStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingCommandUserLatencyDistributionStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,19 +11,17 @@ // 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. -// using HdrHistogram; using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class RollingCommandUserLatencyDistributionStream : RollingDistributionStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static Func AddValuesToBucket { get; } = (initialDistribution, @event) => { @@ -32,8 +29,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { initialDistribution.RecordValue(@event.TotalLatency); } - return initialDistribution; + return initialDistribution; }; public static RollingCommandUserLatencyDistributionStream GetInstance(IHystrixCommandKey commandKey, IHystrixCommandOptions properties) @@ -47,14 +44,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingCommandUserLatencyDistributionStream GetInstance(IHystrixCommandKey commandKey, int numBuckets, int bucketSizeInMs) { - var result = streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandUserLatencyDistributionStream(commandKey, numBuckets, bucketSizeInMs)); + var result = Streams.GetOrAddEx(commandKey.Name, (k) => new RollingCommandUserLatencyDistributionStream(commandKey, numBuckets, bucketSizeInMs)); return result; - } public static void Reset() { - streams.Clear(); + Streams.Clear(); } private RollingCommandUserLatencyDistributionStream(IHystrixCommandKey commandKey, int numPercentileBuckets, int percentileBucketSizeInMs) @@ -62,5 +58,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingConcurrencyStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingConcurrencyStream.cs similarity index 88% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingConcurrencyStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingConcurrencyStream.cs index 818cd2a..c32ff47 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingConcurrencyStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingConcurrencyStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -26,25 +24,21 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public abstract class RollingConcurrencyStream { - private AtomicReference rollingMaxSubscription = new AtomicReference(null); private readonly BehaviorSubject rollingMax = new BehaviorSubject(0); private readonly IObservable rollingMaxStream; + private AtomicReference rollingMaxSubscription = new AtomicReference(null); private static Func ReduceToMax { get; } = (a, b) => { return Math.Max(a, b); }; - private static Func, IObservable> ReduceStreamToMax { get; } = (observedConcurrency) => - { return observedConcurrency.Aggregate(0, (arg1, arg2) => ReduceToMax(arg1, arg2)).Select(n => n); }; - private static Func GetConcurrencyCountFromEvent { get; } = (@event) => - { return @event.CurrentConcurrency; }; @@ -65,23 +59,22 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer .StartWith(emptyRollingMaxBuckets) .Window(numBuckets, 1) .SelectMany((arg) => ReduceStreamToMax(arg)) - .Publish().RefCount(); - // TODO: .OnBackpressureDrop(); + .Publish().RefCount(); } public void StartCachingStreamValuesIfUnstarted() { if (rollingMaxSubscription.Value == null) { - //the stream is not yet started + // the stream is not yet started IDisposable candidateSubscription = Observe().Subscribe(rollingMax); if (rollingMaxSubscription.CompareAndSet(null, candidateSubscription)) { - //won the race to set the subscription + // won the race to set the subscription } else { - //lost the race to set the subscription, so we need to cancel this one + // lost the race to set the subscription, so we need to cancel this one candidateSubscription.Dispose(); } } @@ -92,8 +85,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer get { StartCachingStreamValuesIfUnstarted(); - int value = 0; - rollingMax.TryGetValue(out value); + rollingMax.TryGetValue(out int value); return value; } } @@ -113,5 +105,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer } } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingDistributionStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingDistributionStream.cs similarity index 81% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingDistributionStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingDistributionStream.cs index 8b8c5b1..17ca307 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingDistributionStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingDistributionStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using HdrHistogram; using Steeltoe.CircuitBreaker.Hystrix.Util; @@ -25,11 +23,12 @@ using System.Reactive.Subjects; namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { - public class RollingDistributionStream where Event : IHystrixEvent + public class RollingDistributionStream + where Event : IHystrixEvent { - private AtomicReference rollingDistributionSubscription = new AtomicReference(null); private readonly BehaviorSubject rollingDistribution = new BehaviorSubject(CachedValuesHistogram.BackedBy(CachedValuesHistogram.GetNewHistogram())); private readonly IObservable rollingDistributionStream; + private AtomicReference rollingDistributionSubscription = new AtomicReference(null); private static Func DistributionAggregator { get; } = (initialDistribution, distributionToAdd) => { @@ -39,13 +38,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer private static Func, IObservable> ReduceWindowToSingleDistribution { get; } = (window) => { - var result = window.Aggregate((arg1, arg2) => DistributionAggregator(arg1, arg2)).Select(n=>n); + var result = window.Aggregate((arg1, arg2) => DistributionAggregator(arg1, arg2)).Select(n => n); return result; }; - private static Func CacheHistogramValues { get; } = (histogram) => - { return CachedValuesHistogram.BackedBy(histogram); }; @@ -55,7 +52,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return windowOf2.ToList(); }; - protected RollingDistributionStream(IHystrixEventStream stream, int numBuckets, int bucketSizeInMs, Func addValuesToBucket) { List emptyDistributionsToStart = new List(); @@ -70,17 +66,15 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return result; }; - rollingDistributionStream = stream .Observe() - .Window(TimeSpan.FromMilliseconds(bucketSizeInMs)) //stream of unaggregated buckets - .SelectMany((d) => reduceBucketToSingleDistribution(d)) //stream of aggregated Histograms - .StartWith(emptyDistributionsToStart) //stream of aggregated Histograms that starts with n empty - .Window(numBuckets, 1) //windowed stream: each OnNext is a stream of n Histograms - .SelectMany((w) => ReduceWindowToSingleDistribution(w)) //reduced stream: each OnNext is a single Histogram - .Map((h) => CacheHistogramValues(h)) //convert to CachedValueHistogram (commonly-accessed values are cached) - .Publish().RefCount(); - // TODO: .OnBackpressureDrop(); + .Window(TimeSpan.FromMilliseconds(bucketSizeInMs)) // stream of unaggregated buckets + .SelectMany((d) => reduceBucketToSingleDistribution(d)) // stream of aggregated Histograms + .StartWith(emptyDistributionsToStart) // stream of aggregated Histograms that starts with n empty + .Window(numBuckets, 1) // windowed stream: each OnNext is a stream of n Histograms + .SelectMany((w) => ReduceWindowToSingleDistribution(w)) // reduced stream: each OnNext is a single Histogram + .Map((h) => CacheHistogramValues(h)) // convert to CachedValueHistogram (commonly-accessed values are cached) + .Publish().RefCount(); } public IObservable Observe() @@ -121,15 +115,15 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { if (rollingDistributionSubscription.Value == null) { - //the stream is not yet started + // the stream is not yet started IDisposable candidateSubscription = Observe().Subscribe(rollingDistribution); if (rollingDistributionSubscription.CompareAndSet(null, candidateSubscription)) { - //won the race to set the subscription + // won the race to set the subscription } else { - //lost the race to set the subscription, so we need to cancel this one + // lost the race to set the subscription, so we need to cancel this one candidateSubscription.Dispose(); } } @@ -140,8 +134,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer get { StartCachingStreamValuesIfUnstarted(); - CachedValuesHistogram value = null; - rollingDistribution.TryGetValue(out value); + rollingDistribution.TryGetValue(out CachedValuesHistogram value); return value; } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingThreadPoolEventCounterStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingThreadPoolEventCounterStream.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingThreadPoolEventCounterStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingThreadPoolEventCounterStream.cs index f5ce7af..837f3cb 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingThreadPoolEventCounterStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingThreadPoolEventCounterStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,16 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class RollingThreadPoolEventCounterStream : BucketedRollingCounterStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private static readonly int ALL_EVENT_TYPES_SIZE = ThreadPoolEventTypeHelper.Values.Count; @@ -38,12 +35,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingThreadPoolEventCounterStream GetInstance(IHystrixThreadPoolKey threadPoolKey, int numBuckets, int bucketSizeInMs) { - return streams.GetOrAddEx(threadPoolKey.Name, (k) => new RollingThreadPoolEventCounterStream(threadPoolKey, numBuckets, bucketSizeInMs, HystrixThreadPoolMetrics.AppendEventToBucket, HystrixThreadPoolMetrics.CounterAggregator)); + return Streams.GetOrAddEx(threadPoolKey.Name, (k) => new RollingThreadPoolEventCounterStream(threadPoolKey, numBuckets, bucketSizeInMs, HystrixThreadPoolMetrics.AppendEventToBucket, HystrixThreadPoolMetrics.CounterAggregator)); } public static void Reset() { - streams.Clear(); + Streams.Clear(); } private RollingThreadPoolEventCounterStream(IHystrixThreadPoolKey threadPoolKey, int numCounterBuckets, int counterBucketSizeInMs, Func reduceCommandCompletion, Func reduceBucket) @@ -66,5 +63,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer return Latest[(int)eventType]; } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingThreadPoolMaxConcurrencyStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingThreadPoolMaxConcurrencyStream.cs similarity index 85% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingThreadPoolMaxConcurrencyStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingThreadPoolMaxConcurrencyStream.cs index b9b001b..ec2034d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Consumer/RollingThreadPoolMaxConcurrencyStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Consumer/RollingThreadPoolMaxConcurrencyStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,17 +11,15 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer { public class RollingThreadPoolMaxConcurrencyStream : RollingConcurrencyStream { - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); public static RollingThreadPoolMaxConcurrencyStream GetInstance(IHystrixThreadPoolKey threadPoolKey, IHystrixThreadPoolOptions properties) { @@ -35,19 +32,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer public static RollingThreadPoolMaxConcurrencyStream GetInstance(IHystrixThreadPoolKey threadPoolKey, int numBuckets, int bucketSizeInMs) { - return streams.GetOrAddEx(threadPoolKey.Name, (k) => new RollingThreadPoolMaxConcurrencyStream(threadPoolKey, numBuckets, bucketSizeInMs)); + return Streams.GetOrAddEx(threadPoolKey.Name, (k) => new RollingThreadPoolMaxConcurrencyStream(threadPoolKey, numBuckets, bucketSizeInMs)); } public static void Reset() { - streams.Clear(); + Streams.Clear(); } public RollingThreadPoolMaxConcurrencyStream(IHystrixThreadPoolKey threadPoolKey, int numBuckets, int bucketSizeInMs) - : - base(HystrixThreadPoolStartStream.GetInstance(threadPoolKey), numBuckets, bucketSizeInMs) + : base(HystrixThreadPoolStartStream.GetInstance(threadPoolKey), numBuckets, bucketSizeInMs) { } } - } diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/ExecutionSignature.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/ExecutionSignature.cs new file mode 100644 index 0000000..aaefb10 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/ExecutionSignature.cs @@ -0,0 +1,108 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using System; + +namespace Steeltoe.CircuitBreaker.Hystrix.Metric +{ + public class ExecutionSignature + { + private readonly string commandName; + private readonly ExecutionResult.EventCounts eventCounts; + private readonly string cacheKey; + private readonly int cachedCount; + private readonly IHystrixCollapserKey collapserKey; + private readonly int collapserBatchSize; + + private ExecutionSignature(IHystrixCommandKey commandKey, ExecutionResult.EventCounts eventCounts, string cacheKey, int cachedCount, IHystrixCollapserKey collapserKey, int collapserBatchSize) + { + this.commandName = commandKey.Name; + this.eventCounts = eventCounts; + this.cacheKey = cacheKey; + this.cachedCount = cachedCount; + this.collapserKey = collapserKey; + this.collapserBatchSize = collapserBatchSize; + } + + public static ExecutionSignature From(IHystrixInvokableInfo execution) + { + return new ExecutionSignature(execution.CommandKey, execution.EventCounts, null, 0, execution.OriginatingCollapserKey, execution.NumberCollapsed); + } + + public static ExecutionSignature From(IHystrixInvokableInfo execution, string cacheKey, int cachedCount) + { + return new ExecutionSignature(execution.CommandKey, execution.EventCounts, cacheKey, cachedCount, execution.OriginatingCollapserKey, execution.NumberCollapsed); + } + + public override bool Equals(object o) + { + if (this == o) + { + return true; + } + + if (o == null || GetType() != o.GetType()) + { + return false; + } + + ExecutionSignature that = (ExecutionSignature)o; + + if (!commandName.Equals(that.commandName)) + { + return false; + } + + if (!eventCounts.Equals(that.eventCounts)) + { + return false; + } + + return !(cacheKey != null ? !cacheKey.Equals(that.cacheKey) : that.cacheKey != null); + } + + public override int GetHashCode() + { + int result = commandName.GetHashCode(); + result = (31 * result) + eventCounts.GetHashCode(); + result = (31 * result) + (cacheKey != null ? cacheKey.GetHashCode() : 0); + return result; + } + + public string CommandName + { + get { return commandName; } + } + + public ExecutionResult.EventCounts Eventcounts + { + get { return eventCounts; } + } + + public int CachedCount + { + get { return cachedCount; } + } + + public IHystrixCollapserKey CollapserKey + { + get { return collapserKey; } + } + + public int CollapserBatchSize + { + get { return collapserBatchSize; } + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCollapserEvent.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCollapserEvent.cs similarity index 96% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCollapserEvent.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCollapserEvent.cs index d6e6598..6fb7837 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCollapserEvent.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCollapserEvent.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +11,6 @@ // 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. -// - namespace Steeltoe.CircuitBreaker.Hystrix.Metric { @@ -50,11 +47,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric get { return count; } } - public override string ToString() { return "HystrixCollapserEvent[" + collapserKey.Name + "] : " + eventType + " : " + count; } } } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCollapserEventStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCollapserEventStream.cs similarity index 87% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCollapserEventStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCollapserEventStream.cs index ca65131..492b3d3 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCollapserEventStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCollapserEventStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,31 +11,30 @@ // 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. -// +using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; -using System.Reactive.Subjects; using System.Reactive.Linq; -using Steeltoe.CircuitBreaker.Hystrix.Util; +using System.Reactive.Subjects; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public class HystrixCollapserEventStream : IHystrixEventStream { + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); + private readonly IHystrixCollapserKey collapserKey; private readonly ISubject writeOnlyStream; private readonly IObservable readOnlyStream; - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); - public static HystrixCollapserEventStream GetInstance(IHystrixCollapserKey collapserKey) { - return streams.GetOrAddEx(collapserKey.Name, (k) => new HystrixCollapserEventStream(collapserKey)); + return Streams.GetOrAddEx(collapserKey.Name, (k) => new HystrixCollapserEventStream(collapserKey)); } - HystrixCollapserEventStream(IHystrixCollapserKey collapserKey) + internal HystrixCollapserEventStream(IHystrixCollapserKey collapserKey) { this.collapserKey = collapserKey; this.writeOnlyStream = Subject.Synchronize(new Subject()); @@ -45,8 +43,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric public static void Reset() { - streams.Clear(); - + Streams.Clear(); } public void Write(HystrixCollapserEvent @event) @@ -59,11 +56,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric return readOnlyStream; } - public override string ToString() { return "HystrixCollapserEventStream(" + collapserKey.Name + ")"; } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandCompletion.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandCompletion.cs similarity index 90% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandCompletion.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandCompletion.cs index 676e0f0..d820b6f 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandCompletion.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandCompletion.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; using System.Collections.Generic; @@ -25,10 +23,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric protected readonly ExecutionResult executionResult; protected readonly HystrixRequestContext requestContext; - private readonly static IList ALL_EVENT_TYPES = HystrixEventTypeHelper.Values; + private static readonly IList ALL_EVENT_TYPES = HystrixEventTypeHelper.Values; - HystrixCommandCompletion(ExecutionResult executionResult, IHystrixCommandKey commandKey, - IHystrixThreadPoolKey threadPoolKey, HystrixRequestContext requestContext) : base(commandKey, threadPoolKey) + internal HystrixCommandCompletion( + ExecutionResult executionResult, + IHystrixCommandKey commandKey, + IHystrixThreadPoolKey threadPoolKey, + HystrixRequestContext requestContext) + : base(commandKey, threadPoolKey) { this.executionResult = executionResult; this.requestContext = requestContext; @@ -102,6 +104,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric foundEventTypes.Add(eventType); } } + int i = 0; foreach (HystrixEventType eventType in foundEventTypes) { @@ -110,14 +113,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric if (eventCount > 1) { sb.Append("x").Append(eventCount); - } + if (i < foundEventTypes.Count - 1) { sb.Append(", "); } + i++; } + sb.Append("][").Append(ExecutionLatency).Append(" ms]"); return sb.ToString(); } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandCompletionStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandCompletionStream.cs similarity index 90% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandCompletionStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandCompletionStream.cs index 0d3e1ef..3d58b32 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandCompletionStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandCompletionStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,31 +11,28 @@ // 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. -// +using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; -using System.Reactive.Subjects; using System.Reactive.Linq; -using Steeltoe.CircuitBreaker.Hystrix.Util; +using System.Reactive.Subjects; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public class HystrixCommandCompletionStream : IHystrixEventStream { - private readonly IHystrixCommandKey commandKey; + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); + private readonly IHystrixCommandKey commandKey; private readonly ISubject writeOnlySubject; private readonly IObservable readOnlyStream; - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); - public static HystrixCommandCompletionStream GetInstance(IHystrixCommandKey commandKey) { - return streams.GetOrAddEx(commandKey.Name, (k) => new HystrixCommandCompletionStream(commandKey)); + return Streams.GetOrAddEx(commandKey.Name, (k) => new HystrixCommandCompletionStream(commandKey)); } - internal HystrixCommandCompletionStream(IHystrixCommandKey commandKey) { this.commandKey = commandKey; @@ -46,7 +42,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric public static void Reset() { - streams.Clear(); + Streams.Clear(); } public void Write(HystrixCommandCompletion @event) @@ -54,14 +50,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric writeOnlySubject.OnNext(@event); } - - public IObservable Observe() { return readOnlyStream; } - public override string ToString() { return "HystrixCommandCompletionStream(" + commandKey.Name + ")"; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandEvent.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandEvent.cs similarity index 82% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandEvent.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandEvent.cs index 62cb74c..595ebcf 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandEvent.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandEvent.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,23 +11,32 @@ // 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. -// -using System; +using System; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public abstract class HystrixCommandEvent : IHystrixEvent { private readonly IHystrixCommandKey commandKey; - private readonly IHystrixThreadPoolKey threadPoolKey; + private readonly IHystrixThreadPoolKey threadPoolKey; - protected HystrixCommandEvent(IHystrixCommandKey commandKey, IHystrixThreadPoolKey threadPoolKey) + protected HystrixCommandEvent(IHystrixCommandKey commandKey, IHystrixThreadPoolKey threadPoolKey) { this.commandKey = commandKey; this.threadPoolKey = threadPoolKey; } + public static Func FilterCompletionsOnly { get; } = (commandEvent) => + { + return commandEvent.IsCommandCompletion; + }; + + public static Func FilterActualExecutions { get; } = (commandEvent) => + { + return commandEvent.DidCommandExecute; + }; + public virtual IHystrixCommandKey CommandKey { get { return commandKey; } @@ -41,22 +49,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric public abstract bool IsExecutionStart { get; } - public abstract bool IsExecutedInThread { get; } + public abstract bool IsExecutedInThread { get; } public abstract bool IsResponseThreadPoolRejected { get; } public abstract bool IsCommandCompletion { get; } public abstract bool DidCommandExecute { get; } - - public static Func FilterCompletionsOnly { get; } = (commandEvent) => - { - return commandEvent.IsCommandCompletion; - }; - - public static Func FilterActualExecutions { get; } = (commandEvent) => - { - return commandEvent.DidCommandExecute; - }; } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandExecutionStarted.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandExecutionStarted.cs similarity index 96% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandExecutionStarted.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandExecutionStarted.cs index c9a33f0..6a14b5b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandExecutionStarted.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandExecutionStarted.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Metric { @@ -28,7 +26,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric this.currentConcurrency = currentConcurrency; } - public override bool IsExecutionStart { get { return true; } @@ -44,13 +41,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric get { return false; } } - public override bool IsCommandCompletion { get { return false; } } - public override bool DidCommandExecute { get { return false; } @@ -60,6 +55,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric { get { return currentConcurrency; } } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandStartStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandStartStream.cs similarity index 88% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandStartStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandStartStream.cs index ec56caf..c4ae225 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixCommandStartStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixCommandStartStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,31 +11,29 @@ // 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. -// +using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; -using System.Reactive.Subjects; using System.Reactive.Linq; -using Steeltoe.CircuitBreaker.Hystrix.Util; +using System.Reactive.Subjects; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public class HystrixCommandStartStream : IHystrixEventStream { - private readonly IHystrixCommandKey commandKey; + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); + private readonly IHystrixCommandKey commandKey; private readonly ISubject writeOnlySubject; private readonly IObservable readOnlyStream; - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); - public static HystrixCommandStartStream GetInstance(IHystrixCommandKey commandKey) { - return streams.GetOrAddEx(commandKey.Name, (k) => new HystrixCommandStartStream(commandKey)); + return Streams.GetOrAddEx(commandKey.Name, (k) => new HystrixCommandStartStream(commandKey)); } - HystrixCommandStartStream(IHystrixCommandKey commandKey) + internal HystrixCommandStartStream(IHystrixCommandKey commandKey) { this.commandKey = commandKey; this.writeOnlySubject = Subject.Synchronize(new Subject()); @@ -45,7 +42,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric public static void Reset() { - streams.Clear(); + Streams.Clear(); } public void Write(HystrixCommandExecutionStarted @event) diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixRequestEvents.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixRequestEvents.cs new file mode 100644 index 0000000..0fadd40 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixRequestEvents.cs @@ -0,0 +1,106 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using System; +using System.Collections.Generic; + +namespace Steeltoe.CircuitBreaker.Hystrix.Metric +{ + public class HystrixRequestEvents + { + private readonly ICollection executions; + + public HystrixRequestEvents(ICollection executions) + { + this.executions = executions; + } + + public ICollection Executions + { + get { return executions; } + } + + public IDictionary> ExecutionsMappedToLatencies + { + get + { + Dictionary cachingDetector = new Dictionary(); + List nonCachedExecutions = new List(executions.Count); + foreach (IHystrixInvokableInfo execution in executions) + { + if (execution.PublicCacheKey != null) + { + // eligible for caching - might be the initial, or might be from cache + CommandAndCacheKey key = new CommandAndCacheKey(execution.CommandKey.Name, execution.PublicCacheKey); + int count = -1; + if (cachingDetector.TryGetValue(key, out count)) + { + // key already seen + cachingDetector[key] = count + 1; + } + else + { + // key not seen yet + cachingDetector.Add(key, 0); + } + } + + if (!execution.IsResponseFromCache) + { + nonCachedExecutions.Add(execution); + } + } + + Dictionary> commandDeduper = new Dictionary>(); + foreach (IHystrixInvokableInfo execution in nonCachedExecutions) + { + int cachedCount = 0; + string cacheKey = execution.PublicCacheKey; + if (cacheKey != null) + { + CommandAndCacheKey key = new CommandAndCacheKey(execution.CommandKey.Name, cacheKey); + cachingDetector.TryGetValue(key, out cachedCount); + } + + ExecutionSignature signature; + if (cachedCount > 0) + { + // this has a RESPONSE_FROM_CACHE and needs to get split off + signature = ExecutionSignature.From(execution, cacheKey, cachedCount); + } + else + { + // nothing cached from this, can collapse further + signature = ExecutionSignature.From(execution); + } + + if (commandDeduper.TryGetValue(signature, out List currentLatencyList)) + { + currentLatencyList.Add(execution.ExecutionTimeInMilliseconds); + } + else + { + List newLatencyList = new List + { + execution.ExecutionTimeInMilliseconds + }; + commandDeduper.Add(signature, newLatencyList); + } + } + + return commandDeduper; + } + } + } +} \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixRequestEventsStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixRequestEventsStream.cs similarity index 85% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixRequestEventsStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixRequestEventsStream.cs index 8b1e507..bd5143d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixRequestEventsStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixRequestEventsStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,14 +11,11 @@ // 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. -// using System; using System.Collections.Generic; -using System.Linq; using System.Reactive.Linq; using System.Reactive.Subjects; -using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { @@ -28,14 +24,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric private readonly ISubject writeOnlyRequestEventsSubject; private readonly IObservable readOnlyRequestEvents; - - HystrixRequestEventsStream() + internal HystrixRequestEventsStream() { this.writeOnlyRequestEventsSubject = Subject.Synchronize(new Subject()); this.readOnlyRequestEvents = writeOnlyRequestEventsSubject.AsObservable(); - - //writeOnlyRequestEventsSubject = PublishSubject.create(); - // TODO: readOnlyRequestEvents = writeOnlyRequestEventsSubject.onBackpressureBuffer(1024); } private static readonly HystrixRequestEventsStream INSTANCE = new HystrixRequestEventsStream(); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadEventStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadEventStream.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadEventStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadEventStream.cs index 3323f30..cb667d3 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadEventStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadEventStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,29 +11,25 @@ // 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. -// using System; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Threading; -using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public class HystrixThreadEventStream { + private static readonly ThreadLocal ThreadLocalStreams = new ThreadLocal(); + private readonly long threadId; private readonly string threadName; - private readonly ISubject writeOnlyCommandStartSubject; private readonly ISubject writeOnlyCommandCompletionSubject; private readonly ISubject writeOnlyCollapserSubject; - private static readonly ThreadLocal threadLocalStreams = new ThreadLocal(); - - private static Action WriteCommandStartsToShardedStreams { get; } = (@event) => { HystrixCommandStartStream commandStartStream = HystrixCommandStartStream.GetInstance(@event.CommandKey); @@ -57,7 +52,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric HystrixThreadPoolCompletionStream threadPoolStream = HystrixThreadPoolCompletionStream.GetInstance(commandCompletion.ThreadPoolKey); threadPoolStream.Write(commandCompletion); } - }; private static Action WriteCollapserExecutionsToShardedStreams { get; } = (collapserEvent) => @@ -66,7 +60,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric collapserStream.Write(collapserEvent); }; - HystrixThreadEventStream(int id) + internal HystrixThreadEventStream(int id) { this.threadId = id; this.threadName = "hystrix-" + threadId; @@ -76,26 +70,26 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric writeOnlyCollapserSubject = Subject.Synchronize(new Subject()); writeOnlyCommandStartSubject - // TODO .onBackpressureBuffer() .Do((n) => WriteCommandStartsToShardedStreams(n)) .Subscribe(Observer.Create((v) => { })); writeOnlyCommandCompletionSubject - // TODO .onBackpressureBuffer() .Do((n) => WriteCommandCompletionsToShardedStreams(n)) .Subscribe(Observer.Create((v) => { })); writeOnlyCollapserSubject - // TODO .onBackpressureBuffer() .Do((n) => WriteCollapserExecutionsToShardedStreams(n)) .Subscribe(Observer.Create((v) => { })); } public static HystrixThreadEventStream GetInstance() { - var result = threadLocalStreams.Value; + var result = ThreadLocalStreams.Value; if (result == null) - result = threadLocalStreams.Value = new HystrixThreadEventStream(Thread.CurrentThread.ManagedThreadId); + { + result = ThreadLocalStreams.Value = new HystrixThreadEventStream(Thread.CurrentThread.ManagedThreadId); + } + return result; } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadPoolCompletionStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadPoolCompletionStream.cs similarity index 87% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadPoolCompletionStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadPoolCompletionStream.cs index 8433fb7..03ca51a 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadPoolCompletionStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadPoolCompletionStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,32 +11,29 @@ // 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. -// +using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; -using System.Reactive.Subjects; using System.Reactive.Linq; -using Steeltoe.CircuitBreaker.Hystrix.Util; +using System.Reactive.Subjects; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public class HystrixThreadPoolCompletionStream : IHystrixEventStream { + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private readonly IHystrixThreadPoolKey threadPoolKey; - private readonly ISubject writeOnlySubject; private readonly IObservable readOnlyStream; - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); - public static HystrixThreadPoolCompletionStream GetInstance(IHystrixThreadPoolKey threadPoolKey) { - return streams.GetOrAddEx(threadPoolKey.Name, (k) => new HystrixThreadPoolCompletionStream(threadPoolKey)); + return Streams.GetOrAddEx(threadPoolKey.Name, (k) => new HystrixThreadPoolCompletionStream(threadPoolKey)); } - HystrixThreadPoolCompletionStream(IHystrixThreadPoolKey threadPoolKey) + internal HystrixThreadPoolCompletionStream(IHystrixThreadPoolKey threadPoolKey) { this.threadPoolKey = threadPoolKey; this.writeOnlySubject = Subject.Synchronize(new Subject()); @@ -46,7 +42,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric public static void Reset() { - streams.Clear(); + Streams.Clear(); } public void Write(HystrixCommandCompletion @event) @@ -54,13 +50,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric writeOnlySubject.OnNext(@event); } - public IObservable Observe() { return readOnlyStream; } - public override string ToString() { return "HystrixThreadPoolCompletionStream(" + threadPoolKey.Name + ")"; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadPoolStartStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadPoolStartStream.cs similarity index 86% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadPoolStartStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadPoolStartStream.cs index a68c73a..bdc7a1f 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/HystrixThreadPoolStartStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/HystrixThreadPoolStartStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,36 +11,30 @@ // 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. -// +using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; -using System.Reactive.Subjects; using System.Reactive.Linq; - -using System.Threading.Tasks; -using Steeltoe.CircuitBreaker.Hystrix.Util; +using System.Reactive.Subjects; namespace Steeltoe.CircuitBreaker.Hystrix.Metric { public class HystrixThreadPoolStartStream : IHystrixEventStream { + private static readonly ConcurrentDictionary Streams = new ConcurrentDictionary(); private readonly IHystrixThreadPoolKey threadPoolKey; - private readonly ISubject writeOnlySubject; private readonly IObservable readOnlyStream; - private static readonly ConcurrentDictionary streams = new ConcurrentDictionary(); - public static HystrixThreadPoolStartStream GetInstance(IHystrixThreadPoolKey threadPoolKey) { - return streams.GetOrAddEx(threadPoolKey.Name, (k) => new HystrixThreadPoolStartStream(threadPoolKey)); + return Streams.GetOrAddEx(threadPoolKey.Name, (k) => new HystrixThreadPoolStartStream(threadPoolKey)); } - HystrixThreadPoolStartStream(IHystrixThreadPoolKey threadPoolKey) + internal HystrixThreadPoolStartStream(IHystrixThreadPoolKey threadPoolKey) { - this.threadPoolKey = threadPoolKey; this.writeOnlySubject = Subject.Synchronize(new Subject()); this.readOnlyStream = writeOnlySubject.AsObservable(); @@ -49,7 +42,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric public static void Reset() { - streams.Clear(); + Streams.Clear(); } public void Write(HystrixCommandExecutionStarted @event) @@ -57,7 +50,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric writeOnlySubject.OnNext(@event); } - public IObservable Observe() { return readOnlyStream; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/IHystrixEvent.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/IHystrixEvent.cs similarity index 91% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/IHystrixEvent.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/IHystrixEvent.cs index 2f27415..3d32bcf 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/IHystrixEvent.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/IHystrixEvent.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Metric { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/IHystrixEventStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/IHystrixEventStream.cs similarity index 83% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/IHystrixEventStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/IHystrixEventStream.cs index bacc5a6..9c1c114 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/IHystrixEventStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/IHystrixEventStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,14 +11,13 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric { - public interface IHystrixEventStream where E : IHystrixEvent + public interface IHystrixEventStream + where E : IHystrixEvent { IObservable Observe(); } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixCommandUtilization.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixCommandUtilization.cs similarity index 95% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixCommandUtilization.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixCommandUtilization.cs index 8138be2..808a10e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixCommandUtilization.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixCommandUtilization.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +11,6 @@ // 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. -// - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixThreadPoolUtilization.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixThreadPoolUtilization.cs similarity index 91% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixThreadPoolUtilization.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixThreadPoolUtilization.cs index 4da6e4f..48aa7e5 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixThreadPoolUtilization.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixThreadPoolUtilization.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +11,6 @@ // 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. -// - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample { @@ -38,13 +35,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample threadPoolMetrics.CurrentActiveCount, threadPoolMetrics.CurrentCorePoolSize, threadPoolMetrics.CurrentPoolSize, - threadPoolMetrics.CurrentQueueSize - ); + threadPoolMetrics.CurrentQueueSize); } public int CurrentActiveCount { - get{ return currentActiveCount; } + get { return currentActiveCount; } } public int CurrentCorePoolSize diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixUtilization.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixUtilization.cs similarity index 79% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixUtilization.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixUtilization.cs index 34a9362..2549387 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixUtilization.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixUtilization.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,11 +11,9 @@ // 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. -// using System.Collections.Generic; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample { public class HystrixUtilization @@ -24,15 +21,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample private readonly Dictionary commandUtilizationMap; private readonly Dictionary threadPoolUtilizationMap; - public HystrixUtilization(Dictionary commandUtilizationMap, + public HystrixUtilization( + Dictionary commandUtilizationMap, Dictionary threadPoolUtilizationMap) { this.commandUtilizationMap = commandUtilizationMap; this.threadPoolUtilizationMap = threadPoolUtilizationMap; } - public static HystrixUtilization From(Dictionary commandUtilizationMap, - Dictionary threadPoolUtilizationMap) + public static HystrixUtilization From( + Dictionary commandUtilizationMap, + Dictionary threadPoolUtilizationMap) { return new HystrixUtilization(commandUtilizationMap, threadPoolUtilizationMap); } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixUtilizationStream.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixUtilizationStream.cs similarity index 87% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixUtilizationStream.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixUtilizationStream.cs index e48145e..ffcb433 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Metric/Sample/HystrixUtilizationStream.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Metric/Sample/HystrixUtilizationStream.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -20,30 +18,23 @@ using System.Collections.Generic; using System.Reactive.Linq; using System.Reactive.Observable.Aliases; - namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample { public class HystrixUtilizationStream { + private const int DataEmissionIntervalInMs = 500; private readonly int intervalInMilliseconds; private readonly IObservable allUtilizationStream; private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false); - private static readonly int dataEmissionIntervalInMs = 500; - - //private static final DynamicIntProperty dataEmissionIntervalInMs = - // DynamicPropertyFactory.getInstance().getIntProperty("hystrix.stream.utilization.intervalInMilliseconds", 500); - private static Func AllUtilization { get; } = (long timestamp) => { return HystrixUtilization.From( AllCommandUtilization(timestamp), - AllThreadPoolUtilization(timestamp) - ); + AllThreadPoolUtilization(timestamp)); }; - public HystrixUtilizationStream(int intervalInMilliseconds) { this.intervalInMilliseconds = intervalInMilliseconds; @@ -52,34 +43,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample .OnSubscribe(() => { isSourceCurrentlySubscribed.Value = true; - }) .OnDispose(() => { isSourceCurrentlySubscribed.Value = false; - }) .Publish().RefCount(); - //.onBackpressureDrop(); } - //The data emission interval is looked up on startup only - private static HystrixUtilizationStream INSTANCE = - new HystrixUtilizationStream(dataEmissionIntervalInMs); + // The data emission interval is looked up on startup only + private static HystrixUtilizationStream instance = + new HystrixUtilizationStream(DataEmissionIntervalInMs); public static HystrixUtilizationStream GetInstance() { - return INSTANCE; + return instance; } - internal static HystrixUtilizationStream GetNonSingletonInstanceOnlyUsedInUnitTests(int delayInMs) - { - return new HystrixUtilizationStream(delayInMs); - } - - /** - * Return a ref-counted stream that will only do work when at least one subscriber is present - */ + // Return a ref-counted stream that will only do work when at least one subscriber is present public IObservable Observe() { return allUtilizationStream; @@ -105,6 +86,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample get { return isSourceCurrentlySubscribed.Value; } } + internal static HystrixUtilizationStream GetNonSingletonInstanceOnlyUsedInUnitTests(int delayInMs) + { + return new HystrixUtilizationStream(delayInMs); + } + private static HystrixCommandUtilization SampleCommandUtilization(HystrixCommandMetrics commandMetrics) { return HystrixCommandUtilization.Sample(commandMetrics); @@ -124,8 +110,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample IHystrixCommandKey commandKey = commandMetrics.CommandKey; commandUtilizationPerKey.Add(commandKey, SampleCommandUtilization(commandMetrics)); } - return commandUtilizationPerKey; + return commandUtilizationPerKey; }; private static Func> AllThreadPoolUtilization { get; } = @@ -137,8 +123,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample IHystrixThreadPoolKey threadPoolKey = threadPoolMetrics.ThreadPoolKey; threadPoolUtilizationPerKey.Add(threadPoolKey, SampleThreadPoolUtilization(threadPoolMetrics)); } - return threadPoolUtilizationPerKey; + return threadPoolUtilizationPerKey; }; private static Func> OnlyCommandUtilization { get; } = @@ -153,5 +139,4 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Sample return hystrixUtilization.ThreadPoolUtilizationMap; }; } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/HystrixMetricsStreamOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/HystrixMetricsStreamOptions.cs similarity index 93% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/HystrixMetricsStreamOptions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/HystrixMetricsStreamOptions.cs index b62b609..b416c6f 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/HystrixMetricsStreamOptions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/HystrixMetricsStreamOptions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,7 +17,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream public class HystrixMetricsStreamOptions { public int GatherRate { get; set; } = 500; + public int SendRate { get; set; } = 500; + public bool Validate_Certificates { get; set; } = true; } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/HystrixMetricsStreamPublisher.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/HystrixMetricsStreamPublisher.cs similarity index 83% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/HystrixMetricsStreamPublisher.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/HystrixMetricsStreamPublisher.cs index 80e8b85..c221bad 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/HystrixMetricsStreamPublisher.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/HystrixMetricsStreamPublisher.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,29 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using System.Reactive.Observable.Aliases; -using System.Reactive.Linq; -using System.Reactive.Concurrency; -using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; -using System.Collections.Generic; using Microsoft.Extensions.Logging; -using Steeltoe.Common.Discovery; using Microsoft.Extensions.Options; +using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; +using Steeltoe.Common.Discovery; +using System; +using System.Collections.Generic; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Reactive.Observable.Aliases; namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream { - public class HystrixMetricsStreamPublisher { + protected const string SPRING_CLOUD_HYSTRIX_STREAM_EXCHANGE = "spring.cloud.hystrix.stream"; + + protected IDisposable sampleSubscription; protected IObservable> observable; - internal protected IDisposable sampleSubscription; protected IDiscoveryClient discoveryClient; protected ILogger logger; protected HystrixMetricsStreamOptions options; - - protected const string SPRING_CLOUD_HYSTRIX_STREAM_EXCHANGE = "spring.cloud.hystrix.stream"; + protected internal IDisposable SampleSubscription { get => sampleSubscription; set => sampleSubscription = value; } public HystrixMetricsStreamPublisher(IOptions options, HystrixDashboardStream stream, ILogger logger = null, IDiscoveryClient discoveryClient = null) { @@ -51,38 +50,15 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream StartMetricsPublishing(); } - protected virtual bool EnsureConnection() - { - return true; - } - - protected virtual void OnNext(List jsonList) - { - - } - protected virtual void OnError(Exception error) - { - - } - protected virtual void OnComplete() - { - - } - protected virtual void Dispose() - { - - } - public virtual void StartMetricsPublishing() { logger?.LogInformation("Hystrix Metrics starting"); - sampleSubscription = observable + SampleSubscription = observable .ObserveOn(NewThreadScheduler.Default) .Subscribe( (jsonList) => { - try { if (EnsureConnection()) @@ -97,44 +73,59 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream catch (Exception e) { logger?.LogError("Error sending metrics to Hystrix dashboard, metrics streaming disabled: {0}", e); - if (sampleSubscription != null) + if (SampleSubscription != null) { - sampleSubscription.Dispose(); - sampleSubscription = null; + SampleSubscription.Dispose(); + SampleSubscription = null; } Dispose(); - } - }, (error) => { OnError(error); logger?.LogError("Error sending metrics to Hystrix dashboard, metrics streaming disabled: {0}", error); - if (sampleSubscription != null) + if (SampleSubscription != null) { - sampleSubscription.Dispose(); - sampleSubscription = null; + SampleSubscription.Dispose(); + SampleSubscription = null; } Dispose(); - }, () => { OnComplete(); logger?.LogInformation("Hystrix Metrics shutdown"); - if (sampleSubscription != null) + if (SampleSubscription != null) { - sampleSubscription.Dispose(); - sampleSubscription = null; + SampleSubscription.Dispose(); + SampleSubscription = null; } Dispose(); - }); + } + protected virtual bool EnsureConnection() + { + return true; + } + protected virtual void OnNext(List jsonList) + { + } + + protected virtual void OnError(Exception error) + { + } + + protected virtual void OnComplete() + { + } + + protected virtual void Dispose() + { } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/Serialize.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/Serialize.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/Serialize.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/Serialize.cs index e8ea121..1234bed 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/MetricsStream/Serialize.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/MetricsStream/Serialize.cs @@ -1,12 +1,26 @@ -using Newtonsoft.Json; -using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; -using System; -using Steeltoe.CircuitBreaker.Hystrix.Serial; -using System.IO; -using Steeltoe.CircuitBreaker.Hystrix.Util; +// Copyright 2017 the original author or authors. +// +// 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. + +using Newtonsoft.Json; using Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker; -using System.Collections.Generic; +using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer; +using Steeltoe.CircuitBreaker.Hystrix.Serial; +using Steeltoe.CircuitBreaker.Hystrix.Util; using Steeltoe.Common.Discovery; +using System; +using System.Collections.Generic; +using System.IO; namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream { @@ -20,16 +34,20 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream return jsonList; } - private static string contextId = Guid.NewGuid().ToString(); + private static void WriteLocalService(JsonTextWriter writer, IServiceInstance localService) { writer.WriteObjectFieldStart("origin"); writer.WriteStringField("host", localService?.Host); if (localService == null) + { writer.WriteIntegerField("port", -1); + } else + { writer.WriteIntegerField("port", localService.Port); + } writer.WriteStringField("serviceId", localService?.ServiceId); writer.WriteStringField("id", contextId); @@ -55,6 +73,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream writer.WriteEndObject(); writer.WriteEndObject(); } + jsonList.Add(sw.ToString()); } } @@ -69,7 +88,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream { try { - var localService = discoveryClient?.GetLocalServiceInstance(); foreach (HystrixCommandMetrics commandMetrics in data.CommandMetrics) @@ -85,6 +103,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream writer.WriteEndObject(); writer.WriteEndObject(); } + jsonList.Add(sw.ToString()); } } @@ -119,10 +138,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream writer.WriteIntegerField("propertyValue_metricsRollingStatisticalWindowInMilliseconds", threadPoolMetrics.Properties.MetricsRollingStatisticalWindowInMilliseconds); writer.WriteLongField("reportingHosts", 1); // this will get summed across all instances in a cluster - } - private static void WriteCommandMetrics(JsonTextWriter writer, HystrixCommandMetrics commandMetrics, IServiceInstance localService) { IHystrixCommandKey key = commandMetrics.CommandKey; @@ -131,9 +148,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream writer.WriteStringField("type", "HystrixCommand"); if (localService != null) + { writer.WriteStringField("name", localService.ServiceId + "." + key.Name); + } else + { writer.WriteStringField("name", key.Name); + } writer.WriteStringField("group", commandMetrics.CommandGroup.Name); writer.WriteLongField("currentTime", Time.CurrentTimeMillisJava); @@ -148,6 +169,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream { writer.WriteBooleanField("isCircuitBreakerOpen", circuitBreaker.IsOpen); } + HealthCounts healthCounts = commandMetrics.Healthcounts; writer.WriteIntegerField("errorPercentage", healthCounts.ErrorPercentage); writer.WriteLongField("errorCount", healthCounts.ErrorCount); @@ -182,7 +204,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream writer.WriteIntegerField("99.5", commandMetrics.GetExecutionTimePercentile(99.5)); writer.WriteIntegerField("100", commandMetrics.GetExecutionTimePercentile(100)); writer.WriteEndObject(); - // + writer.WriteIntegerField("latencyTotal_mean", commandMetrics.TotalTimeMean); writer.WriteObjectFieldStart("latencyTotal"); writer.WriteIntegerField("0", commandMetrics.GetTotalTimePercentile(0)); @@ -220,4 +242,3 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream } } } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Properties/AssemblyInfo.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Properties/AssemblyInfo.cs similarity index 57% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Properties/AssemblyInfo.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Properties/AssemblyInfo.cs index d7dc480..97dc882 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Properties/AssemblyInfo.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Properties/AssemblyInfo.cs @@ -1,4 +1,18 @@ -using System.Reflection; +// Copyright 2017 the original author or authors. +// +// 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. + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -7,7 +21,7 @@ using System.Runtime.InteropServices; // associated with an assembly. [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Steeltoe.CircuitBreaker.Hystrix.Core")] +[assembly: AssemblyProduct("Steeltoe.CircuitBreaker.HystrixBase")] [assembly: AssemblyTrademark("")] // Setting ComVisible to false makes the types in this assembly not visible @@ -15,7 +29,7 @@ using System.Runtime.InteropServices; // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -[assembly: InternalsVisibleTo("Steeltoe.CircuitBreaker.Hystrix.Core.Test")] +[assembly: InternalsVisibleTo("Steeltoe.CircuitBreaker.HystrixBase.Test")] [assembly: InternalsVisibleTo("Steeltoe.CircuitBreaker.HystrixCore.Test")] [assembly: InternalsVisibleTo("Steeltoe.CircuitBreaker.HystrixAutofac.Test")] [assembly: InternalsVisibleTo("Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test")] diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/README.md b/src/Steeltoe.CircuitBreaker.HystrixBase/README.md similarity index 100% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/README.md rename to src/Steeltoe.CircuitBreaker.HystrixBase/README.md diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixConfiguration.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixConfiguration.cs similarity index 99% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixConfiguration.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixConfiguration.cs index 1bc081d..4fd8217 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixConfiguration.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixConfiguration.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,14 +11,12 @@ // 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. -// using Newtonsoft.Json; using Steeltoe.CircuitBreaker.Hystrix.Config; using System; using System.IO; - namespace Steeltoe.CircuitBreaker.Hystrix.Serial { public static class SerialHystrixConfiguration @@ -32,12 +29,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial { SerializeConfiguration(writer, config); } + return sw.ToString(); } } + private static void SerializeConfiguration(JsonTextWriter writer, HystrixConfiguration config) { - writer.WriteStartObject(); writer.WriteStringField("type", "HystrixConfig"); writer.WriteObjectFieldStart("commands"); @@ -46,8 +44,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial IHystrixCommandKey key = entry.Key; HystrixCommandConfiguration commandConfig = entry.Value; WriteCommandConfigJson(writer, key, commandConfig); - } + writer.WriteEndObject(); writer.WriteObjectFieldStart("threadpools"); @@ -57,6 +55,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial HystrixThreadPoolConfiguration threadPoolConfig = entry.Value; WriteThreadPoolConfigJson(writer, threadPoolKey, threadPoolConfig); } + writer.WriteEndObject(); writer.WriteObjectFieldStart("collapsers"); @@ -66,10 +65,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial HystrixCollapserConfiguration collapserConfig = entry.Value; WriteCollapserConfigJson(writer, collapserKey, collapserConfig); } - writer.WriteEndObject(); - writer.WriteEndObject(); + writer.WriteEndObject(); + writer.WriteEndObject(); } + private static void WriteCommandConfigJson(JsonTextWriter json, IHystrixCommandKey key, HystrixCommandConfiguration commandConfig) { json.WriteObjectFieldStart(key.Name); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixDashboardData.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixDashboardData.cs similarity index 85% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixDashboardData.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixDashboardData.cs index b56486f..dab73a2 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixDashboardData.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixDashboardData.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Newtonsoft.Json; using Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker; @@ -22,7 +20,6 @@ using System; using System.Collections.Generic; using System.IO; - namespace Steeltoe.CircuitBreaker.Hystrix.Serial { public static class SerialHystrixDashboardData @@ -35,10 +32,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial { WriteDashboardData(writer, data); } + return sw.ToString(); } - } + public static List ToMultipleJsonStrings(HystrixDashboardStream.DashboardData dashboardData) { List jsonStrings = new List(); @@ -61,72 +59,65 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial return jsonStrings; } - public static String ToJsonString(HystrixCommandMetrics commandMetrics) + public static string ToJsonString(HystrixCommandMetrics commandMetrics) { using (StringWriter sw = new StringWriter()) { using (JsonTextWriter writer = new JsonTextWriter(sw)) { WriteCommandMetrics(writer, commandMetrics); - return sw.ToString(); } - } } - public static String ToJsonString(HystrixThreadPoolMetrics threadPoolMetrics) + public static string ToJsonString(HystrixThreadPoolMetrics threadPoolMetrics) { using (StringWriter sw = new StringWriter()) { using (JsonTextWriter writer = new JsonTextWriter(sw)) { WriteThreadPoolMetrics(writer, threadPoolMetrics); - return sw.ToString(); } - } } - public static String ToJsonString(HystrixCollapserMetrics collapserMetrics) + public static string ToJsonString(HystrixCollapserMetrics collapserMetrics) { using (StringWriter sw = new StringWriter()) { using (JsonTextWriter writer = new JsonTextWriter(sw)) { WriteCollapserMetrics(writer, collapserMetrics); - return sw.ToString(); } - } } - private static void WriteDashboardData(JsonTextWriter writer, HystrixDashboardStream.DashboardData data) { try { writer.WriteStartArray(); - - foreach(HystrixCommandMetrics commandMetrics in data.CommandMetrics) + foreach (HystrixCommandMetrics commandMetrics in data.CommandMetrics) { WriteCommandMetrics(writer, commandMetrics); } + foreach (HystrixThreadPoolMetrics threadPoolMetrics in data.ThreadPoolMetrics) { - WriteThreadPoolMetrics(writer, threadPoolMetrics ); + WriteThreadPoolMetrics(writer, threadPoolMetrics); } - foreach (HystrixCollapserMetrics collapserMetrics in data.CollapserMetrics) + + foreach (HystrixCollapserMetrics collapserMetrics in data.CollapserMetrics) { WriteCollapserMetrics(writer, collapserMetrics); } writer.WriteEndArray(); - - - } catch(Exception) + } + catch (Exception) { // Log } @@ -162,6 +153,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial writer.WriteEndObject(); } + private static void WriteCollapserMetrics(JsonTextWriter writer, HystrixCollapserMetrics collapserMetrics) { IHystrixCollapserKey key = collapserMetrics.CollapserKey; @@ -178,7 +170,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial writer.WriteLongField("rollingCountResponsesFromCache", collapserMetrics.GetRollingCount(CollapserEventType.RESPONSE_FROM_CACHE)); - // batch size percentiles writer.WriteIntegerField("batchSize_mean", collapserMetrics.BatchSizeMean); writer.WriteObjectFieldStart("batchSize"); @@ -192,7 +183,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial writer.WriteIntegerField("100", collapserMetrics.GetBatchSizePercentile(100)); writer.WriteEndObject(); - writer.WriteBooleanField("propertyValue_requestCacheEnabled", collapserMetrics.Properties.RequestCacheEnabled); writer.WriteIntegerField("propertyValue_maxRequestsInBatch", collapserMetrics.Properties.MaxRequestsInBatch); writer.WriteIntegerField("propertyValue_timerDelayInMilliseconds", collapserMetrics.Properties.TimerDelayInMilliseconds); @@ -223,28 +213,29 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial { writer.WriteBooleanField("isCircuitBreakerOpen", circuitBreaker.IsOpen); } + HealthCounts healthCounts = commandMetrics.Healthcounts; writer.WriteIntegerField("errorPercentage", healthCounts.ErrorPercentage); writer.WriteLongField("errorCount", healthCounts.ErrorCount); writer.WriteLongField("requestCount", healthCounts.TotalRequests); // rolling counters - writer.WriteLongField( "rollingCountBadRequests", commandMetrics.GetRollingCount(HystrixEventType.BAD_REQUEST)); + writer.WriteLongField("rollingCountBadRequests", commandMetrics.GetRollingCount(HystrixEventType.BAD_REQUEST)); writer.WriteLongField("rollingCountCollapsedRequests", commandMetrics.GetRollingCount(HystrixEventType.COLLAPSED)); - writer.WriteLongField( "rollingCountEmit", commandMetrics.GetRollingCount(HystrixEventType.EMIT)); - writer.WriteLongField( "rollingCountExceptionsThrown", commandMetrics.GetRollingCount(HystrixEventType.EXCEPTION_THROWN)); - writer.WriteLongField( "rollingCountFailure", commandMetrics.GetRollingCount(HystrixEventType.FAILURE)); - writer.WriteLongField( "rollingCountFallbackEmit", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_EMIT)); - writer.WriteLongField( "rollingCountFallbackFailure", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_FAILURE)); - writer.WriteLongField( "rollingCountFallbackMissing", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_MISSING)); - writer.WriteLongField( "rollingCountFallbackRejection", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_REJECTION)); - writer.WriteLongField( "rollingCountFallbackSuccess", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_SUCCESS)); - writer.WriteLongField( "rollingCountResponsesFromCache", commandMetrics.GetRollingCount(HystrixEventType.RESPONSE_FROM_CACHE)); - writer.WriteLongField( "rollingCountSemaphoreRejected", commandMetrics.GetRollingCount(HystrixEventType.SEMAPHORE_REJECTED)); - writer.WriteLongField( "rollingCountShortCircuited", commandMetrics.GetRollingCount(HystrixEventType.SHORT_CIRCUITED)); - writer.WriteLongField( "rollingCountSuccess", commandMetrics.GetRollingCount(HystrixEventType.SUCCESS)); - writer.WriteLongField( "rollingCountThreadPoolRejected", commandMetrics.GetRollingCount(HystrixEventType.THREAD_POOL_REJECTED)); - writer.WriteLongField( "rollingCountTimeout", commandMetrics.GetRollingCount(HystrixEventType.TIMEOUT)); + writer.WriteLongField("rollingCountEmit", commandMetrics.GetRollingCount(HystrixEventType.EMIT)); + writer.WriteLongField("rollingCountExceptionsThrown", commandMetrics.GetRollingCount(HystrixEventType.EXCEPTION_THROWN)); + writer.WriteLongField("rollingCountFailure", commandMetrics.GetRollingCount(HystrixEventType.FAILURE)); + writer.WriteLongField("rollingCountFallbackEmit", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_EMIT)); + writer.WriteLongField("rollingCountFallbackFailure", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_FAILURE)); + writer.WriteLongField("rollingCountFallbackMissing", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_MISSING)); + writer.WriteLongField("rollingCountFallbackRejection", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_REJECTION)); + writer.WriteLongField("rollingCountFallbackSuccess", commandMetrics.GetRollingCount(HystrixEventType.FALLBACK_SUCCESS)); + writer.WriteLongField("rollingCountResponsesFromCache", commandMetrics.GetRollingCount(HystrixEventType.RESPONSE_FROM_CACHE)); + writer.WriteLongField("rollingCountSemaphoreRejected", commandMetrics.GetRollingCount(HystrixEventType.SEMAPHORE_REJECTED)); + writer.WriteLongField("rollingCountShortCircuited", commandMetrics.GetRollingCount(HystrixEventType.SHORT_CIRCUITED)); + writer.WriteLongField("rollingCountSuccess", commandMetrics.GetRollingCount(HystrixEventType.SUCCESS)); + writer.WriteLongField("rollingCountThreadPoolRejected", commandMetrics.GetRollingCount(HystrixEventType.THREAD_POOL_REJECTED)); + writer.WriteLongField("rollingCountTimeout", commandMetrics.GetRollingCount(HystrixEventType.TIMEOUT)); writer.WriteIntegerField("currentConcurrentExecutionCount", commandMetrics.CurrentConcurrentExecutionCount); writer.WriteLongField("rollingMaxConcurrentExecutionCount", commandMetrics.RollingMaxConcurrentExecutions); @@ -262,7 +253,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial writer.WriteIntegerField("99.5", commandMetrics.GetExecutionTimePercentile(99.5)); writer.WriteIntegerField("100", commandMetrics.GetExecutionTimePercentile(100)); writer.WriteEndObject(); - // writer.WriteIntegerField("latencyTotal_mean", commandMetrics.TotalTimeMean); writer.WriteObjectFieldStart("latencyTotal"); writer.WriteIntegerField("0", commandMetrics.GetTotalTimePercentile(0)); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixRequestEvents.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixRequestEvents.cs similarity index 86% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixRequestEvents.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixRequestEvents.cs index aad98d1..f0a99d7 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixRequestEvents.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixRequestEvents.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,14 +11,12 @@ // 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. -// using Newtonsoft.Json; using Steeltoe.CircuitBreaker.Hystrix.Metric; using System.Collections.Generic; using System.IO; - namespace Steeltoe.CircuitBreaker.Hystrix.Serial { public static class SerialHystrixRequestEvents @@ -32,13 +29,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial { SerializeRequestEvents(writer, requestEvents); } + return sw.ToString(); } } private static void SerializeRequestEvents(JsonTextWriter json, HystrixRequestEvents requestEvents) { - json.WriteStartArray(); foreach (var entry in requestEvents.ExecutionsMappedToLatencies) @@ -47,44 +44,57 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial } json.WriteEndArray(); - } + private static void ConvertExecutionToJson(JsonTextWriter json, ExecutionSignature executionSignature, List latencies) { json.WriteStartObject(); json.WriteStringField("name", executionSignature.CommandName); json.WriteArrayFieldStart("events"); ExecutionResult.EventCounts eventCounts = executionSignature.Eventcounts; - foreach (HystrixEventType eventType in HystrixEventTypeHelper.Values) { - if (!eventType.Equals(HystrixEventType.COLLAPSED)) { - if (eventCounts.Contains(eventType)) { + foreach (HystrixEventType eventType in HystrixEventTypeHelper.Values) + { + if (!eventType.Equals(HystrixEventType.COLLAPSED)) + { + if (eventCounts.Contains(eventType)) + { int eventCount = eventCounts.GetCount(eventType); - if (eventCount > 1) { + if (eventCount > 1) + { json.WriteStartObject(); json.WriteStringField("name", eventType.ToString()); json.WriteIntegerField("count", eventCount); json.WriteEndObject(); - } else { + } + else + { json.WriteValue(eventType.ToString()); } } } } + json.WriteEndArray(); json.WriteArrayFieldStart("latencies"); - foreach (int latency in latencies) { + foreach (int latency in latencies) + { json.WriteValue(latency); } + json.WriteEndArray(); - if (executionSignature.CachedCount > 0) { + if (executionSignature.CachedCount > 0) + { json.WriteIntegerField("cached", executionSignature.CachedCount); } - if (executionSignature.Eventcounts.Contains(HystrixEventType.COLLAPSED)) { + + if (executionSignature.Eventcounts.Contains(HystrixEventType.COLLAPSED)) + { json.WriteObjectFieldStart("collapsed"); json.WriteStringField("name", executionSignature.CollapserKey.Name); json.WriteIntegerField("count", executionSignature.CollapserBatchSize); json.WriteEndObject(); } + json.WriteEndObject(); } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixUtilization.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixUtilization.cs similarity index 78% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixUtilization.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixUtilization.cs index 2a3dec6..ab98e73 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerialHystrixUtilization.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerialHystrixUtilization.cs @@ -1,17 +1,27 @@ -using Newtonsoft.Json; +// Copyright 2017 the original author or authors. +// +// 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. + +using Newtonsoft.Json; using Steeltoe.CircuitBreaker.Hystrix.Metric.Sample; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix.Serial { public static class SerialHystrixUtilization { - public static String ToJsonString(HystrixUtilization utilization) + public static string ToJsonString(HystrixUtilization utilization) { using (StringWriter sw = new StringWriter()) { @@ -19,15 +29,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial { SerializeUtilization(writer, utilization); } + return sw.ToString(); } - - } private static void SerializeUtilization(JsonTextWriter json, HystrixUtilization utilization) { - json.WriteStartObject(); json.WriteStringField("type", "HystrixUtilization"); json.WriteObjectFieldStart("commands"); @@ -36,8 +44,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial IHystrixCommandKey key = entry.Key; HystrixCommandUtilization commandUtilization = entry.Value; WriteCommandUtilizationJson(json, key, commandUtilization); - } + json.WriteEndObject(); json.WriteObjectFieldStart("threadpools"); @@ -47,9 +55,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial HystrixThreadPoolUtilization threadPoolUtilization = entry.Value; WriteThreadPoolUtilizationJson(json, threadPoolKey, threadPoolUtilization); } + json.WriteEndObject(); json.WriteEndObject(); } + private static void WriteCommandUtilizationJson(JsonTextWriter json, IHystrixCommandKey key, HystrixCommandUtilization utilization) { json.WriteObjectFieldStart(key.Name); @@ -66,6 +76,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial json.WriteIntegerField("poolSize", utilization.CurrentPoolSize); json.WriteEndObject(); } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerializationExtensions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerializationExtensions.cs similarity index 97% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerializationExtensions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerializationExtensions.cs index 7217fbf..2f318ba 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Serial/SerializationExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Serial/SerializationExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,11 +11,9 @@ // 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. -// using Newtonsoft.Json; - namespace Steeltoe.CircuitBreaker.Hystrix.Serial { public static class SerializationExtensions @@ -26,26 +23,31 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Serial writer.WritePropertyName(fieldName); writer.WriteValue(fieldValue); } + public static void WriteLongField(this JsonTextWriter writer, string fieldName, long fieldValue) { writer.WritePropertyName(fieldName); writer.WriteValue(fieldValue); } + public static void WriteBooleanField(this JsonTextWriter writer, string fieldName, bool fieldValue) { writer.WritePropertyName(fieldName); writer.WriteValue(fieldValue); } + public static void WriteIntegerField(this JsonTextWriter writer, string fieldName, int fieldValue) { writer.WritePropertyName(fieldName); writer.WriteValue(fieldValue); } + public static void WriteObjectFieldStart(this JsonTextWriter writer, string fieldName) { writer.WritePropertyName(fieldName); writer.WriteStartObject(); } + public static void WriteArrayFieldStart(this JsonTextWriter writer, string fieldName) { writer.WritePropertyName(fieldName); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Steeltoe.CircuitBreaker.Hystrix.Core.csproj b/src/Steeltoe.CircuitBreaker.HystrixBase/Steeltoe.CircuitBreaker.HystrixBase.csproj similarity index 71% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Steeltoe.CircuitBreaker.Hystrix.Core.csproj rename to src/Steeltoe.CircuitBreaker.HystrixBase/Steeltoe.CircuitBreaker.HystrixBase.csproj index 0c96a24..30e3ce6 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Steeltoe.CircuitBreaker.Hystrix.Core.csproj +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Steeltoe.CircuitBreaker.HystrixBase.csproj @@ -3,13 +3,13 @@ - Steeltoe Neflix Hystrix Client + Steeltoe Neflix Hystrix Client - Base Package Pivotal,dtillman $(SteeltoeVersion) $(VersionSuffix) netstandard2.0 - Steeltoe.CircuitBreaker.Hystrix.Core - Steeltoe.CircuitBreaker.Hystrix.Core + Steeltoe.CircuitBreaker.HystrixBase + Steeltoe.CircuitBreaker.HystrixBase Spring Cloud;Netflix;Hystrix Client;Circuit Breaker http://steeltoe.io/images/transparent.png http://steeltoe.io @@ -28,11 +28,17 @@ + + All + - \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixConcurrencyStrategy.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixConcurrencyStrategy.cs similarity index 89% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixConcurrencyStrategy.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixConcurrencyStrategy.cs index e9763f0..3d00463 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixConcurrencyStrategy.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixConcurrencyStrategy.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,11 +11,9 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { public class HystrixConcurrencyStrategy @@ -24,9 +21,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency public virtual HystrixTaskScheduler GetTaskScheduler(IHystrixThreadPoolOptions options) { if (options.MaxQueueSize < 0) + { return new HystrixSyncTaskScheduler(options); - else + } + else + { return new HystrixQueuedTaskScheduler(options); + } } public virtual IHystrixRequestVariable GetRequestVariable(T value) @@ -34,7 +35,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency return new HystrixRequestVariableDefault(value); } - public virtual IHystrixRequestVariable GetRequestVariable(Func valueFactory, Action disposeAction) + public virtual IHystrixRequestVariable GetRequestVariable(Func valueFactory, Action disposeAction) { return new HystrixRequestVariableDefault(valueFactory, disposeAction); } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixConcurrencyStrategyDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixConcurrencyStrategyDefault.cs similarity index 67% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixConcurrencyStrategyDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixConcurrencyStrategyDefault.cs index 585b4d3..372309f 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixConcurrencyStrategyDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixConcurrencyStrategyDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,23 +11,20 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { public class HystrixConcurrencyStrategyDefault : HystrixConcurrencyStrategy { + private static HystrixConcurrencyStrategyDefault instance = new HystrixConcurrencyStrategyDefault(); - private static HystrixConcurrencyStrategyDefault INSTANCE = new HystrixConcurrencyStrategyDefault(); + public static HystrixConcurrencyStrategy GetInstance() + { + return instance; + } - public static HystrixConcurrencyStrategy GetInstance() - { - return INSTANCE; + private HystrixConcurrencyStrategyDefault() + { + } } - - private HystrixConcurrencyStrategyDefault() - { - } - -} } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixQueuedTaskScheduler.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixQueuedTaskScheduler.cs similarity index 87% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixQueuedTaskScheduler.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixQueuedTaskScheduler.cs index 5f64493..aebc9cc 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixQueuedTaskScheduler.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixQueuedTaskScheduler.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,28 +11,26 @@ // 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. -// +using Steeltoe.CircuitBreaker.Hystrix.Exceptions; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Steeltoe.CircuitBreaker.Hystrix.Exceptions; using System.Threading; +using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { public class HystrixQueuedTaskScheduler : HystrixTaskScheduler { - protected BlockingCollection workQueue; [ThreadStatic] private static bool isHystrixThreadPoolThread; - public HystrixQueuedTaskScheduler(IHystrixThreadPoolOptions options) : - base(options) + public HystrixQueuedTaskScheduler(IHystrixThreadPoolOptions options) + : base(options) { if (options.MaxQueueSize < 0) { @@ -49,10 +46,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency StartThreadPoolWorker(); runningThreads = 1; - } - #region IHystrixTaskScheduler public override int CurrentQueueSize { @@ -76,12 +71,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency protected override void QueueTask(Task task) { - if (runningThreads < corePoolSize) { Interlocked.Increment(ref runningThreads); StartThreadPoolWorker(); - } else if (allowMaxToDivergeFromCore && runningThreads < maximumPoolSize ) + } + else if (allowMaxToDivergeFromCore && runningThreads < maximumPoolSize) { Interlocked.Increment(ref runningThreads); StartThreadPoolWorker(); @@ -100,33 +95,33 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency protected virtual void StartThreadPoolWorker() { - System.Threading.ThreadPool.QueueUserWorkItem(_ => + System.Threading.ThreadPool.QueueUserWorkItem( + _ => { isHystrixThreadPoolThread = true; try { while (!this.shutdown) { - Task item = null; - workQueue.TryTake(out item, 250); + workQueue.TryTake(out Task item, 250); if (item != null) { try { Interlocked.Increment(ref this.runningTasks); - base.TryExecuteTask(item); - - } catch(Exception) + TryExecuteTask(item); + } + catch (Exception) { // Log - } finally + } + finally { Interlocked.Decrement(ref this.runningTasks); Interlocked.Increment(ref completedTasks); } } - } } finally @@ -143,24 +138,28 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { return false; } + if (prevQueued) { return false; } + try { Interlocked.Increment(ref this.runningTasks); - return base.TryExecuteTask(task); - } catch (Exception) + return TryExecuteTask(task); + } + catch (Exception) { // Log - } finally + } + finally { Interlocked.Decrement(ref this.runningTasks); Interlocked.Increment(ref completedTasks); } + return true; } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixRequestContext.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixRequestContext.cs similarity index 74% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixRequestContext.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixRequestContext.cs index 658ae39..d1c3ba6 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixRequestContext.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixRequestContext.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,16 @@ // 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. -// using System; using System.Collections.Concurrent; using System.Threading; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { public class HystrixRequestContext : IDisposable { - private static readonly AsyncLocal requestVariables = new AsyncLocal(); + private static readonly AsyncLocal RequestVariables = new AsyncLocal(); internal ConcurrentDictionary State { get; set; } @@ -35,7 +32,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { get { - HystrixRequestContext context = requestVariables.Value; + HystrixRequestContext context = RequestVariables.Value; return context != null && context.State != null; } } @@ -44,10 +41,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { get { - if (IsCurrentThreadInitialized) { - return requestVariables.Value; + return RequestVariables.Value; } else { @@ -55,45 +51,42 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency } } } + public static void SetContextOnCurrentThread(HystrixRequestContext state) { - requestVariables.Value = state; + RequestVariables.Value = state; } - public static HystrixRequestContext InitializeContext() { - HystrixRequestContext context = new HystrixRequestContext(); - context.State = new ConcurrentDictionary(); - requestVariables.Value = context; + HystrixRequestContext context = new HystrixRequestContext + { + State = new ConcurrentDictionary() + }; + RequestVariables.Value = context; return context; } - public virtual void Dispose() { if (State != null) { - foreach (var v in State.Keys) { try { v.Dispose(); - object oldValue; - State.TryRemove(v, out oldValue); - + State.TryRemove(v, out object oldValue); } - catch (Exception ) + catch (Exception) { - //HystrixRequestVariableDefault.logger.error("Error in shutdown, will continue with shutdown of other variables", t); + // HystrixRequestVariableDefault.logger.error("Error in shutdown, will continue with shutdown of other variables", t); } } State = null; } } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixRequestVariableDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixRequestVariableDefault.cs similarity index 89% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixRequestVariableDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixRequestVariableDefault.cs index 317edb6..c897d78 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixRequestVariableDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixRequestVariableDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,24 +11,23 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { public class HystrixRequestVariableDefault : IHystrixRequestVariable { private Action _disposeAction; private Func _valueFactory; + public HystrixRequestVariableDefault(T value) { _valueFactory = () => { return value; }; } - public HystrixRequestVariableDefault(Func valueFactory, Action disposeAction) + public HystrixRequestVariableDefault(Func valueFactory, Action disposeAction) { _valueFactory = valueFactory; _disposeAction = disposeAction; @@ -40,6 +38,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency _valueFactory = valueFactory; } + internal virtual void Remove() + { + if (HystrixRequestContext.ContextForCurrentThread != null) + { + Remove(HystrixRequestContext.ContextForCurrentThread, this); + } + } public virtual T Value { @@ -47,38 +52,25 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { // Checks to make sure HystrixRequestContext.ContextForCurrentThread.State != null if (!HystrixRequestContext.IsCurrentThreadInitialized) + { throw new InvalidOperationException("HystrixRequestContext.InitializeContext() must be called at the beginning of each request before RequestVariable functionality can be used."); + } return (T)HystrixRequestContext.ContextForCurrentThread.State.GetOrAddEx(this, (k) => _valueFactory()); } - - } - - internal virtual void Remove() - { - if (HystrixRequestContext.ContextForCurrentThread != null) - { - Remove(HystrixRequestContext.ContextForCurrentThread, this); - - } - } - - internal static void Remove(HystrixRequestContext context, IHystrixRequestVariable v) - { - object oldValue; - if (context.State.TryRemove(v, out oldValue)) - { - v.Dispose(); - } } public virtual void Dispose() { - if (_disposeAction != null) + _disposeAction?.Invoke(Value); + } + + internal static void Remove(HystrixRequestContext context, IHystrixRequestVariable v) + { + if (context.State.TryRemove(v, out object oldValue)) { - _disposeAction(Value); + v.Dispose(); } } } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixSyncTaskScheduler.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixSyncTaskScheduler.cs similarity index 72% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixSyncTaskScheduler.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixSyncTaskScheduler.cs index 918d33e..0a7900e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixSyncTaskScheduler.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixSyncTaskScheduler.cs @@ -1,6 +1,4 @@ - -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Exceptions; using Steeltoe.CircuitBreaker.Hystrix.Util; @@ -24,24 +21,22 @@ using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { - public class HystrixSyncTaskScheduler : HystrixTaskScheduler { - - public ThreadTaskQueue[] workQueues; - + public class HystrixSyncTaskScheduler : HystrixTaskScheduler + { [ThreadStatic] private static bool isHystrixThreadPoolThread; [ThreadStatic] private static ThreadTaskQueue workQueue; + private ThreadTaskQueue[] workQueues; - public HystrixSyncTaskScheduler(IHystrixThreadPoolOptions options) : - base(options) + public HystrixSyncTaskScheduler(IHystrixThreadPoolOptions options) + : base(options) { SetupWorkQueues(corePoolSize); } - protected override void QueueTask(Task task) { if (runningThreads < corePoolSize) @@ -49,26 +44,23 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency StartThreadPoolWorker(); } - if (!TryAddToAny(task)) { throw new RejectedExecutionException("Rejected command because task work queues rejected add."); } - } protected virtual void StartThreadPoolWorker() { - for (int i = 0; i < corePoolSize; i++) { - if (!workQueues[i].threadAssigned) + if (!workQueues[i].ThreadAssigned) { - lock(workQueues[i]) + lock (workQueues[i]) { - if (!workQueues[i].threadAssigned) + if (!workQueues[i].ThreadAssigned) { - workQueues[i].threadAssigned = true; + workQueues[i].ThreadAssigned = true; StartThreadPoolWorker(workQueues[i]); Interlocked.Increment(ref runningThreads); break; @@ -80,59 +72,59 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency protected virtual void StartThreadPoolWorker(ThreadTaskQueue input) { - input.workerStartTime = Time.CurrentTimeMillis; - System.Threading.ThreadPool.QueueUserWorkItem((queue) => + input.WorkerStartTime = Time.CurrentTimeMillis; + System.Threading.ThreadPool.QueueUserWorkItem( + (queue) => { isHystrixThreadPoolThread = true; workQueue = queue as ThreadTaskQueue; - workQueue.threadStartTime = Time.CurrentTimeMillis; + workQueue.ThreadStartTime = Time.CurrentTimeMillis; try { while (!this.shutdown) { Task item = null; - workQueue.signal.Wait(250); + workQueue.Signal.Wait(250); - item = workQueue.task; + item = workQueue.Task; if (item != null) { try { Interlocked.Increment(ref this.runningTasks); - base.TryExecuteTask(item); - + TryExecuteTask(item); } - catch (Exception ) + catch (Exception) { // log - } finally + } + finally { Interlocked.Decrement(ref this.runningTasks); Interlocked.Increment(ref completedTasks); } - workQueue.signal.Reset(); - workQueue.task = null; + workQueue.Signal.Reset(); + workQueue.Task = null; } } } finally { isHystrixThreadPoolThread = false; - workQueue.signal.Reset(); - workQueue.threadAssigned = false; + workQueue.Signal.Reset(); + workQueue.ThreadAssigned = false; Interlocked.Decrement(ref runningThreads); workQueue = null; } }, input); } - protected override IEnumerable GetScheduledTasks() { - return new List< Task> (); + return new List(); } protected override bool TryExecuteTaskInline(Task task, bool prevQueued) @@ -141,14 +133,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { return false; } + if (prevQueued) { return false; } + try { Interlocked.Increment(ref this.runningTasks); - return base.TryExecuteTask(task); + return TryExecuteTask(task); } catch (Exception) { @@ -159,23 +153,22 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency Interlocked.Decrement(ref this.runningTasks); Interlocked.Increment(ref completedTasks); } + return true; } protected virtual bool TryAddToAny(Task task) { - foreach (ThreadTaskQueue queue in workQueues) { - - if (queue.threadAssigned && queue.task == null) + if (queue.ThreadAssigned && queue.Task == null) { lock (queue) { - if (queue.threadAssigned && queue.task == null) + if (queue.ThreadAssigned && queue.Task == null) { - queue.task = task; - queue.signal.Set(); + queue.Task = task; + queue.Signal.Set(); return true; } } @@ -188,7 +181,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency protected virtual void SetupWorkQueues(int size) { workQueues = new ThreadTaskQueue[size]; - for (int i = 0; i < size; i++) workQueues[i] = new ThreadTaskQueue(); + for (int i = 0; i < size; i++) + { + workQueues[i] = new ThreadTaskQueue(); + } } #region IHystrixTaskScheduler @@ -199,10 +195,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency int size = 0; for (int i = 0; i < workQueues.Length; i++) { - ThreadTaskQueue queue = workQueues[i]; - if (queue.threadAssigned && queue.task != null) size++; + if (queue.ThreadAssigned && queue.Task != null) + { + size++; + } } + return size; } } @@ -218,17 +217,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { public ThreadTaskQueue() { - signal = new ManualResetEventSlim(false); - task = null; - threadAssigned = false; + Signal = new ManualResetEventSlim(false); + Task = null; + ThreadAssigned = false; } - public ManualResetEventSlim signal; - public Task task; - public bool threadAssigned; - public long threadStartTime; - public long workerStartTime; + public ManualResetEventSlim Signal; + public Task Task; + public bool ThreadAssigned; + public long ThreadStartTime; + public long WorkerStartTime; } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixTaskScheduler.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixTaskScheduler.cs similarity index 93% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixTaskScheduler.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixTaskScheduler.cs index 5f4cb09..809ffdb 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/HystrixTaskScheduler.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/HystrixTaskScheduler.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; @@ -22,8 +20,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { public abstract class HystrixTaskScheduler : TaskScheduler, IHystrixTaskScheduler { - private const int DEFAULT_MIN_WORKTHREADS = 50; - protected int corePoolSize; protected TimeSpan keepAliveTime; protected int maximumPoolSize; @@ -35,6 +31,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency protected int completedTasks = 0; protected bool allowMaxToDivergeFromCore; + private const int DEFAULT_MIN_WORKTHREADS = 50; + public HystrixTaskScheduler(IHystrixThreadPoolOptions options) { if (options.MaximumSize < 1) @@ -47,7 +45,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency throw new ArgumentOutOfRangeException("corePoolSize"); } - this.allowMaxToDivergeFromCore = options.AllowMaximumSizeToDivergeFromCoreSize; this.corePoolSize = options.CoreSize; this.maximumPoolSize = options.MaximumSize; @@ -55,14 +52,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency this.queueSize = options.MaxQueueSize; this.queueSizeRejectionThreshold = options.QueueSizeRejectionThreshold; - int workThreads = 0; - int compThreads = 0; - System.Threading.ThreadPool.GetMinThreads(out workThreads, out compThreads); - - System.Threading.ThreadPool.SetMinThreads(Math.Max(workThreads, DEFAULT_MIN_WORKTHREADS), compThreads); - ; + System.Threading.ThreadPool.GetMinThreads(out int workThreads, out int compThreads); + System.Threading.ThreadPool.SetMinThreads(Math.Max(workThreads, DEFAULT_MIN_WORKTHREADS), compThreads); } + #region IHystrixTaskScheduler public virtual int CurrentActiveCount { @@ -175,9 +169,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency public virtual void Dispose() { this.shutdown = true; - + Time.WaitUntil(() => { return !(runningThreads > 0); }, 500); - } #endregion IHystrixTaskScheduler @@ -195,4 +188,3 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency } } } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/IHystrixRequestVariable.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/IHystrixRequestVariable.cs similarity index 83% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/IHystrixRequestVariable.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/IHystrixRequestVariable.cs index 6421bb9..b44dd39 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/IHystrixRequestVariable.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/IHystrixRequestVariable.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,19 +11,13 @@ // 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. -// -using System; +using System; namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { - //public interface IHystrixRequestVariable { - // object Value { get; } - //} - public interface IHystrixRequestVariable : IDisposable { T Value { get; } } } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/IHystrixTaskScheduler.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/IHystrixTaskScheduler.cs similarity index 90% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/IHystrixTaskScheduler.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/IHystrixTaskScheduler.cs index fec91af..0a0087d 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Concurrency/IHystrixTaskScheduler.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Concurrency/IHystrixTaskScheduler.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,28 +11,35 @@ // 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. -// using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency { - public interface IHystrixTaskScheduler: IDisposable + public interface IHystrixTaskScheduler : IDisposable { int CurrentActiveCount { get; } + int CurrentCompletedTaskCount { get; } + int CurrentCorePoolSize { get; } + int CurrentLargestPoolSize { get; } + int CurrentMaximumPoolSize { get; } + int CurrentPoolSize { get; } + int CurrentQueueSize { get; } + int CurrentTaskCount { get; } int CorePoolSize { get; set; } + int MaximumPoolSize { get; set; } + TimeSpan KeepAliveTime { get; set; } - + bool IsQueueSpaceAvailable { get; } bool IsShutdown { get; } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/EventNotifier/HystrixEventNotifier.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/EventNotifier/HystrixEventNotifier.cs similarity index 93% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/EventNotifier/HystrixEventNotifier.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/EventNotifier/HystrixEventNotifier.cs index a0f8666..ec614bd 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/EventNotifier/HystrixEventNotifier.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/EventNotifier/HystrixEventNotifier.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,28 +11,21 @@ // 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. -// -using System; using System.Collections.Generic; namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.EventNotifier { public abstract class HystrixEventNotifier { - public void MarkEvent(HystrixEventType eventType, IHystrixCommandKey key) { // do nothing } - public void MarkCommandExecution(IHystrixCommandKey key, ExecutionIsolationStrategy isolationStrategy, int duration, IList eventsDuringExecution) { // do nothing } - } } - - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/EventNotifier/HystrixEventNotifierDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/EventNotifier/HystrixEventNotifierDefault.cs similarity index 84% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/EventNotifier/HystrixEventNotifierDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/EventNotifier/HystrixEventNotifierDefault.cs index d311836..7165552 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/EventNotifier/HystrixEventNotifierDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/EventNotifier/HystrixEventNotifierDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,25 +11,20 @@ // 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. -// - - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.EventNotifier { public class HystrixEventNotifierDefault : HystrixEventNotifier { - private static HystrixEventNotifierDefault INSTANCE = new HystrixEventNotifierDefault(); + private static HystrixEventNotifierDefault instance = new HystrixEventNotifierDefault(); private HystrixEventNotifierDefault() { - } public static HystrixEventNotifier GetInstance() { - return INSTANCE; + return instance; } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/ExecutionHook/HystrixCommandExecutionHook.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/ExecutionHook/HystrixCommandExecutionHook.cs similarity index 77% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/ExecutionHook/HystrixCommandExecutionHook.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/ExecutionHook/HystrixCommandExecutionHook.cs index fbd30ae..b198f1b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/ExecutionHook/HystrixCommandExecutionHook.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/ExecutionHook/HystrixCommandExecutionHook.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,84 +11,88 @@ // 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. -// -using System; using Steeltoe.CircuitBreaker.Hystrix.Exceptions; +using System; namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.ExecutionHook { public abstract class HystrixCommandExecutionHook { - public virtual void OnStart(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } public virtual T OnEmit(IHystrixInvokable commandInstance, T value) { - return value; //by default, just pass through + return value; // by default, just pass through } + public virtual Exception OnError(IHystrixInvokable commandInstance, FailureType failureType, Exception e) { - return e; //by default, just pass through + return e; // by default, just pass through } public virtual void OnSuccess(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } public virtual void OnThreadStart(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } public virtual void OnThreadComplete(IHystrixInvokable commandInstance) { // do nothing by default } + public virtual void OnExecutionStart(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } public virtual T OnExecutionEmit(IHystrixInvokable commandInstance, T value) { - return value; //by default, just pass through + return value; // by default, just pass through } public virtual Exception OnExecutionError(IHystrixInvokable commandInstance, Exception e) { - return e; //by default, just pass through + return e; // by default, just pass through } public virtual void OnExecutionSuccess(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } + public virtual void OnFallbackStart(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } public virtual T OnFallbackEmit(IHystrixInvokable commandInstance, T value) { - return value; //by default, just pass through + return value; // by default, just pass through } + public virtual Exception OnFallbackError(IHystrixInvokable commandInstance, Exception e) { - //by default, just pass through + // by default, just pass through return e; } + public virtual void OnFallbackSuccess(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } + public virtual void OnCacheHit(IHystrixInvokable commandInstance) { - //do nothing by default + // do nothing by default } } } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/ExecutionHook/HystrixCommandExecutionHookDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/ExecutionHook/HystrixCommandExecutionHookDefault.cs similarity index 81% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/ExecutionHook/HystrixCommandExecutionHookDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/ExecutionHook/HystrixCommandExecutionHookDefault.cs index dd5d052..4902d3e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/ExecutionHook/HystrixCommandExecutionHookDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/ExecutionHook/HystrixCommandExecutionHookDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,24 +11,20 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.ExecutionHook { public class HystrixCommandExecutionHookDefault : HystrixCommandExecutionHook { - - private static HystrixCommandExecutionHookDefault INSTANCE = new HystrixCommandExecutionHookDefault(); + private static HystrixCommandExecutionHookDefault instance = new HystrixCommandExecutionHookDefault(); private HystrixCommandExecutionHookDefault() { - } public static HystrixCommandExecutionHook GetInstance() { - return INSTANCE; + return instance; } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/HystrixPlugins.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/HystrixPlugins.cs similarity index 66% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/HystrixPlugins.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/HystrixPlugins.cs index 8851bec..febd554 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/HystrixPlugins.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/HystrixPlugins.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; using Steeltoe.CircuitBreaker.Hystrix.Strategy.EventNotifier; @@ -22,39 +20,37 @@ using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options; using Steeltoe.CircuitBreaker.Hystrix.Util; using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy { public static class HystrixPlugins { - private static readonly AtomicReference notifier = new AtomicReference(); - private static readonly AtomicReference concurrencyStrategy = new AtomicReference(); - private static readonly AtomicReference metricsPublisher = new AtomicReference(); - private static readonly AtomicReference commandExecutionHook = new AtomicReference(); - private static readonly AtomicReference options = new AtomicReference(); + private static readonly AtomicReference _notifier = new AtomicReference(); + private static readonly AtomicReference _concurrencyStrategy = new AtomicReference(); + private static readonly AtomicReference _metricsPublisher = new AtomicReference(); + private static readonly AtomicReference _commandExecutionHook = new AtomicReference(); + private static readonly AtomicReference _options = new AtomicReference(); static HystrixPlugins() { - } - #region EventNotifier public static HystrixEventNotifier EventNotifier { get { - if (notifier.Value == null) + if (_notifier.Value == null) { - notifier.CompareAndSet(null, HystrixEventNotifierDefault.GetInstance()); + _notifier.CompareAndSet(null, HystrixEventNotifierDefault.GetInstance()); } - return notifier.Value; + + return _notifier.Value; } } public static void RegisterEventNotifier(HystrixEventNotifier impl) { - if (!notifier.CompareAndSet(null, impl)) + if (!_notifier.CompareAndSet(null, impl)) { throw new InvalidOperationException("Another strategy was already registered."); } @@ -66,17 +62,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy { get { - if (concurrencyStrategy.Value == null) + if (_concurrencyStrategy.Value == null) { - concurrencyStrategy.CompareAndSet(null, HystrixConcurrencyStrategyDefault.GetInstance()); + _concurrencyStrategy.CompareAndSet(null, HystrixConcurrencyStrategyDefault.GetInstance()); } - return concurrencyStrategy.Value; + + return _concurrencyStrategy.Value; } } public static void RegisterConcurrencyStrategy(HystrixConcurrencyStrategy impl) { - if (!concurrencyStrategy.CompareAndSet(null, impl)) + if (!_concurrencyStrategy.CompareAndSet(null, impl)) { throw new InvalidOperationException("Another strategy was already registered."); } @@ -88,17 +85,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy { get { - if (metricsPublisher.Value == null) + if (_metricsPublisher.Value == null) { - metricsPublisher.CompareAndSet(null, HystrixMetricsPublisherDefault.GetInstance()); + _metricsPublisher.CompareAndSet(null, HystrixMetricsPublisherDefault.GetInstance()); } - return metricsPublisher.Value; + + return _metricsPublisher.Value; } } public static void RegisterMetricsPublisher(HystrixMetricsPublisher impl) { - if (!metricsPublisher.CompareAndSet(null, impl)) + if (!_metricsPublisher.CompareAndSet(null, impl)) { throw new InvalidOperationException("Another strategy was already registered."); } @@ -110,17 +108,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy { get { - if (commandExecutionHook.Value == null) + if (_commandExecutionHook.Value == null) { - commandExecutionHook.CompareAndSet(null, HystrixCommandExecutionHookDefault.GetInstance()); + _commandExecutionHook.CompareAndSet(null, HystrixCommandExecutionHookDefault.GetInstance()); } - return commandExecutionHook.Value; + + return _commandExecutionHook.Value; } } public static void RegisterMetricsPublisher(HystrixCommandExecutionHook impl) { - if (!commandExecutionHook.CompareAndSet(null, impl)) + if (!_commandExecutionHook.CompareAndSet(null, impl)) { throw new InvalidOperationException("Another strategy was already registered."); } @@ -132,17 +131,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy { get { - if (options.Value == null) + if (_options.Value == null) { - options.CompareAndSet(null, HystrixOptionsStrategyDefault.GetInstance()); + _options.CompareAndSet(null, HystrixOptionsStrategyDefault.GetInstance()); } - return options.Value; + + return _options.Value; } } public static void RegisterOptionsStrategy(HystrixOptionsStrategy impl) { - if (!options.CompareAndSet(null, impl)) + if (!_options.CompareAndSet(null, impl)) { throw new InvalidOperationException("Another strategy was already registered."); } @@ -151,11 +151,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy public static void Reset() { - notifier.Value = null; - concurrencyStrategy.Value = null; - metricsPublisher.Value = null ; - commandExecutionHook.Value = null; - options.Value = null; + _notifier.Value = null; + _concurrencyStrategy.Value = null; + _metricsPublisher.Value = null; + _commandExecutionHook.Value = null; + _options.Value = null; HystrixMetricsPublisherFactory.Reset(); } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisher.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisher.cs similarity index 96% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisher.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisher.cs index 067f0d1..defa857 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisher.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisher.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { @@ -23,7 +21,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics return new HystrixMetricsPublisherCommandDefault(commandKey, commandGroupKey, metrics, circuitBreaker, properties); } - public virtual IHystrixMetricsPublisherThreadPool GetMetricsPublisherForThreadPool(IHystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, IHystrixThreadPoolOptions properties) { return new HystrixMetricsPublisherThreadPoolDefault(threadPoolKey, metrics, properties); @@ -33,6 +30,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { return new HystrixMetricsPublisherCollapserDefault(collapserKey, metrics, properties); } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherCollapserDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherCollapserDefault.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherCollapserDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherCollapserDefault.cs index c81f6be..2cece28 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherCollapserDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherCollapserDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { @@ -23,7 +21,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics // do nothing by default } - public void Initialize() { // do nothing by default diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherCommandDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherCommandDefault.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherCommandDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherCommandDefault.cs index 265eec5..284589c 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherCommandDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherCommandDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherDefault.cs similarity index 85% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherDefault.cs index 6a163f8..6a48054 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,22 +11,20 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { public class HystrixMetricsPublisherDefault : HystrixMetricsPublisher { - private static HystrixMetricsPublisherDefault INSTANCE = new HystrixMetricsPublisherDefault(); + private static HystrixMetricsPublisherDefault instance = new HystrixMetricsPublisherDefault(); public static HystrixMetricsPublisher GetInstance() { - return INSTANCE; + return instance; } private HystrixMetricsPublisherDefault() { } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherFactory.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherFactory.cs similarity index 65% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherFactory.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherFactory.cs index 9d8b8ad..a9d85af 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherFactory.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherFactory.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,65 +11,60 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { public class HystrixMetricsPublisherFactory { - - - private static HystrixMetricsPublisherFactory SINGLETON = new HystrixMetricsPublisherFactory(); + private static HystrixMetricsPublisherFactory singleton = new HystrixMetricsPublisherFactory(); public static IHystrixMetricsPublisherThreadPool CreateOrRetrievePublisherForThreadPool(IHystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, IHystrixThreadPoolOptions properties) { - return SINGLETON.GetPublisherForThreadPool(threadPoolKey, metrics, properties); + return singleton.GetPublisherForThreadPool(threadPoolKey, metrics, properties); } public static IHystrixMetricsPublisherCommand CreateOrRetrievePublisherForCommand(IHystrixCommandKey commandKey, IHystrixCommandGroupKey commandOwner, HystrixCommandMetrics metrics, IHystrixCircuitBreaker circuitBreaker, IHystrixCommandOptions properties) { - return SINGLETON.GetPublisherForCommand(commandKey, commandOwner, metrics, circuitBreaker, properties); + return singleton.GetPublisherForCommand(commandKey, commandOwner, metrics, circuitBreaker, properties); } public static IHystrixMetricsPublisherCollapser CreateOrRetrievePublisherForCollapser(IHystrixCollapserKey collapserKey, HystrixCollapserMetrics metrics, IHystrixCollapserOptions properties) { - return SINGLETON.GetPublisherForCollapser(collapserKey, metrics, properties); + return singleton.GetPublisherForCollapser(collapserKey, metrics, properties); } public static void Reset() { - SINGLETON = new HystrixMetricsPublisherFactory(); - SINGLETON.commandPublishers.Clear(); - SINGLETON.threadPoolPublishers.Clear(); - SINGLETON.collapserPublishers.Clear(); + singleton = new HystrixMetricsPublisherFactory(); + singleton.CommandPublishers.Clear(); + singleton.ThreadPoolPublishers.Clear(); + singleton.CollapserPublishers.Clear(); } - internal HystrixMetricsPublisherFactory() { } + internal HystrixMetricsPublisherFactory() + { + } - internal readonly ConcurrentDictionary commandPublishers = new ConcurrentDictionary(); + private readonly ConcurrentDictionary commandPublishers = new ConcurrentDictionary(); internal IHystrixMetricsPublisherCommand GetPublisherForCommand(IHystrixCommandKey commandKey, IHystrixCommandGroupKey commandOwner, HystrixCommandMetrics metrics, IHystrixCircuitBreaker circuitBreaker, IHystrixCommandOptions properties) { - - return commandPublishers.GetOrAddEx(commandKey.Name, (k) => + return CommandPublishers.GetOrAddEx(commandKey.Name, (k) => { IHystrixMetricsPublisherCommand newPublisher = HystrixPlugins.MetricsPublisher.GetMetricsPublisherForCommand(commandKey, commandOwner, metrics, circuitBreaker, properties); newPublisher.Initialize(); return newPublisher; }); - - } - internal readonly ConcurrentDictionary threadPoolPublishers = new ConcurrentDictionary(); + private readonly ConcurrentDictionary threadPoolPublishers = new ConcurrentDictionary(); internal IHystrixMetricsPublisherThreadPool GetPublisherForThreadPool(IHystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, IHystrixThreadPoolOptions properties) { - return threadPoolPublishers.GetOrAddEx(threadPoolKey.Name, (k) => + return ThreadPoolPublishers.GetOrAddEx(threadPoolKey.Name, (k) => { IHystrixMetricsPublisherThreadPool publisher = HystrixPlugins.MetricsPublisher.GetMetricsPublisherForThreadPool(threadPoolKey, metrics, properties); publisher.Initialize(); @@ -78,20 +72,22 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics }); } + private readonly ConcurrentDictionary collapserPublishers = new ConcurrentDictionary(); - internal readonly ConcurrentDictionary collapserPublishers = new ConcurrentDictionary(); + internal ConcurrentDictionary CommandPublishers => commandPublishers; + internal ConcurrentDictionary ThreadPoolPublishers => threadPoolPublishers; + + internal ConcurrentDictionary CollapserPublishers => collapserPublishers; internal IHystrixMetricsPublisherCollapser GetPublisherForCollapser(IHystrixCollapserKey collapserKey, HystrixCollapserMetrics metrics, IHystrixCollapserOptions properties) { - return collapserPublishers.GetOrAddEx(collapserKey.Name, (k) => + return CollapserPublishers.GetOrAddEx(collapserKey.Name, (k) => { IHystrixMetricsPublisherCollapser publisher = HystrixPlugins.MetricsPublisher.GetMetricsPublisherForCollapser(collapserKey, metrics, properties); publisher.Initialize(); return publisher; }); } - } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherThreadPoolDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherThreadPoolDefault.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherThreadPoolDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherThreadPoolDefault.cs index b8c1107..b701e3a 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/HystrixMetricsPublisherThreadPoolDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/HystrixMetricsPublisherThreadPoolDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherCollapser.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherCollapser.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherCollapser.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherCollapser.cs index 4bd0170..a088e3c 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherCollapser.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherCollapser.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherCommand.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherCommand.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherCommand.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherCommand.cs index 0717c83..f2903b3 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherCommand.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherCommand.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherThreadPool.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherThreadPool.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherThreadPool.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherThreadPool.cs index c47a91c..0e6a9b4 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Metrics/IHystrixMetricsPublisherThreadPool.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Metrics/IHystrixMetricsPublisherThreadPool.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics { diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixDynamicOptionsDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixDynamicOptionsDefault.cs similarity index 91% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixDynamicOptionsDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixDynamicOptionsDefault.cs index 71c77fc..c51e3db 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixDynamicOptionsDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixDynamicOptionsDefault.cs @@ -1,7 +1,4 @@ -using Microsoft.Extensions.Configuration; -using System; -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +12,9 @@ using System; // See the License for the specific language governing permissions and // limitations under the License. +using Microsoft.Extensions.Configuration; +using System; + namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { public class HystrixDynamicOptionsDefault : IHystrixDynamicOptions @@ -34,13 +34,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options return fallback; } - bool result = false; - if (Boolean.TryParse(val, out result)) + if (bool.TryParse(val, out bool result)) { return result; } + return fallback; - } public int GetInteger(string name, int fallback) @@ -56,6 +55,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { return result; } + return fallback; } @@ -72,6 +72,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { return result; } + return fallback; } @@ -82,9 +83,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { return fallback; } + return val; - } - } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsFactory.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsFactory.cs similarity index 82% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsFactory.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsFactory.cs index bb36945..3fdbba7 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsFactory.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsFactory.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,15 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { public class HystrixOptionsFactory { - public static void Reset() { commandProperties.Clear(); @@ -31,16 +27,15 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options collapserProperties.Clear(); } - private static ConcurrentDictionary commandProperties = new ConcurrentDictionary(); + private static ConcurrentDictionary commandProperties = new ConcurrentDictionary(); public static IHystrixCommandOptions GetCommandOptions(IHystrixCommandKey key, IHystrixCommandOptions builder) { HystrixOptionsStrategy hystrixPropertiesStrategy = HystrixPlugins.OptionsStrategy; - String cacheKey = hystrixPropertiesStrategy.GetCommandOptionsCacheKey(key, builder); + string cacheKey = hystrixPropertiesStrategy.GetCommandOptionsCacheKey(key, builder); if (cacheKey != null) { return commandProperties.GetOrAddEx(cacheKey, (k) => hystrixPropertiesStrategy.GetCommandOptions(key, builder)); - } else { @@ -49,46 +44,38 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options } } - private static ConcurrentDictionary threadPoolProperties = new ConcurrentDictionary(); - + private static ConcurrentDictionary threadPoolProperties = new ConcurrentDictionary(); public static IHystrixThreadPoolOptions GetThreadPoolOptions(IHystrixThreadPoolKey key, IHystrixThreadPoolOptions builder) { HystrixOptionsStrategy hystrixPropertiesStrategy = HystrixPlugins.OptionsStrategy; - String cacheKey = hystrixPropertiesStrategy.GetThreadPoolOptionsCacheKey(key, builder); + string cacheKey = hystrixPropertiesStrategy.GetThreadPoolOptionsCacheKey(key, builder); if (cacheKey != null) { return threadPoolProperties.GetOrAddEx(cacheKey, (k) => hystrixPropertiesStrategy.GetThreadPoolOptions(key, builder)); - } else { // no cacheKey so we generate it with caching return hystrixPropertiesStrategy.GetThreadPoolOptions(key, builder); } - } - private static ConcurrentDictionary collapserProperties = new ConcurrentDictionary(); - + private static ConcurrentDictionary collapserProperties = new ConcurrentDictionary(); public static IHystrixCollapserOptions GetCollapserOptions(IHystrixCollapserKey key, IHystrixCollapserOptions builder) { HystrixOptionsStrategy hystrixPropertiesStrategy = HystrixPlugins.OptionsStrategy; - String cacheKey = hystrixPropertiesStrategy.GetCollapserOptionsCacheKey(key, builder); + string cacheKey = hystrixPropertiesStrategy.GetCollapserOptionsCacheKey(key, builder); if (cacheKey != null) { return collapserProperties.GetOrAddEx(cacheKey, (k) => hystrixPropertiesStrategy.GetCollapserOptions(key, builder)); - } else { // no cacheKey so we generate it with caching return hystrixPropertiesStrategy.GetCollapserOptions(key, builder); } - } - } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsStrategy.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsStrategy.cs similarity index 90% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsStrategy.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsStrategy.cs index 4569633..c87c4fc 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsStrategy.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsStrategy.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,48 +11,40 @@ // 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. -// using Microsoft.Extensions.Configuration; using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { public abstract class HystrixOptionsStrategy { - - public virtual IHystrixCommandOptions GetCommandOptions(IHystrixCommandKey commandKey, IHystrixCommandOptions builder) { return new HystrixCommandOptions(commandKey, builder); } - public virtual string GetCommandOptionsCacheKey(IHystrixCommandKey commandKey, IHystrixCommandOptions builder) { return commandKey.Name; } - public virtual IHystrixThreadPoolOptions GetThreadPoolOptions(IHystrixThreadPoolKey threadPoolKey, IHystrixThreadPoolOptions builder) { return new HystrixThreadPoolOptions(threadPoolKey, builder); } - public virtual String GetThreadPoolOptionsCacheKey(IHystrixThreadPoolKey threadPoolKey, IHystrixThreadPoolOptions builder) + public virtual string GetThreadPoolOptionsCacheKey(IHystrixThreadPoolKey threadPoolKey, IHystrixThreadPoolOptions builder) { return threadPoolKey.Name; } - public virtual IHystrixCollapserOptions GetCollapserOptions(IHystrixCollapserKey collapserKey, IHystrixCollapserOptions builder) { return new HystrixCollapserOptions(collapserKey, builder); } - - public virtual String GetCollapserOptionsCacheKey(IHystrixCollapserKey collapserKey, IHystrixCollapserOptions builder) + public virtual string GetCollapserOptionsCacheKey(IHystrixCollapserKey collapserKey, IHystrixCollapserOptions builder) { return collapserKey.Name; } @@ -62,7 +53,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { return new HystrixDynamicOptionsDefault(configSource); } - } - } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsStrategyDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsStrategyDefault.cs similarity index 78% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsStrategyDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsStrategyDefault.cs index f057cf3..42d49b2 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/HystrixOptionsStrategyDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/HystrixOptionsStrategyDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,14 +11,12 @@ // 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. -// namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options { - class HystrixOptionsStrategyDefault : HystrixOptionsStrategy + internal class HystrixOptionsStrategyDefault : HystrixOptionsStrategy { - - private static HystrixOptionsStrategyDefault INSTANCE = new HystrixOptionsStrategyDefault(); + private static HystrixOptionsStrategyDefault instance = new HystrixOptionsStrategyDefault(); private HystrixOptionsStrategyDefault() { @@ -27,7 +24,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Options public static HystrixOptionsStrategy GetInstance() { - return INSTANCE; + return instance; } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/IHystrixDynamicOptions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/IHystrixDynamicOptions.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/IHystrixDynamicOptions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/IHystrixDynamicOptions.cs index 7892e01..06f21a1 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Strategy/Options/IHystrixDynamicOptions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Strategy/Options/IHystrixDynamicOptions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ThreadPool/HystrixThreadPoolDefault.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPool/HystrixThreadPoolDefault.cs similarity index 85% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/ThreadPool/HystrixThreadPoolDefault.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPool/HystrixThreadPoolDefault.cs index ce01c21..f97d4aa 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ThreadPool/HystrixThreadPoolDefault.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPool/HystrixThreadPoolDefault.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Strategy; using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; @@ -25,10 +23,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.ThreadPool { public class HystrixThreadPoolDefault : IHystrixThreadPool { - //private static Logger logger = LoggerFactory.getLogger(HystrixThreadPoolDefault.class); - private readonly IHystrixThreadPoolOptions properties; - //private readonly BlockingCollection queue; private readonly IHystrixTaskScheduler taskScheduler; private readonly HystrixThreadPoolMetrics metrics; private readonly int queueSize; @@ -41,7 +36,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.ThreadPool this.queueSize = properties.MaxQueueSize; this.metrics = HystrixThreadPoolMetrics.GetInstance(threadPoolKey, concurrencyStrategy.GetTaskScheduler(properties), properties); this.taskScheduler = this.metrics.TaskScheduler; - /* strategy: HystrixMetricsPublisherThreadPool */ HystrixMetricsPublisherFactory.CreateOrRetrievePublisherForThreadPool(threadPoolKey, this.metrics, this.properties); @@ -57,43 +51,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.ThreadPool return this.taskScheduler as TaskScheduler; } - // allow us to change things via fast-properties by setting it each time - private void TouchConfig() - { - int dynamicCoreSize = properties.CoreSize; - int dynamicMaximumSize = properties.MaximumSize; - bool allowSizesToDiverge = properties.AllowMaximumSizeToDivergeFromCoreSize; - bool maxTooLow = false; - - if (allowSizesToDiverge && dynamicMaximumSize < dynamicCoreSize) - { - //if user sets maximum < core (or defaults get us there), we need to maintain invariant of core <= maximum - dynamicMaximumSize = dynamicCoreSize; - maxTooLow = true; - } - - if (!allowSizesToDiverge) - { - //if user has not opted in to allowing sizes to diverge, ensure maximum == core - dynamicMaximumSize = dynamicCoreSize; - } - - // In JDK 6, setCorePoolSize and setMaximumPoolSize will execute a lock operation. Avoid them if the pool size is not changed. - if (taskScheduler.CorePoolSize != dynamicCoreSize || (allowSizesToDiverge && taskScheduler.MaximumPoolSize != dynamicMaximumSize)) - { - if (maxTooLow) - { - //logger.error("Hystrix ThreadPool configuration for : " + metrics.getThreadPoolKey().name() + " is trying to set coreSize = " + - // dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ". Maximum size will be set to " + - // dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value"); - } - taskScheduler.CorePoolSize = dynamicCoreSize; - taskScheduler.MaximumPoolSize =dynamicMaximumSize; - } - - taskScheduler.KeepAliveTime = TimeSpan.FromMinutes(properties.KeepAliveTimeMinutes); - } - public void MarkThreadExecution() { metrics.MarkThreadExecution(); @@ -135,7 +92,42 @@ namespace Steeltoe.CircuitBreaker.Hystrix.ThreadPool { get { return this.taskScheduler.IsShutdown; } } + + // allow us to change things via fast-properties by setting it each time + private void TouchConfig() + { + int dynamicCoreSize = properties.CoreSize; + int dynamicMaximumSize = properties.MaximumSize; + bool allowSizesToDiverge = properties.AllowMaximumSizeToDivergeFromCoreSize; + bool maxTooLow = false; + + if (allowSizesToDiverge && dynamicMaximumSize < dynamicCoreSize) + { + // if user sets maximum < core (or defaults get us there), we need to maintain invariant of core <= maximum + dynamicMaximumSize = dynamicCoreSize; + maxTooLow = true; + } + + if (!allowSizesToDiverge) + { + // if user has not opted in to allowing sizes to diverge, ensure maximum == core + dynamicMaximumSize = dynamicCoreSize; + } + + if (taskScheduler.CorePoolSize != dynamicCoreSize || (allowSizesToDiverge && taskScheduler.MaximumPoolSize != dynamicMaximumSize)) + { + if (maxTooLow) + { + // logger.error("Hystrix ThreadPool configuration for : " + metrics.getThreadPoolKey().name() + " is trying to set coreSize = " + + // dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ". Maximum size will be set to " + + // dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value"); + } + + taskScheduler.CorePoolSize = dynamicCoreSize; + taskScheduler.MaximumPoolSize = dynamicMaximumSize; + } + + taskScheduler.KeepAliveTime = TimeSpan.FromMinutes(properties.KeepAliveTimeMinutes); + } } - } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ThreadPool/HystrixThreadPoolFactory.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPool/HystrixThreadPoolFactory.cs similarity index 74% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/ThreadPool/HystrixThreadPoolFactory.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPool/HystrixThreadPoolFactory.cs index 270c5c0..8136e4e 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/ThreadPool/HystrixThreadPoolFactory.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPool/HystrixThreadPoolFactory.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,15 @@ // 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. -// using Steeltoe.CircuitBreaker.Hystrix.Util; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.ThreadPool { - static class HystrixThreadPoolFactory + internal static class HystrixThreadPoolFactory { - - internal static readonly ConcurrentDictionary threadPools = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary _threadPools = new ConcurrentDictionary(); internal static IHystrixThreadPool GetInstance(IHystrixThreadPoolKey threadPoolKey, IHystrixThreadPoolOptions propertiesBuilder) { @@ -31,23 +27,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix.ThreadPool string key = threadPoolKey.Name; // if we get here this is the first time so we need to initialize - return threadPools.GetOrAddEx(key, (k) => new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder)); - + return ThreadPools.GetOrAddEx(key, (k) => new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder)); } private static object shutdownLock = new object(); + + internal static ConcurrentDictionary ThreadPools => _threadPools; + internal static void Shutdown() { lock (shutdownLock) { - foreach (IHystrixThreadPool pool in threadPools.Values) + foreach (IHystrixThreadPool pool in ThreadPools.Values) { pool.Dispose(); } - threadPools.Clear(); + + ThreadPools.Clear(); } } - } } - diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPoolEventTypeHelper.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPoolEventTypeHelper.cs new file mode 100644 index 0000000..c8b8dfc --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/ThreadPoolEventTypeHelper.cs @@ -0,0 +1,68 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using Steeltoe.CircuitBreaker.Hystrix.Util; +using System; +using System.Collections.Generic; + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public static class ThreadPoolEventTypeHelper + { + private static readonly IList ValueList = new List(); + + public static IList Values + { + get { return ValueList; } + } + + static ThreadPoolEventTypeHelper() + { + ValueList.Add(ThreadPoolEventType.EXECUTED); + ValueList.Add(ThreadPoolEventType.REJECTED); + } + + public static ThreadPoolEventType From(this HystrixRollingNumberEvent @event) + { + switch (@event) + { + case HystrixRollingNumberEvent.THREAD_EXECUTION: + return ThreadPoolEventType.EXECUTED; + case HystrixRollingNumberEvent.THREAD_POOL_REJECTED: + return ThreadPoolEventType.REJECTED; + default: + throw new ArgumentOutOfRangeException("Not an event that can be converted to HystrixEventType.ThreadPool : " + @event); + } + } + + public static ThreadPoolEventType From(this HystrixEventType eventType) + { + switch (eventType) + { + case HystrixEventType.SUCCESS: + return ThreadPoolEventType.EXECUTED; + case HystrixEventType.FAILURE: + return ThreadPoolEventType.EXECUTED; + case HystrixEventType.TIMEOUT: + return ThreadPoolEventType.EXECUTED; + case HystrixEventType.BAD_REQUEST: + return ThreadPoolEventType.EXECUTED; + case HystrixEventType.THREAD_POOL_REJECTED: + return ThreadPoolEventType.REJECTED; + default: + return ThreadPoolEventType.UNKNOWN; + } + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/TimerReference.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/TimerReference.cs similarity index 93% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/TimerReference.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/TimerReference.cs index 1041b25..84fceb5 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/TimerReference.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/TimerReference.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,6 +24,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util internal CancellationTokenSource _tokenSource; internal TimeSpan _period; internal Task _timerTask; + public TimerReference(ITimerListener listener, TimeSpan period) { _listener = listener; @@ -45,14 +45,19 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util Time.WaitUntil(() => { return token.IsCancellationRequested; }, _period.Milliseconds); if (!token.IsCancellationRequested) + { _listener.Tick(); + } } } public virtual void Dispose() { if (!_tokenSource.IsCancellationRequested) + { _tokenSource.Cancel(); + } + _listener = null; _timerTask = null; } diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ActualTime.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ActualTime.cs new file mode 100644 index 0000000..ba10521 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ActualTime.cs @@ -0,0 +1,24 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix.Util +{ + public class ActualTime : ITime + { + public long CurrentTimeInMillis + { + get { return Time.CurrentTimeMillis; } + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicBoolean.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicBoolean.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicBoolean.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicBoolean.cs index 0fe3f16..e73d216 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicBoolean.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicBoolean.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +11,6 @@ // 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. -// using System.Threading; @@ -22,7 +20,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { private int _value; - public AtomicBoolean() : this(false) + public AtomicBoolean() + : this(false) { } @@ -37,6 +36,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { return _value != 0; } + set { this._value = value ? 1 : 0; @@ -51,4 +51,3 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } } } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicInteger.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicInteger.cs similarity index 94% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicInteger.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicInteger.cs index 490f799..6026857 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicInteger.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicInteger.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,18 +11,17 @@ // 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. -// using System.Threading; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { public class AtomicInteger { protected int _value; - public AtomicInteger() : this(0) + public AtomicInteger() + : this(0) { } @@ -38,6 +36,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { return _value; } + set { _value = value; @@ -58,6 +57,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { return Interlocked.Decrement(ref this._value); } + public int GetAndIncrement() { return Interlocked.Increment(ref this._value) - 1; @@ -69,4 +69,3 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } } } - diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicIntegerArray.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicIntegerArray.cs similarity index 84% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicIntegerArray.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicIntegerArray.cs index 4c4b420..05c97a0 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicIntegerArray.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicIntegerArray.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,15 +11,13 @@ // 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. -// - - namespace Steeltoe.CircuitBreaker.Hystrix.Util { public class AtomicIntegerArray : AtomicReferenceArray { - public AtomicIntegerArray(int length) : base(length) + public AtomicIntegerArray(int length) + : base(length) { } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicLong.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicLong.cs similarity index 93% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicLong.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicLong.cs index b6311e5..da09af3 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicLong.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicLong.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,7 +20,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { private long _value; - public AtomicLong() : this(0) + public AtomicLong() + : this(0) { } @@ -36,6 +36,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { return Interlocked.Read(ref _value); } + set { Interlocked.Exchange(ref _value, value); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicReference.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicReference.cs similarity index 85% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicReference.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicReference.cs index f2002ed..01c0a09 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicReference.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicReference.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,14 +14,15 @@ using System.Threading; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { - public class AtomicReference where T : class + public class AtomicReference + where T : class { - private T _value; + private T _value; - public AtomicReference() : this((T) default(T)) + public AtomicReference() + : this(default(T)) { } @@ -37,6 +37,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { return _value; } + set { _value = value; @@ -47,6 +48,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { return Interlocked.CompareExchange(ref this._value, update, expected) == expected; } + public T GetAndSet(T value) { return Interlocked.Exchange(ref this._value, value); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicReferenceArray.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicReferenceArray.cs similarity index 95% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicReferenceArray.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicReferenceArray.cs index cf6cf1d..c0c3fcb 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/AtomicReferenceArray.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/AtomicReferenceArray.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,6 +22,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { this._array = new T[length]; } + public T this[int index] { get @@ -32,6 +32,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util return this._array[index]; } } + set { lock (this._array) @@ -40,13 +41,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } } } + public T[] ToArray() { lock (this._array) { return (T[])this._array.Clone(); } - } public int Length diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ConcurrentDictionaryExtensions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ConcurrentDictionaryExtensions.cs similarity index 86% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ConcurrentDictionaryExtensions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/ConcurrentDictionaryExtensions.cs index 0be4c65..97528f6 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ConcurrentDictionaryExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ConcurrentDictionaryExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,20 +15,24 @@ using System; using System.Collections.Concurrent; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { public static class ConcurrentDictionaryExtensions { public static V GetOrAddEx(this ConcurrentDictionary dict, K key, Func factory) { - V value = default(V); - if (dict.TryGetValue(key, out value)) + if (dict.TryGetValue(key, out V value)) + { return value; + } + lock (dict) { if (dict.TryGetValue(key, out value)) + { return value; + } + return dict.GetOrAdd(key, factory); } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingNumber.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumber.cs similarity index 68% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingNumber.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumber.cs index fe52cae..024bcd5 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingNumber.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumber.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,181 +17,117 @@ using System.Collections; using System.Collections.Generic; using System.Threading; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { public class HystrixRollingNumber { + internal readonly int _timeInMilliseconds; + internal readonly int _numberOfBuckets; + internal readonly int _bucketSizeInMillseconds; - private static ITime ACTUAL_TIME = new ActualTime(); + internal readonly BucketCircularArray _buckets; + internal readonly CumulativeSum _cumulativeSum = new CumulativeSum(); + + private static ITime actual_time = new ActualTime(); private readonly ITime time; - internal readonly int timeInMilliseconds; - internal readonly int numberOfBuckets; - internal readonly int bucketSizeInMillseconds; - internal readonly BucketCircularArray buckets; - internal readonly CumulativeSum cumulativeSum = new CumulativeSum(); - - public HystrixRollingNumber( int timeInMilliseconds, int numberOfBuckets) : - this(ACTUAL_TIME, timeInMilliseconds, numberOfBuckets) + public HystrixRollingNumber(int timeInMilliseconds, int numberOfBuckets) + : this(actual_time, timeInMilliseconds, numberOfBuckets) { - } + /* package for testing */ internal HystrixRollingNumber(ITime time, int timeInMilliseconds, int numberOfBuckets) { this.time = time; - this.timeInMilliseconds = timeInMilliseconds; - this.numberOfBuckets = numberOfBuckets; + this._timeInMilliseconds = timeInMilliseconds; + this._numberOfBuckets = numberOfBuckets; if (timeInMilliseconds % numberOfBuckets != 0) { throw new ArgumentException("The timeInMilliseconds must divide equally into numberOfBuckets. For example 1000/10 is ok, 1000/11 is not."); } - this.bucketSizeInMillseconds = timeInMilliseconds / numberOfBuckets; - buckets = new BucketCircularArray(numberOfBuckets); + this._bucketSizeInMillseconds = timeInMilliseconds / numberOfBuckets; + + _buckets = new BucketCircularArray(numberOfBuckets); } - /** - * Increment the counter in the current bucket by one for the given {@link HystrixRollingNumberEvent} type. - *

- * The {@link HystrixRollingNumberEvent} must be a "counter" type HystrixRollingNumberEvent.isCounter() == true. - * - * @param type - * HystrixRollingNumberEvent defining which counter to increment - */ public void Increment(HystrixRollingNumberEvent type) { GetCurrentBucket().GetAdder(type).Increment(); } - /** - * Add to the counter in the current bucket for the given {@link HystrixRollingNumberEvent} type. - *

- * The {@link HystrixRollingNumberEvent} must be a "counter" type HystrixRollingNumberEvent.isCounter() == true. - * - * @param type - * HystrixRollingNumberEvent defining which counter to add to - * @param value - * long value to be added to the current bucket - */ public void Add(HystrixRollingNumberEvent type, long value) { GetCurrentBucket().GetAdder(type).Add(value); } - /** - * Update a value and retain the max value. - *

- * The {@link HystrixRollingNumberEvent} must be a "max updater" type HystrixRollingNumberEvent.isMaxUpdater() == true. - * - * @param type HystrixRollingNumberEvent defining which counter to retrieve values from - * @param value long value to be given to the max updater - */ public void UpdateRollingMax(HystrixRollingNumberEvent type, long value) { GetCurrentBucket().GetMaxUpdater(type).Update(value); } - /** - * Force a reset of all rolling counters (clear all buckets) so that statistics start being gathered from scratch. - *

- * This does NOT reset the CumulativeSum values. - */ public void Reset() { // if we are resetting, that means the lastBucket won't have a chance to be captured in CumulativeSum, so let's do it here - Bucket lastBucket = buckets.PeekLast; + Bucket lastBucket = _buckets.PeekLast; if (lastBucket != null) { - cumulativeSum.AddBucket(lastBucket); + _cumulativeSum.AddBucket(lastBucket); } // clear buckets so we start over again - buckets.Clear(); + _buckets.Clear(); } - /** - * Get the cumulative sum of all buckets ever since the JVM started without rolling for the given {@link HystrixRollingNumberEvent} type. - *

- * See {@link #getRollingSum(HystrixRollingNumberEvent)} for the rolling sum. - *

- * The {@link HystrixRollingNumberEvent} must be a "counter" type HystrixRollingNumberEvent.isCounter() == true. - * - * @param type HystrixRollingNumberEvent defining which counter to retrieve values from - * @return cumulative sum of all increments and adds for the given {@link HystrixRollingNumberEvent} counter type - */ public long GetCumulativeSum(HystrixRollingNumberEvent type) { // this isn't 100% atomic since multiple threads can be affecting latestBucket & cumulativeSum independently // but that's okay since the count is always a moving target and we're accepting a "point in time" best attempt // we are however putting 'getValueOfLatestBucket' first since it can have side-affects on cumulativeSum whereas the inverse is not true - return GetValueOfLatestBucket(type) + cumulativeSum.Get(type); + return GetValueOfLatestBucket(type) + _cumulativeSum.Get(type); } - /** - * Get the sum of all buckets in the rolling counter for the given {@link HystrixRollingNumberEvent} type. - *

- * The {@link HystrixRollingNumberEvent} must be a "counter" type HystrixRollingNumberEvent.isCounter() == true. - * - * @param type - * HystrixRollingNumberEvent defining which counter to retrieve values from - * @return - * value from the given {@link HystrixRollingNumberEvent} counter type - */ public long GetRollingSum(HystrixRollingNumberEvent type) { Bucket lastBucket = GetCurrentBucket(); if (lastBucket == null) + { return 0; + } long sum = 0; - foreach (Bucket b in buckets) + foreach (Bucket b in _buckets) { sum += b.GetAdder(type).Sum(); } + return sum; } - /** - * Get the value of the latest (current) bucket in the rolling counter for the given {@link HystrixRollingNumberEvent} type. - *

- * The {@link HystrixRollingNumberEvent} must be a "counter" type HystrixRollingNumberEvent.isCounter() == true. - * - * @param type - * HystrixRollingNumberEvent defining which counter to retrieve value from - * @return - * value from latest bucket for given {@link HystrixRollingNumberEvent} counter type - */ public long GetValueOfLatestBucket(HystrixRollingNumberEvent type) { Bucket lastBucket = GetCurrentBucket(); if (lastBucket == null) + { return 0; + } + // we have bucket data so we'll return the lastBucket return lastBucket.Get(type); } - /** - * Get an array of values for all buckets in the rolling counter for the given {@link HystrixRollingNumberEvent} type. - *

- * Index 0 is the oldest bucket. - *

- * The {@link HystrixRollingNumberEvent} must be a "counter" type HystrixRollingNumberEvent.isCounter() == true. - * - * @param type - * HystrixRollingNumberEvent defining which counter to retrieve values from - * @return array of values from each of the rolling buckets for given {@link HystrixRollingNumberEvent} counter type - */ public long[] GetValues(HystrixRollingNumberEvent type) { Bucket lastBucket = GetCurrentBucket(); if (lastBucket == null) + { return new long[0]; + } // get buckets as an array (which is a copy of the current state at this point in time) - Bucket[] bucketArray = buckets.Array; + Bucket[] bucketArray = _buckets.Array; // we have bucket data so we'll return an array of values for all buckets long[] values = new long[bucketArray.Length]; @@ -208,18 +143,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util values[i++] = bucket.GetMaxUpdater(type).Max; } } + return values; } - /** - * Get the max value of values in all buckets for the given {@link HystrixRollingNumberEvent} type. - *

- * The {@link HystrixRollingNumberEvent} must be a "max updater" type HystrixRollingNumberEvent.isMaxUpdater() == true. - * - * @param type - * HystrixRollingNumberEvent defining which "max updater" to retrieve values from - * @return max value for given {@link HystrixRollingNumberEvent} type during rolling window - */ public long GetRollingMaxValue(HystrixRollingNumberEvent type) { long[] values = GetValues(type); @@ -234,8 +161,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } } - //private ReentrantLock newBucketLock = new ReentrantLock(); private object newBucketLock = new object(); + /* package for testing */ internal Bucket GetCurrentBucket() { @@ -245,11 +172,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util /** * Retrieve the latest bucket if the given time is BEFORE the end of the bucket window, otherwise it returns NULL. - * * NOTE: This is thread-safe because it's accessing 'buckets' which is a LinkedBlockingDeque */ - Bucket currentBucket = buckets.PeekLast; - if (currentBucket != null && currentTime < currentBucket.windowStart + this.bucketSizeInMillseconds) + Bucket currentBucket = _buckets.PeekLast; + if (currentBucket != null && currentTime < currentBucket._windowStart + this._bucketSizeInMillseconds) { // if we're within the bucket 'window of time' return the current one // NOTE: We do not worry if we are BEFORE the window in a weird case of where thread scheduling causes that to occur, @@ -263,25 +189,20 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util * The following needs to be synchronized/locked even with a synchronized/thread-safe data structure such as LinkedBlockingDeque because * the logic involves multiple steps to check existence, create an object then insert the object. The 'check' or 'insertion' themselves * are thread-safe by themselves but not the aggregate algorithm, thus we put this entire block of logic inside synchronized. - * * I am using a tryLock if/then (http://download.oracle.com/javase/6/docs/api/java/util/concurrent/locks/Lock.html#tryLock()) * so that a single thread will get the lock and as soon as one thread gets the lock all others will go the 'else' block * and just return the currentBucket until the newBucket is created. This should allow the throughput to be far higher * and only slow down 1 thread instead of blocking all of them in each cycle of creating a new bucket based on some testing * (and it makes sense that it should as well). - * * This means the timing won't be exact to the millisecond as to what data ends up in a bucket, but that's acceptable. * It's not critical to have exact precision to the millisecond, as long as it's rolling, if we can instead reduce the impact synchronization. - * * More importantly though it means that the 'if' block within the lock needs to be careful about what it changes that can still * be accessed concurrently in the 'else' block since we're not completely synchronizing access. - * * For example, we can't have a multi-step process to add a bucket, remove a bucket, then update the sum since the 'else' block of code * can retrieve the sum while this is all happening. The trade-off is that we don't maintain the rolling sum and let readers just iterate * bucket to calculate the sum themselves. This is an example of favoring write-performance instead of read-performance and how the tryLock * versus a synchronized block needs to be accommodated. */ - bool lockTaken = false; Monitor.TryEnter(newBucketLock, ref lockTaken); if (lockTaken) @@ -289,48 +210,50 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util currentTime = time.CurrentTimeInMillis; try { - if (buckets.PeekLast == null) + if (_buckets.PeekLast == null) { // the list is empty so create the first bucket Bucket newBucket = new Bucket(currentTime); - buckets.AddLast(newBucket); + _buckets.AddLast(newBucket); return newBucket; } else { // We go into a loop so that it will create as many buckets as needed to catch up to the current time // as we want the buckets complete even if we don't have transactions during a period of time. - for (int i = 0; i < numberOfBuckets; i++) + for (int i = 0; i < _numberOfBuckets; i++) { // we have at least 1 bucket so retrieve it - Bucket lastBucket = buckets.PeekLast; - if (currentTime < lastBucket.windowStart + this.bucketSizeInMillseconds) + Bucket lastBucket = _buckets.PeekLast; + if (currentTime < lastBucket._windowStart + this._bucketSizeInMillseconds) { // if we're within the bucket 'window of time' return the current one // NOTE: We do not worry if we are BEFORE the window in a weird case of where thread scheduling causes that to occur, // we'll just use the latest as long as we're not AFTER the window return lastBucket; } - else if (currentTime - (lastBucket.windowStart + this.bucketSizeInMillseconds) > timeInMilliseconds) + else if (currentTime - (lastBucket._windowStart + this._bucketSizeInMillseconds) > _timeInMilliseconds) { // the time passed is greater than the entire rolling counter so we want to clear it all and start from scratch Reset(); - + Bucket newBucket = new Bucket(currentTime); - buckets.AddLast(newBucket); + _buckets.AddLast(newBucket); return newBucket; - } else - { // we're past the window so we need to create a new bucket - // create a new bucket and add it as the new 'last' - buckets.AddLast(new Bucket(lastBucket.windowStart + this.bucketSizeInMillseconds)); + { + // we're past the window so we need to create a new bucket + // create a new bucket and add it as the new 'last' + _buckets.AddLast(new Bucket(lastBucket._windowStart + this._bucketSizeInMillseconds)); + // add the lastBucket values to the cumulativeSum - cumulativeSum.AddBucket(lastBucket); + _cumulativeSum.AddBucket(lastBucket); } } + // we have finished the for-loop and created all of the buckets, so return the lastBucket now - return buckets.PeekLast; + return _buckets.PeekLast; } } finally @@ -340,7 +263,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } else { - currentBucket = buckets.PeekLast; + currentBucket = _buckets.PeekLast; if (currentBucket != null) { // we didn't get the lock so just return the latest bucket while another thread creates the next one @@ -350,31 +273,27 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { // the rare scenario where multiple threads raced to create the very first bucket // wait slightly and then use recursion while the other thread finishes creating a bucket - - if (Time.WaitUntil(() => { return buckets.PeekLast != null; }, 500)) + if (Time.WaitUntil(() => { return _buckets.PeekLast != null; }, 500)) { - return buckets.PeekLast; + return _buckets.PeekLast; } else { return null; } - } } - } - internal class Bucket { - public readonly long windowStart; - public readonly LongAdder[] adderForCounterType; - public readonly LongMaxUpdater[] updaterForCounterType; + internal readonly long _windowStart; + internal readonly LongAdder[] _adderForCounterType; + internal readonly LongMaxUpdater[] _updaterForCounterType; public Bucket(long startTime) { - this.windowStart = startTime; + this._windowStart = startTime; /* * We support both LongAdder and LongMaxUpdater in a bucket but don't want the memory allocation @@ -384,23 +303,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util */ // initialize the array of LongAdders - adderForCounterType = new LongAdder[HystrixRollingNumberEventHelper.Values.Count]; + _adderForCounterType = new LongAdder[HystrixRollingNumberEventHelper.Values.Count]; foreach (HystrixRollingNumberEvent type in HystrixRollingNumberEventHelper.Values) { if (HystrixRollingNumberEventHelper.IsCounter(type)) { - adderForCounterType[(int)type] = new LongAdder(); + _adderForCounterType[(int)type] = new LongAdder(); } } - updaterForCounterType = new LongMaxUpdater[HystrixRollingNumberEventHelper.Values.Count]; + _updaterForCounterType = new LongMaxUpdater[HystrixRollingNumberEventHelper.Values.Count]; foreach (HystrixRollingNumberEvent type in HystrixRollingNumberEventHelper.Values) { if (HystrixRollingNumberEventHelper.IsMaxUpdater(type)) { - updaterForCounterType[(int)type] = new LongMaxUpdater(); + _updaterForCounterType[(int)type] = new LongMaxUpdater(); + // initialize to 0 otherwise it is Long.MIN_VALUE - updaterForCounterType[(int)type].Update(0); + _updaterForCounterType[(int)type].Update(0); } } } @@ -409,12 +329,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { if (HystrixRollingNumberEventHelper.IsCounter(type)) { - return adderForCounterType[(int)type].Sum(); + return _adderForCounterType[(int)type].Sum(); } + if (HystrixRollingNumberEventHelper.IsMaxUpdater(type)) { - return updaterForCounterType[(int)type].Max; + return _updaterForCounterType[(int)type].Max; } + throw new InvalidOperationException("Unknown type of event: " + type.ToString()); } @@ -424,7 +346,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { throw new InvalidOperationException("Type is not a Counter: " + type.ToString()); } - return adderForCounterType[(int)type]; + + return _adderForCounterType[(int)type]; } public LongMaxUpdater GetMaxUpdater(HystrixRollingNumberEvent type) @@ -433,19 +356,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { throw new InvalidOperationException("Type is not a MaxUpdater: " + type.ToString()); } - return updaterForCounterType[(int)type]; - } + return _updaterForCounterType[(int)type]; + } } - + internal class CumulativeSum { - readonly LongAdder[] adderForCounterType; - readonly LongMaxUpdater[] updaterForCounterType; + internal readonly LongAdder[] _adderForCounterType; + internal readonly LongMaxUpdater[] _updaterForCounterType; public CumulativeSum() { - /* * We support both LongAdder and LongMaxUpdater in a bucket but don't want the memory allocation * of all types for each so we only allocate the objects if the HystrixRollingNumberEvent matches @@ -454,23 +376,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util */ // initialize the array of LongAdders - adderForCounterType = new LongAdder[HystrixRollingNumberEventHelper.Values.Count]; + _adderForCounterType = new LongAdder[HystrixRollingNumberEventHelper.Values.Count]; foreach (HystrixRollingNumberEvent type in HystrixRollingNumberEventHelper.Values) { if (HystrixRollingNumberEventHelper.IsCounter(type)) { - adderForCounterType[(int)type] = new LongAdder(); + _adderForCounterType[(int)type] = new LongAdder(); } } - updaterForCounterType = new LongMaxUpdater[HystrixRollingNumberEventHelper.Values.Count]; + _updaterForCounterType = new LongMaxUpdater[HystrixRollingNumberEventHelper.Values.Count]; foreach (HystrixRollingNumberEvent type in HystrixRollingNumberEventHelper.Values) { if (HystrixRollingNumberEventHelper.IsMaxUpdater(type)) { - updaterForCounterType[(int)type] = new LongMaxUpdater(); + _updaterForCounterType[(int)type] = new LongMaxUpdater(); + // initialize to 0 otherwise it is Long.MIN_VALUE - updaterForCounterType[(int)type].Update(0); + _updaterForCounterType[(int)type].Update(0); } } } @@ -483,6 +406,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { GetAdder(type).Add(lastBucket.GetAdder(type).Sum()); } + if (HystrixRollingNumberEventHelper.IsMaxUpdater(type)) { GetMaxUpdater(type).Update(lastBucket.GetMaxUpdater(type).Max); @@ -494,12 +418,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { if (HystrixRollingNumberEventHelper.IsCounter(type)) { - return adderForCounterType[(int)type].Sum(); + return _adderForCounterType[(int)type].Sum(); } + if (HystrixRollingNumberEventHelper.IsMaxUpdater(type)) { - return updaterForCounterType[(int)type].Max; + return _updaterForCounterType[(int)type].Max; } + throw new InvalidOperationException("Unknown type of event: " + type.ToString()); } @@ -509,7 +435,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { throw new InvalidOperationException("Type is not a Counter: " + type.ToString()); } - return adderForCounterType[(int)type]; + + return _adderForCounterType[(int)type]; } public LongMaxUpdater GetMaxUpdater(HystrixRollingNumberEvent type) @@ -518,63 +445,59 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { throw new InvalidOperationException("Type is not a MaxUpdater: " + type.ToString()); } - return updaterForCounterType[(int)type]; - } + return _updaterForCounterType[(int)type]; + } } - + internal class BucketCircularArray : IEnumerable { private readonly AtomicReference state; private readonly int dataLength; // we don't resize, we always stay the same, so remember this private readonly int numBuckets; - /** - * Immutable object that is atomically set every time the state of the BucketCircularArray changes - *

- * This handles the compound operations - */ - class ListState + internal class ListState { /* * this is an AtomicReferenceArray and not a normal Array because we're copying the reference * between ListState objects and multiple threads could maintain references across these * compound operations so I want the visibility/concurrency guarantees */ - public readonly AtomicReferenceArray data; - public readonly int size; - public readonly int tail; - public readonly int head; - public readonly BucketCircularArray ca; + internal readonly AtomicReferenceArray _data; + internal readonly int _size; + internal readonly int _tail; + internal readonly int _head; + internal readonly BucketCircularArray _ca; public ListState(BucketCircularArray ca, AtomicReferenceArray data, int head, int tail) { - this.ca = ca; - this.head = head; - this.tail = tail; + this._ca = ca; + this._head = head; + this._tail = tail; if (head == 0 && tail == 0) { - size = 0; + _size = 0; } else { - this.size = (tail + ca.dataLength - head) % ca.dataLength; + this._size = (tail + ca.dataLength - head) % ca.dataLength; } - this.data = data; + + this._data = data; } public Bucket Tail { get { - if (size == 0) + if (_size == 0) { return null; } else { // we want to get the last item, so size()-1 - return data[(Convert(size - 1))]; + return _data[Convert(_size - 1)]; } } } @@ -583,55 +506,36 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { get { - /* * this isn't technically thread-safe since it requires multiple reads on something that can change * but since we never clear the data directly, only increment/decrement head/tail we would never get a NULL * just potentially return stale data which we are okay with doing */ List array = new List(); - for (int i = 0; i < size; i++) + for (int i = 0; i < _size; i++) { - array.Add(data[(Convert(i))]); + array.Add(_data[Convert(i)]); } - return array.ToArray(); - } - } - private ListState IncrementTail() - { - /* if incrementing results in growing larger than 'length' which is the max we should be at, then also increment head (equivalent of removeFirst but done atomically) */ - if (size == ca.numBuckets) - { - // increment tail and head - return new ListState(ca, data, (head + 1) % ca.dataLength, (tail + 1) % ca.dataLength); - } - else - { - // increment only tail - return new ListState(ca, data, head, (tail + 1) % ca.dataLength); + return array.ToArray(); } } public ListState Clear() { - return new ListState(ca, new AtomicReferenceArray(ca.dataLength), 0, 0); + return new ListState(_ca, new AtomicReferenceArray(_ca.dataLength), 0, 0); } public ListState AddBucket(Bucket b) { /* * We could in theory have 2 threads addBucket concurrently and this compound operation would interleave. - *

* This should NOT happen since getCurrentBucket is supposed to be executed by a single thread. - *

* If it does happen, it's not a huge deal as incrementTail() will be protected by compareAndSet and one of the two addBucket calls will succeed with one of the Buckets. - *

* In either case, a single Bucket will be returned as "last" and data loss should not occur and everything keeps in sync for head/tail. - *

* Also, it's fine to set it before incrementTail because nothing else should be referencing that index position until incrementTail occurs. */ - data[tail] = b; + _data[_tail] = b; return IncrementTail(); } @@ -639,15 +543,30 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util // always 0) and calculates the index within elementData private int Convert(int index) { - return (index + head) % ca.dataLength; + return (index + _head) % _ca.dataLength; + } + + private ListState IncrementTail() + { + /* if incrementing results in growing larger than 'length' which is the max we should be at, then also increment head (equivalent of removeFirst but done atomically) */ + if (_size == _ca.numBuckets) + { + // increment tail and head + return new ListState(_ca, _data, (_head + 1) % _ca.dataLength, (_tail + 1) % _ca.dataLength); + } + else + { + // increment only tail + return new ListState(_ca, _data, _head, (_tail + 1) % _ca.dataLength); + } } } public BucketCircularArray(int size) { - AtomicReferenceArray _buckets = new AtomicReferenceArray(size + 1); // + 1 as extra room for the add/remove; - state = new AtomicReference(new ListState(this, _buckets, 0, 0)); - dataLength = _buckets.Length; + AtomicReferenceArray buckets = new AtomicReferenceArray(size + 1); // + 1 as extra room for the add/remove; + state = new AtomicReference(new ListState(this, buckets, 0, 0)); + dataLength = buckets.Length; numBuckets = size; } @@ -660,11 +579,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util * a single thread protected by a tryLock, but there is at least 1 other place (at time of writing this comment) * where reset can be called from (CircuitBreaker.markSuccess after circuit was tripped) so it can * in an edge-case conflict. - * * Instead of trying to determine if someone already successfully called clear() and we should skip * we will have both calls reset the circuit, even if that means losing data added in between the two * depending on thread scheduling. - * * The rare scenario in which that would occur, we'll accept the possible data loss while clearing it * since the code has stated its desire to clear() anyways. */ @@ -677,10 +594,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } } - public void AddLast(Bucket o) { ListState currentState = state.Value; + // create new version of state (what we want it to become) ListState newState = currentState.AddBucket(o); @@ -711,7 +628,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { // the size can also be worked out each time as: // return (tail + data.length() - head) % data.length(); - get { return state.Value.size; } + get { return state.Value._size; } } IEnumerator IEnumerable.GetEnumerator() @@ -734,9 +651,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { get { return state.Value.Array; } } - } - } - } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEvent.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEvent.cs new file mode 100644 index 0000000..9347a19 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEvent.cs @@ -0,0 +1,41 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix.Util +{ + public enum HystrixRollingNumberEvent + { + SUCCESS, + FAILURE, + TIMEOUT, + SHORT_CIRCUITED, + THREAD_POOL_REJECTED, + SEMAPHORE_REJECTED, + BAD_REQUEST, + FALLBACK_SUCCESS, + FALLBACK_FAILURE, + FALLBACK_REJECTION, + FALLBACK_MISSING, + EXCEPTION_THROWN, + COMMAND_MAX_ACTIVE, + EMIT, + FALLBACK_EMIT, + THREAD_EXECUTION, + THREAD_MAX_ACTIVE, + COLLAPSED, + RESPONSE_FROM_CACHE, + COLLAPSER_REQUEST_BATCHED, + COLLAPSER_BATCH + } +} \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingNumberEvent.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEventHelper.cs similarity index 68% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingNumberEvent.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEventHelper.cs index 1edacfb..b4550e8 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingNumberEvent.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingNumberEventHelper.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,67 +12,45 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System.Collections.Generic; using System; +using System.Collections.Generic; namespace Steeltoe.CircuitBreaker.Hystrix.Util { - public enum HystrixRollingNumberEvent + internal static class HystrixRollingNumberEventHelper { - SUCCESS, - FAILURE, - TIMEOUT, - SHORT_CIRCUITED, - THREAD_POOL_REJECTED, - SEMAPHORE_REJECTED, - BAD_REQUEST, - FALLBACK_SUCCESS, - FALLBACK_FAILURE, - FALLBACK_REJECTION, - FALLBACK_MISSING, - EXCEPTION_THROWN, - COMMAND_MAX_ACTIVE, - EMIT, - FALLBACK_EMIT, - THREAD_EXECUTION, - THREAD_MAX_ACTIVE, - COLLAPSED, - RESPONSE_FROM_CACHE, - COLLAPSER_REQUEST_BATCHED, - COLLAPSER_BATCH - } - public static class HystrixRollingNumberEventHelper - { - private static readonly IList valueList = new List(); + private static readonly IList _valueList = new List(); static HystrixRollingNumberEventHelper() { - valueList.Add(HystrixRollingNumberEvent.SUCCESS); - valueList.Add(HystrixRollingNumberEvent.FAILURE); - valueList.Add(HystrixRollingNumberEvent.TIMEOUT); - valueList.Add(HystrixRollingNumberEvent.SHORT_CIRCUITED); - valueList.Add(HystrixRollingNumberEvent.THREAD_POOL_REJECTED); - valueList.Add(HystrixRollingNumberEvent.SEMAPHORE_REJECTED); - valueList.Add(HystrixRollingNumberEvent.BAD_REQUEST); - valueList.Add(HystrixRollingNumberEvent.FALLBACK_SUCCESS); - valueList.Add(HystrixRollingNumberEvent.FALLBACK_FAILURE); - valueList.Add(HystrixRollingNumberEvent.FALLBACK_REJECTION); - valueList.Add(HystrixRollingNumberEvent.FALLBACK_MISSING); - valueList.Add(HystrixRollingNumberEvent.EXCEPTION_THROWN); - valueList.Add(HystrixRollingNumberEvent.COMMAND_MAX_ACTIVE); - valueList.Add(HystrixRollingNumberEvent.EMIT); - valueList.Add(HystrixRollingNumberEvent.FALLBACK_EMIT); - valueList.Add(HystrixRollingNumberEvent.THREAD_EXECUTION); - valueList.Add(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE); - valueList.Add(HystrixRollingNumberEvent.COLLAPSED); - valueList.Add(HystrixRollingNumberEvent.RESPONSE_FROM_CACHE); - valueList.Add(HystrixRollingNumberEvent.COLLAPSER_REQUEST_BATCHED); - valueList.Add(HystrixRollingNumberEvent.COLLAPSER_BATCH); + _valueList.Add(HystrixRollingNumberEvent.SUCCESS); + _valueList.Add(HystrixRollingNumberEvent.FAILURE); + _valueList.Add(HystrixRollingNumberEvent.TIMEOUT); + _valueList.Add(HystrixRollingNumberEvent.SHORT_CIRCUITED); + _valueList.Add(HystrixRollingNumberEvent.THREAD_POOL_REJECTED); + _valueList.Add(HystrixRollingNumberEvent.SEMAPHORE_REJECTED); + _valueList.Add(HystrixRollingNumberEvent.BAD_REQUEST); + _valueList.Add(HystrixRollingNumberEvent.FALLBACK_SUCCESS); + _valueList.Add(HystrixRollingNumberEvent.FALLBACK_FAILURE); + _valueList.Add(HystrixRollingNumberEvent.FALLBACK_REJECTION); + _valueList.Add(HystrixRollingNumberEvent.FALLBACK_MISSING); + _valueList.Add(HystrixRollingNumberEvent.EXCEPTION_THROWN); + _valueList.Add(HystrixRollingNumberEvent.COMMAND_MAX_ACTIVE); + _valueList.Add(HystrixRollingNumberEvent.EMIT); + _valueList.Add(HystrixRollingNumberEvent.FALLBACK_EMIT); + _valueList.Add(HystrixRollingNumberEvent.THREAD_EXECUTION); + _valueList.Add(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE); + _valueList.Add(HystrixRollingNumberEvent.COLLAPSED); + _valueList.Add(HystrixRollingNumberEvent.RESPONSE_FROM_CACHE); + _valueList.Add(HystrixRollingNumberEvent.COLLAPSER_REQUEST_BATCHED); + _valueList.Add(HystrixRollingNumberEvent.COLLAPSER_BATCH); } + public static IList Values { - get { return valueList; } + get { return _valueList; } } + public static HystrixRollingNumberEvent From(HystrixEventType eventType) { switch (eventType) @@ -114,6 +91,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util throw new ArgumentOutOfRangeException("Unknown HystrixEventType : " + eventType); } } + public static bool IsCounter(HystrixRollingNumberEvent @event) { switch (@event) @@ -142,6 +120,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util return false; } } + public static bool IsMaxUpdater(HystrixRollingNumberEvent @event) { switch (@event) @@ -151,9 +130,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util return true; default: return false; - } } } - -} \ No newline at end of file +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingPercentile.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingPercentile.cs similarity index 73% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingPercentile.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingPercentile.cs index d1c136f..d7dc750 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixRollingPercentile.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixRollingPercentile.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,58 +21,53 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { public class HystrixRollingPercentile { + internal readonly BucketCircularArray _buckets; + internal readonly int _timeInMilliseconds; + internal readonly int _numberOfBuckets; + internal readonly int _bucketDataLength; + internal readonly int _bucketSizeInMilliseconds; + internal readonly bool _enabled; - //private static readonly Logger logger = LoggerFactory.getLogger(HystrixRollingPercentile.class); - - private static ITime ACTUAL_TIME = new ActualTime(); + private static ITime actual_time = new ActualTime(); private readonly ITime time; - internal readonly BucketCircularArray buckets; - internal readonly int timeInMilliseconds; - internal readonly int numberOfBuckets; - internal readonly int bucketDataLength; - internal readonly int bucketSizeInMilliseconds; - internal readonly bool enabled; /* * This will get flipped each time a new bucket is created. */ /* package for testing */ - volatile PercentileSnapshot currentPercentileSnapshot = new PercentileSnapshot(0); + private volatile PercentileSnapshot currentPercentileSnapshot = new PercentileSnapshot(0); - public HystrixRollingPercentile(int timeInMilliseconds, int numberOfBuckets, int bucketDataLength, bool enabled) : - this(ACTUAL_TIME, timeInMilliseconds, numberOfBuckets, bucketDataLength, enabled) + public HystrixRollingPercentile(int timeInMilliseconds, int numberOfBuckets, int bucketDataLength, bool enabled) + : this(actual_time, timeInMilliseconds, numberOfBuckets, bucketDataLength, enabled) { - } + /* package for testing */ internal HystrixRollingPercentile(ITime time, int timeInMilliseconds, int numberOfBuckets, int bucketDataLength, bool enabled) { this.time = time; - this.timeInMilliseconds = timeInMilliseconds; - this.numberOfBuckets = numberOfBuckets; - this.bucketDataLength = bucketDataLength; - this.enabled = enabled; + this._timeInMilliseconds = timeInMilliseconds; + this._numberOfBuckets = numberOfBuckets; + this._bucketDataLength = bucketDataLength; + this._enabled = enabled; - if (this.timeInMilliseconds % this.numberOfBuckets != 0) + if (this._timeInMilliseconds % this._numberOfBuckets != 0) { throw new ArgumentException("The timeInMilliseconds must divide equally into numberOfBuckets. For example 1000/10 is ok, 1000/11 is not."); } - this.bucketSizeInMilliseconds = this.timeInMilliseconds / this.numberOfBuckets; - buckets = new BucketCircularArray(this.numberOfBuckets); + this._bucketSizeInMilliseconds = this._timeInMilliseconds / this._numberOfBuckets; + + _buckets = new BucketCircularArray(this._numberOfBuckets); } - /** - * Add value (or values) to current bucket. - * - * @param value - * Value to be stored in current bucket such as execution latency in milliseconds - */ public void AddValue(params int[] value) { /* no-op if disabled */ - if (!enabled) + if (!_enabled) + { return; + } foreach (int v in value) { @@ -81,65 +75,65 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { var cbucket = GetCurrentBucket(); if (cbucket != null) - cbucket.data.AddValue(v); + { + cbucket._data.AddValue(v); + } } - catch (Exception ) + catch (Exception) { - //logger.error("Failed to add value: " + v, e); + // logger.error("Failed to add value: " + v, e); } } } - /** - * Compute a percentile from the underlying rolling buckets of values. - *

- * For performance reasons it maintains a single snapshot of the sorted values from all buckets that is re-generated each time the bucket rotates. - *

- * This means that if a bucket is 5000ms, then this method will re-compute a percentile at most once every 5000ms. - * - * @param percentile - * value such as 99 (99th percentile), 99.5 (99.5th percentile), 50 (median, 50th percentile) to compute and retrieve percentile from rolling buckets. - * @return int percentile value - */ public int GetPercentile(double percentile) { /* no-op if disabled */ - if (!enabled) + if (!_enabled) + { return -1; + } // force logic to move buckets forward in case other requests aren't making it happen GetCurrentBucket(); + // fetch the current snapshot return CurrentPercentileSnapshot.GetPercentile(percentile); } - /** - * This returns the mean (average) of all values in the current snapshot. This is not a percentile but often desired so captured and exposed here. - * - * @return mean of all values - */ public int Mean { get { /* no-op if disabled */ - if (!enabled) + if (!_enabled) + { return -1; + } // force logic to move buckets forward in case other requests aren't making it happen GetCurrentBucket(); + // fetch the current snapshot return CurrentPercentileSnapshot.Mean; } } - /** - * This will retrieve the current snapshot or create a new one if one does not exist. - *

- * It will NOT include data from the current bucket, but all previous buckets. - *

- * It remains cached until the next bucket rotates at which point a new one will be created. - */ + public void Reset() + { + /* no-op if disabled */ + if (!_enabled) + { + return; + } + + // clear buckets so we start over again + _buckets.Clear(); + + // and also make sure the percentile snapshot gets reset + currentPercentileSnapshot = new PercentileSnapshot(_buckets.Array); + } + private PercentileSnapshot CurrentPercentileSnapshot { get { return currentPercentileSnapshot; } @@ -155,11 +149,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util /** * Retrieve the latest bucket if the given time is BEFORE the end of the bucket window, otherwise it returns NULL. - * * NOTE: This is thread-safe because it's accessing 'buckets' which is a LinkedBlockingDeque */ - Bucket currentBucket = buckets.PeekLast; - if (currentBucket != null && currentTime < currentBucket.windowStart + this.bucketSizeInMilliseconds) + Bucket currentBucket = _buckets.PeekLast; + if (currentBucket != null && currentTime < currentBucket._windowStart + this._bucketSizeInMilliseconds) { // if we're within the bucket 'window of time' return the current one // NOTE: We do not worry if we are BEFORE the window in a weird case of where thread scheduling causes that to occur, @@ -173,25 +166,20 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util * The following needs to be synchronized/locked even with a synchronized/thread-safe data structure such as LinkedBlockingDeque because * the logic involves multiple steps to check existence, create an object then insert the object. The 'check' or 'insertion' themselves * are thread-safe by themselves but not the aggregate algorithm, thus we put this entire block of logic inside synchronized. - * * I am using a tryLock if/then (http://download.oracle.com/javase/6/docs/api/java/util/concurrent/locks/Lock.html#tryLock()) * so that a single thread will get the lock and as soon as one thread gets the lock all others will go the 'else' block * and just return the currentBucket until the newBucket is created. This should allow the throughput to be far higher * and only slow down 1 thread instead of blocking all of them in each cycle of creating a new bucket based on some testing * (and it makes sense that it should as well). - * * This means the timing won't be exact to the millisecond as to what data ends up in a bucket, but that's acceptable. * It's not critical to have exact precision to the millisecond, as long as it's rolling, if we can instead reduce the impact synchronization. - * * More importantly though it means that the 'if' block within the lock needs to be careful about what it changes that can still * be accessed concurrently in the 'else' block since we're not completely synchronizing access. - * * For example, we can't have a multi-step process to add a bucket, remove a bucket, then update the sum since the 'else' block of code * can retrieve the sum while this is all happening. The trade-off is that we don't maintain the rolling sum and let readers just iterate * bucket to calculate the sum themselves. This is an example of favoring write-performance instead of read-performance and how the tryLock * versus a synchronized block needs to be accommodated. */ - bool lockTaken = false; Monitor.TryEnter(newBucketLock, ref lockTaken); if (lockTaken) @@ -199,49 +187,54 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util currentTime = time.CurrentTimeInMillis; try { - if (buckets.PeekLast == null) + if (_buckets.PeekLast == null) { // the list is empty so create the first bucket - Bucket newBucket = new Bucket(currentTime, bucketDataLength); - buckets.AddLast(newBucket); + Bucket newBucket = new Bucket(currentTime, _bucketDataLength); + _buckets.AddLast(newBucket); return newBucket; } else { // We go into a loop so that it will create as many buckets as needed to catch up to the current time // as we want the buckets complete even if we don't have transactions during a period of time. - for (int i = 0; i < numberOfBuckets; i++) + for (int i = 0; i < _numberOfBuckets; i++) { // we have at least 1 bucket so retrieve it - Bucket lastBucket = buckets.PeekLast; - if (currentTime < lastBucket.windowStart + this.bucketSizeInMilliseconds) + Bucket lastBucket = _buckets.PeekLast; + if (currentTime < lastBucket._windowStart + this._bucketSizeInMilliseconds) { // if we're within the bucket 'window of time' return the current one // NOTE: We do not worry if we are BEFORE the window in a weird case of where thread scheduling causes that to occur, // we'll just use the latest as long as we're not AFTER the window return lastBucket; } - else if (currentTime - (lastBucket.windowStart + this.bucketSizeInMilliseconds) > timeInMilliseconds) + else if (currentTime - (lastBucket._windowStart + this._bucketSizeInMilliseconds) > _timeInMilliseconds) { // the time passed is greater than the entire rolling counter so we want to clear it all and start from scratch Reset(); + // recursively call getCurrentBucket which will create a new bucket and return it - //return GetCurrentBucket(); - Bucket newBucket = new Bucket(currentTime, bucketDataLength); - buckets.AddLast(newBucket); + // return GetCurrentBucket(); + Bucket newBucket = new Bucket(currentTime, _bucketDataLength); + _buckets.AddLast(newBucket); return newBucket; } else - { // we're past the window so we need to create a new bucket - Bucket[] allBuckets = buckets.Array; + { + // we're past the window so we need to create a new bucket + Bucket[] allBuckets = _buckets.Array; + // create a new bucket and add it as the new 'last' (once this is done other threads will start using it on subsequent retrievals) - buckets.AddLast(new Bucket(lastBucket.windowStart + this.bucketSizeInMilliseconds, bucketDataLength)); + _buckets.AddLast(new Bucket(lastBucket._windowStart + this._bucketSizeInMilliseconds, _bucketDataLength)); + // we created a new bucket so let's re-generate the PercentileSnapshot (not including the new bucket) currentPercentileSnapshot = new PercentileSnapshot(allBuckets); } } + // we have finished the for-loop and created all of the buckets, so return the lastBucket now - return buckets.PeekLast; + return _buckets.PeekLast; } } finally @@ -251,7 +244,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } else { - currentBucket = buckets.PeekLast; + currentBucket = _buckets.PeekLast; if (currentBucket != null) { // we didn't get the lock so just return the latest bucket while another thread creates the next one @@ -261,47 +254,28 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { // the rare scenario where multiple threads raced to create the very first bucket // wait slightly and then use recursion while the other thread finishes creating a bucket - if (Time.WaitUntil(() => { return buckets.PeekLast != null; }, 500)) + if (Time.WaitUntil(() => { return _buckets.PeekLast != null; }, 500)) { - return buckets.PeekLast; + return _buckets.PeekLast; } else { return null; } - } } } - /** - * Force a reset so that percentiles start being gathered from scratch. - */ - public void Reset() - { - /* no-op if disabled */ - if (!enabled) - return; - - // clear buckets so we start over again - buckets.Clear(); - - // and also make sure the percentile snapshot gets reset - currentPercentileSnapshot = new PercentileSnapshot(buckets.Array); - } - - - internal class PercentileBucketData { - public readonly int length; - public readonly AtomicIntegerArray list; - public readonly AtomicInteger index = new AtomicInteger(); + internal readonly int _length; + internal readonly AtomicIntegerArray _list; + internal readonly AtomicInteger _index = new AtomicInteger(); public PercentileBucketData(int dataLength) { - this.length = dataLength; - this.list = new AtomicIntegerArray(dataLength); + this._length = dataLength; + this._list = new AtomicIntegerArray(dataLength); } public void AddValue(params int[] latency) @@ -309,7 +283,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util foreach (int l in latency) { /* We just wrap around the beginning and over-write if we go past 'dataLength' as that will effectively cause us to "sample" the most recent data */ - list[index.GetAndIncrement() % length] = l; + _list[_index.GetAndIncrement() % _length] = l; + // TODO Alternative to AtomicInteger? The getAndIncrement may be a source of contention on high throughput circuits on large multi-core systems. // LongAdder isn't suited to this as it is not consistent. Perhaps a different data structure that doesn't need indexed adds? // A threadlocal data storage that only aggregates when fetched would be ideal. Similar to LongAdder except for accumulating lists of data. @@ -320,17 +295,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { get { - if (index.Value > list.Length) + if (_index.Value > _list.Length) { - return list.Length; + return _list.Length; } else { - return index.Value; + return _index.Value; } } } - } internal class PercentileSnapshot @@ -343,26 +317,29 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util public PercentileSnapshot(Bucket[] buckets) { int lengthFromBuckets = 0; + // we need to calculate it dynamically as it could have been changed by properties (rare, but possible) // also this way we capture the actual index size rather than the max so size the int[] to only what we need foreach (Bucket bd in buckets) { - lengthFromBuckets += bd.data.length; + lengthFromBuckets += bd._data._length; } + data = new int[lengthFromBuckets]; int index = 0; int sum = 0; foreach (Bucket bd in buckets) { - PercentileBucketData pbd = bd.data; + PercentileBucketData pbd = bd._data; int length = pbd.Length; for (int i = 0; i < length; i++) { - int v = pbd.list[i]; + int v = pbd._list[i]; this.data[index++] = v; sum += v; } } + this.length = index; if (this.length == 0) { @@ -387,6 +364,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { sum += v; } + this.mean = sum / this.length; Array.Sort(this.data, 0, length); @@ -398,25 +376,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util get { return mean; } } - /** - * Provides percentile computation. - */ public int GetPercentile(double percentile) { if (length == 0) { return 0; } + return ComputePercentile(percentile); } - /** - * @see Percentile (Wikipedia) - * @see Percentile - * - * @param percent percentile of data desired - * @return data at the asked-for percentile. Interpolation is used if exactness is not possible - */ private int ComputePercentile(double percent) { // Some just-in-case edge cases @@ -439,7 +408,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util // linear interpolation between closest ranks int iLow = (int)Math.Floor(rank); int iHigh = (int)Math.Ceiling(rank); - //assert 0 <= iLow && iLow <= rank && rank <= iHigh && iHigh <= length; + + // assert 0 <= iLow && iLow <= rank && rank <= iHigh && iHigh <= length; // assert(iHigh - iLow) <= 1; if (iHigh >= length) { @@ -453,65 +423,59 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util else { // Interpolate between the two bounding values - return (int)(data[iLow] + (rank - iLow) * (data[iHigh] - data[iLow])); + return (int)(data[iLow] + ((rank - iLow) * (data[iHigh] - data[iLow]))); } } - } internal class BucketCircularArray : IEnumerable { - private readonly AtomicReference state; private readonly int dataLength; // we don't resize, we always stay the same, so remember this private readonly int numBuckets; - /** - * Immutable object that is atomically set every time the state of the BucketCircularArray changes - *

- * This handles the compound operations - */ - class ListState + internal class ListState { /* * this is an AtomicReferenceArray and not a normal Array because we're copying the reference * between ListState objects and multiple threads could maintain references across these * compound operations so I want the visibility/concurrency guarantees */ - public readonly AtomicReferenceArray data; - public readonly int size; - public readonly int tail; - public readonly int head; - public BucketCircularArray cb; + internal readonly AtomicReferenceArray _data; + internal readonly int _size; + internal readonly int _tail; + internal readonly int _head; + internal BucketCircularArray _cb; public ListState(BucketCircularArray cb, AtomicReferenceArray data, int head, int tail) { - this.cb = cb; - this.head = head; - this.tail = tail; + this._cb = cb; + this._head = head; + this._tail = tail; if (head == 0 && tail == 0) { - size = 0; + _size = 0; } else { - this.size = (tail + cb.dataLength - head) % cb.dataLength; + this._size = (tail + cb.dataLength - head) % cb.dataLength; } - this.data = data; + + this._data = data; } public Bucket Tail { get { - if (size == 0) + if (_size == 0) { return null; } else { // we want to get the last item, so size()-1 - return data[(Convert(size - 1))]; + return _data[Convert(_size - 1)]; } } } @@ -526,48 +490,30 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util * just potentially return stale data which we are okay with doing */ List array = new List(); - for (int i = 0; i < size; i++) + for (int i = 0; i < _size; i++) { - array.Add(data[(Convert(i))]); + array.Add(_data[Convert(i)]); } - return array.ToArray(); - } - } - private ListState IncrementTail() - { - /* if incrementing results in growing larger than 'length' which is the max we should be at, then also increment head (equivalent of removeFirst but done atomically) */ - if (size == cb.numBuckets) - { - // increment tail and head - return new ListState(cb, data, (head + 1) % cb.dataLength, (tail + 1) % cb.dataLength); - } - else - { - // increment only tail - return new ListState(cb, data, head, (tail + 1) % cb.dataLength); + return array.ToArray(); } } public ListState Clear() { - return new ListState(cb, new AtomicReferenceArray(cb.dataLength), 0, 0); + return new ListState(_cb, new AtomicReferenceArray(_cb.dataLength), 0, 0); } public ListState AddBucket(Bucket b) { /* * We could in theory have 2 threads addBucket concurrently and this compound operation would interleave. - *

* This should NOT happen since getCurrentBucket is supposed to be executed by a single thread. - *

* If it does happen, it's not a huge deal as incrementTail() will be protected by compareAndSet and one of the two addBucket calls will succeed with one of the Buckets. - *

* In either case, a single Bucket will be returned as "last" and data loss should not occur and everything keeps in sync for head/tail. - *

* Also, it's fine to set it before incrementTail because nothing else should be referencing that index position until incrementTail occurs. */ - data[tail] = b; + _data[_tail] = b; return IncrementTail(); } @@ -575,15 +521,30 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util // always 0) and calculates the index within elementData private int Convert(int index) { - return (index + head) % cb.dataLength; + return (index + _head) % _cb.dataLength; + } + + private ListState IncrementTail() + { + /* if incrementing results in growing larger than 'length' which is the max we should be at, then also increment head (equivalent of removeFirst but done atomically) */ + if (_size == _cb.numBuckets) + { + // increment tail and head + return new ListState(_cb, _data, (_head + 1) % _cb.dataLength, (_tail + 1) % _cb.dataLength); + } + else + { + // increment only tail + return new ListState(_cb, _data, _head, (_tail + 1) % _cb.dataLength); + } } } public BucketCircularArray(int size) { - AtomicReferenceArray _buckets = new AtomicReferenceArray(size + 1); // + 1 as extra room for the add/remove; - state = new AtomicReference(new ListState(this, _buckets, 0, 0)); - dataLength = _buckets.Length; + AtomicReferenceArray buckets = new AtomicReferenceArray(size + 1); // + 1 as extra room for the add/remove; + state = new AtomicReference(new ListState(this, buckets, 0, 0)); + dataLength = buckets.Length; numBuckets = size; } @@ -596,11 +557,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util * a single thread protected by a tryLock, but there is at least 1 other place (at time of writing this comment) * where reset can be called from (CircuitBreaker.markSuccess after circuit was tripped) so it can * in an edge-case conflict. - * * Instead of trying to determine if someone already successfully called clear() and we should skip * we will have both calls reset the circuit, even if that means losing data added in between the two * depending on thread scheduling. - * * The rare scenario in which that would occur, we'll accept the possible data loss while clearing it * since the code has stated its desire to clear() anyways. */ @@ -613,10 +572,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } } - public void AddLast(Bucket o) { ListState currentState = state.Value; + // create new version of state (what we want it to become) ListState newState = currentState.AddBucket(o); @@ -642,7 +601,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { // the size can also be worked out each time as: // return (tail + data.length() - head) % data.length(); - get { return state.Value.size; } + get { return state.Value._size; } } public Bucket PeekLast @@ -665,21 +624,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { get { return state.Value.Array; } } - } internal class Bucket { - public readonly long windowStart; - public readonly PercentileBucketData data; + internal readonly long _windowStart; + internal readonly PercentileBucketData _data; public Bucket(long startTime, int bucketDataLength) { - this.windowStart = startTime; - this.data = new PercentileBucketData(bucketDataLength); + this._windowStart = startTime; + this._data = new PercentileBucketData(bucketDataLength); } - } } - } \ No newline at end of file diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixTimer.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixTimer.cs similarity index 91% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixTimer.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixTimer.cs index ee2147b..06d1b0c 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/HystrixTimer.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/HystrixTimer.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,12 +15,11 @@ using System; using System.Collections.Generic; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { public class HystrixTimer { - private static HystrixTimer INSTANCE = new HystrixTimer(); + private static HystrixTimer instance = new HystrixTimer(); private List timerList = new List(); private object _lock = new object(); @@ -32,7 +30,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util public static HystrixTimer GetInstance() { - return INSTANCE; + return instance; } public static void Reset() @@ -59,7 +57,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util return refr; } - - } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ITime.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ITime.cs new file mode 100644 index 0000000..bd249ad --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ITime.cs @@ -0,0 +1,24 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +namespace Steeltoe.CircuitBreaker.Hystrix.Util +{ + public interface ITime + { + long CurrentTimeInMillis + { + get; + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ITimerListener.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ITimerListener.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ITimerListener.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/ITimerListener.cs index bebfbc8..678d6d4 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ITimerListener.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ITimerListener.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,13 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. - namespace Steeltoe.CircuitBreaker.Hystrix.Util { public interface ITimerListener { void Tick(); - int IntervalTimeInMilliseconds { get; } + int IntervalTimeInMilliseconds { get; } } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/LongAdder.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/LongAdder.cs similarity index 92% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/LongAdder.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/LongAdder.cs index 95ec78a..c3d1b67 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/LongAdder.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/LongAdder.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,12 +16,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { public class LongAdder { - AtomicLong _value = new AtomicLong(0); + private AtomicLong _value = new AtomicLong(0); public void Increment() { this.Add(1); } + public void Decrement() { this.Add(-1); @@ -32,6 +32,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util { this._value.AddAndGet(value); } + public long Sum() { return this._value.Value; diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/LongMaxUpdater.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/LongMaxUpdater.cs similarity index 85% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/LongMaxUpdater.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/LongMaxUpdater.cs index 35f7739..54cf1e0 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/LongMaxUpdater.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/LongMaxUpdater.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,12 +14,11 @@ using System; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { public class LongMaxUpdater { - private readonly AtomicLong _value = new AtomicLong(Int64.MinValue); + private readonly AtomicLong _value = new AtomicLong(long.MinValue); public void Update(long value) { @@ -38,6 +36,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } } } + public long Max { get { return _value.Value; } @@ -45,13 +44,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util public void Reset() { - _value.GetAndSet(Int64.MinValue); + _value.GetAndSet(long.MinValue); } public long MaxThenReset() { - return _value.GetAndSet(Int64.MinValue); + return _value.GetAndSet(long.MinValue); } + public override string ToString() { return _value.Value.ToString(); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ObservableExtensions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ObservableExtensions.cs similarity index 72% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ObservableExtensions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/ObservableExtensions.cs index 3a20201..9033d96 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/ObservableExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/ObservableExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,23 +15,8 @@ using System; using System.Reactive.Linq; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { - //public class OnSubscribeObservable : ObservableBase - //{ - // private Action onSubscribe; - - // public OnSubscribeObservable(Action onSubscribe) - // { - // this.onSubscribe = onSubscribe; - // } - - // protected override IDisposable SubscribeCore(IObserver observer) - // { - // throw new NotImplementedException(); - // } - //} public static class ObservableExtensions { public static IObservable OnSubscribe(this IObservable source, Action onSubscribe) @@ -43,8 +27,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util var d = source.Subscribe(o); return d; }); - } + public static IObservable OnDispose(this IObservable source, Action action) { return source.Finally(action); diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/SemaphoreSlimExtensions.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/SemaphoreSlimExtensions.cs similarity index 91% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/SemaphoreSlimExtensions.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/SemaphoreSlimExtensions.cs index 5586191..7b1978b 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/SemaphoreSlimExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/SemaphoreSlimExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,7 +21,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util public static bool TryAcquire(this SemaphoreSlim sema) { if (sema == null) + { return true; + } + return sema.Wait(1); } } diff --git a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/Time.cs b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/Time.cs similarity index 82% rename from src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/Time.cs rename to src/Steeltoe.CircuitBreaker.HystrixBase/Util/Time.cs index 8b09eef..a17b86c 100644 --- a/src/Steeltoe.CircuitBreaker.Hystrix.Core/Util/Time.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixBase/Util/Time.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,28 +15,12 @@ using System; using System.Threading; - namespace Steeltoe.CircuitBreaker.Hystrix.Util { - public interface ITime - { - long CurrentTimeInMillis - { - get; - } - } - - public class ActualTime : ITime - { - public long CurrentTimeInMillis - { - get { return Time.CurrentTimeMillis; } - } - } - public static class Time { private static DateTime baseTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + public static long CurrentTimeMillis { get @@ -45,6 +28,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util return DateTime.Now.Ticks / 10000; } } + public static long CurrentTimeMillisJava { get @@ -53,9 +37,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util return javaTicks / 10000; } } + public static bool WaitUntil(Func check, int maxWaitMilli) { - SpinWait sw = new SpinWait(); + SpinWait sw = default(SpinWait); long start = DateTime.Now.Ticks; long ticksToWait = maxWaitMilli * 10000; @@ -69,16 +54,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util } sw.SpinOnce(); - } - return true; + return true; } + public static void Wait(int maxWaitMilli) { WaitUntil(() => { return false; }, maxWaitMilli); } - } - } diff --git a/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixApplicationBuilderExtensions.cs b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixApplicationBuilderExtensions.cs index e6f9b8a..5cbad14 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixApplicationBuilderExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixApplicationBuilderExtensions.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using Microsoft.AspNetCore.Builder; - +using System; namespace Steeltoe.CircuitBreaker.Hystrix { @@ -27,7 +25,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix { throw new ArgumentNullException(nameof(builder)); } - + return builder.UseMiddleware(); } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddleware.cs b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddleware.cs index badffdd..1788869 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddleware.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddleware.cs @@ -1,5 +1,4 @@ -// -// Copyright 2017 the original author or authors. +// Copyright 2017 the original author or authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,7 +19,6 @@ using System.Collections.Generic; using System.Threading.Tasks; namespace Steeltoe.CircuitBreaker.Hystrix - { public class HystrixRequestContextMiddleware { @@ -37,24 +35,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix await _next.Invoke(context); - hystrix.Dispose(); - } - } - public class HystrixRequestContextMiddlewareOwin - { - private readonly Func, Task> _next; - - public HystrixRequestContextMiddlewareOwin(Func, Task> next) - { - _next = next; - } - - public async Task Invoke(IDictionary environment) - { - var hystrix = HystrixRequestContext.InitializeContext(); - - await _next(environment); - hystrix.Dispose(); } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddlewareOwin.cs b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddlewareOwin.cs new file mode 100644 index 0000000..d747337 --- /dev/null +++ b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixRequestContextMiddlewareOwin.cs @@ -0,0 +1,40 @@ +// Copyright 2017 the original author or authors. +// +// 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. + +using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Steeltoe.CircuitBreaker.Hystrix +{ + public class HystrixRequestContextMiddlewareOwin + { + private readonly Func, Task> _next; + + public HystrixRequestContextMiddlewareOwin(Func, Task> next) + { + _next = next; + } + + public async Task Invoke(IDictionary environment) + { + var hystrix = HystrixRequestContext.InitializeContext(); + + await _next(environment); + + hystrix.Dispose(); + } + } +} diff --git a/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixServiceCollectionExtensions.cs b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixServiceCollectionExtensions.cs index c6deb35..6c6b2c8 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixServiceCollectionExtensions.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixCore/HystrixServiceCollectionExtensions.cs @@ -1,4 +1,18 @@ -using Microsoft.Extensions.Configuration; +// Copyright 2017 the original author or authors. +// +// 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. + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Steeltoe.CircuitBreaker.Hystrix.Strategy; using System; @@ -8,7 +22,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix public static class HystrixServiceCollectionExtensions { public static void AddHystrixCommand(this IServiceCollection services, IHystrixCommandGroupKey groupKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (services == null) { @@ -38,7 +53,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void AddHystrixCommand(this IServiceCollection services, IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (services == null) { @@ -69,7 +85,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix }; services.AddTransient((p) => (TImplementation)ActivatorUtilities.CreateInstance(p, typeof(TImplementation), opts)); } - public static void AddHystrixCommand(this IServiceCollection services, IHystrixCommandGroupKey groupKey, IConfiguration config) where TService : class + + public static void AddHystrixCommand(this IServiceCollection services, IHystrixCommandGroupKey groupKey, IConfiguration config) + where TService : class { if (services == null) { @@ -99,7 +117,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix services.AddTransient((p) => (TService)ActivatorUtilities.CreateInstance(p, typeof(TService), opts)); } - public static void AddHystrixCommand(this IServiceCollection services, IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, IConfiguration config) where TService : class + public static void AddHystrixCommand(this IServiceCollection services, IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, IConfiguration config) + where TService : class { if (services == null) { @@ -132,7 +151,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix services.AddTransient((p) => (TService)ActivatorUtilities.CreateInstance(p, typeof(TService), opts)); } - public static void AddHystrixCommand(this IServiceCollection services, string groupKey, IConfiguration config) where TService : class + public static void AddHystrixCommand(this IServiceCollection services, string groupKey, IConfiguration config) + where TService : class { if (services == null) { @@ -152,9 +172,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix AddHystrixCommand(services, HystrixCommandGroupKeyDefault.AsKey(groupKey), config); } - public static void AddHystrixCommand(this IServiceCollection services, string groupKey, string commandKey, IConfiguration config) where TService : class + public static void AddHystrixCommand(this IServiceCollection services, string groupKey, string commandKey, IConfiguration config) + where TService : class { - if (services == null) { throw new ArgumentNullException(nameof(services)); @@ -179,7 +199,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void AddHystrixCommand(this IServiceCollection services, string groupKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (services == null) { @@ -200,9 +221,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void AddHystrixCommand(this IServiceCollection services, string groupKey, string commandKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { - if (services == null) { throw new ArgumentNullException(nameof(services)); @@ -227,7 +248,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void AddHystrixCollapser(this IServiceCollection services, IHystrixCollapserKey collapserKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (services == null) { @@ -253,7 +275,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void AddHystrixCollapser(this IServiceCollection services, IHystrixCollapserKey collapserKey, RequestCollapserScope scope, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (services == null) { @@ -265,7 +288,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentNullException(nameof(collapserKey)); } - if (config == null) { throw new ArgumentNullException(nameof(config)); @@ -277,7 +299,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix HystrixCollapserOptions opts = new HystrixCollapserOptions(collapserKey, scope, null, dynOpts); services.AddTransient((p) => (TImplementation)ActivatorUtilities.CreateInstance(p, typeof(TImplementation), opts)); } - public static void AddHystrixCollapser(this IServiceCollection services, IHystrixCollapserKey collapserKey, IConfiguration config) where TService : class + + public static void AddHystrixCollapser(this IServiceCollection services, IHystrixCollapserKey collapserKey, IConfiguration config) + where TService : class { if (services == null) { @@ -302,7 +326,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix services.AddTransient((p) => (TService)ActivatorUtilities.CreateInstance(p, typeof(TService), opts)); } - public static void AddHystrixCollapser(this IServiceCollection services, IHystrixCollapserKey collapserKey, RequestCollapserScope scope, IConfiguration config) where TService : class + public static void AddHystrixCollapser(this IServiceCollection services, IHystrixCollapserKey collapserKey, RequestCollapserScope scope, IConfiguration config) + where TService : class { if (services == null) { @@ -327,7 +352,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix services.AddTransient((p) => (TService)ActivatorUtilities.CreateInstance(p, typeof(TService), opts)); } - public static void AddHystrixCollapser(this IServiceCollection services, string collapserKey, IConfiguration config) where TService : class + public static void AddHystrixCollapser(this IServiceCollection services, string collapserKey, IConfiguration config) + where TService : class { if (services == null) { @@ -347,9 +373,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix AddHystrixCollapser(services, HystrixCollapserKeyDefault.AsKey(collapserKey), config); } - public static void AddHystrixCollapser(this IServiceCollection services, string collapserKey, RequestCollapserScope scope, IConfiguration config) where TService : class + public static void AddHystrixCollapser(this IServiceCollection services, string collapserKey, RequestCollapserScope scope, IConfiguration config) + where TService : class { - if (services == null) { throw new ArgumentNullException(nameof(services)); @@ -360,7 +386,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentNullException(nameof(collapserKey)); } - if (config == null) { throw new ArgumentNullException(nameof(config)); @@ -370,7 +395,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void AddHystrixCollapser(this IServiceCollection services, string collapserKey, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { if (services == null) { @@ -391,9 +417,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix } public static void AddHystrixCollapser(this IServiceCollection services, string collapserKey, RequestCollapserScope scope, IConfiguration config) - where TService : class where TImplementation : class, TService + where TService : class + where TImplementation : class, TService { - if (services == null) { throw new ArgumentNullException(nameof(services)); @@ -404,7 +430,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix throw new ArgumentNullException(nameof(collapserKey)); } - if (config == null) { throw new ArgumentNullException(nameof(config)); @@ -412,6 +437,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix AddHystrixCollapser(services, HystrixCollapserKeyDefault.AsKey(collapserKey), scope, config); } - } } diff --git a/src/Steeltoe.CircuitBreaker.HystrixCore/Properties/AssemblyInfo.cs b/src/Steeltoe.CircuitBreaker.HystrixCore/Properties/AssemblyInfo.cs index 0cdd9d6..47838cc 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixCore/Properties/AssemblyInfo.cs +++ b/src/Steeltoe.CircuitBreaker.HystrixCore/Properties/AssemblyInfo.cs @@ -1,4 +1,18 @@ -using System.Reflection; +// Copyright 2017 the original author or authors. +// +// 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. + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/Steeltoe.CircuitBreaker.HystrixCore/Steeltoe.CircuitBreaker.HystrixCore.csproj b/src/Steeltoe.CircuitBreaker.HystrixCore/Steeltoe.CircuitBreaker.HystrixCore.csproj index 037e8df..2d9daa0 100644 --- a/src/Steeltoe.CircuitBreaker.HystrixCore/Steeltoe.CircuitBreaker.HystrixCore.csproj +++ b/src/Steeltoe.CircuitBreaker.HystrixCore/Steeltoe.CircuitBreaker.HystrixCore.csproj @@ -20,16 +20,27 @@ - + - + + + All + + + + SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591 + + + + stylecop.json + Always + - \ No newline at end of file diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 0000000..0210b9c --- /dev/null +++ b/stylecop.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "copyrightText": "Copyright {copyrightYear} the original author or authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.", + "xmlHeader": false, + "variables": { + "copyrightYear": "2017" + }, + "documentExposedElements": false, + "documentInternalElements": false, + "documentPrivateElements": false + }, + "indentation": { + "useTabs": false, + "indentationSize": 4 + }, + "namingRules": { + }, + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace", + "systemUsingDirectivesFirst": false + }, + "readabilityRules": { + } + } +} \ No newline at end of file diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixConfigStreamControllerTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixConfigStreamControllerTest.cs index 3f82417..339ebee 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixConfigStreamControllerTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixConfigStreamControllerTest.cs @@ -35,7 +35,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers.Test { var stream = HystrixConfigurationStream.GetInstance(); var controller = new HystrixConfigStreamController(stream); - Assert.NotNull(controller.sampleStream); + Assert.NotNull(controller.SampleStream); } [Fact] diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixMetricsStreamControllerTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixMetricsStreamControllerTest.cs index 77f05f7..44c6395 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixMetricsStreamControllerTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixMetricsStreamControllerTest.cs @@ -35,7 +35,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers.Test { var stream = HystrixDashboardStream.GetInstance(); var controller = new HystrixMetricsStreamController(stream); - Assert.NotNull(controller.sampleStream); + Assert.NotNull(controller.SampleStream); } [Fact] diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixRequestEventStreamControllerTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixRequestEventStreamControllerTest.cs index 18c817c..906d085 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixRequestEventStreamControllerTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixRequestEventStreamControllerTest.cs @@ -35,7 +35,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers.Test { var stream = HystrixRequestEventsStream.GetInstance(); var controller = new HystrixRequestEventStreamController(stream); - Assert.NotNull(controller.sampleStream); + Assert.NotNull(controller.SampleStream); } [Fact] diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixUtilizationStreamControllerTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixUtilizationStreamControllerTest.cs index db0b9fd..e01ab11 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixUtilizationStreamControllerTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Controllers/HystrixUtilizationStreamControllerTest.cs @@ -34,7 +34,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers.Test { var stream = HystrixUtilizationStream.GetInstance(); var controller = new HystrixUtilizationStreamController(stream); - Assert.NotNull(controller.sampleStream); + Assert.NotNull(controller.SampleStream); } [Fact] diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test.csproj b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test.csproj index 52e4df1..414a5d5 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test.csproj +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test.csproj @@ -5,6 +5,7 @@ Unit test project for Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore net461;netcoreapp2.0 + 2.0.3 Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore.Test ASPNET Core;CircuitBreaker;Spring;Spring Cloud;Spring Cloud Hystrix;Hystrix diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/HystrixContainerBuilderExtensionsTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/HystrixContainerBuilderExtensionsTest.cs index 90c7242..4cd0815 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/HystrixContainerBuilderExtensionsTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/HystrixContainerBuilderExtensionsTest.cs @@ -68,7 +68,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test var factory = provider.Resolve(); Assert.NotNull(factory); - publisher.sampleSubscription.Dispose(); + publisher.SampleSubscription.Dispose(); } diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/RabbitMetricsStreamPublisherTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/RabbitMetricsStreamPublisherTest.cs index 5204cdc..6348ba8 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/RabbitMetricsStreamPublisherTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamAutofac.Test/RabbitMetricsStreamPublisherTest.cs @@ -34,9 +34,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test Value = new HystrixMetricsStreamOptions() }; var publisher = new RabbitMetricsStreamPublisher(options, stream, factory); - Assert.NotNull(publisher.sampleSubscription); - Assert.NotNull(publisher.factory); - publisher.sampleSubscription.Dispose(); + Assert.NotNull(publisher.SampleSubscription); + Assert.NotNull(publisher.Factory); + publisher.SampleSubscription.Dispose(); } } diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/HystrixServiceCollectionExtensionsTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/HystrixServiceCollectionExtensionsTest.cs index 1710fba..0c6d3b3 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/HystrixServiceCollectionExtensionsTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/HystrixServiceCollectionExtensionsTest.cs @@ -67,7 +67,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test var factory = provider.GetService(); Assert.NotNull(factory); - publisher.sampleSubscription.Dispose(); + publisher.SampleSubscription.Dispose(); } } diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/RabbitMetricsStreamPublisherTest.cs b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/RabbitMetricsStreamPublisherTest.cs index 5204cdc..6348ba8 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/RabbitMetricsStreamPublisherTest.cs +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/RabbitMetricsStreamPublisherTest.cs @@ -34,9 +34,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test Value = new HystrixMetricsStreamOptions() }; var publisher = new RabbitMetricsStreamPublisher(options, stream, factory); - Assert.NotNull(publisher.sampleSubscription); - Assert.NotNull(publisher.factory); - publisher.sampleSubscription.Dispose(); + Assert.NotNull(publisher.SampleSubscription); + Assert.NotNull(publisher.Factory); + publisher.SampleSubscription.Dispose(); } } diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test.csproj b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test.csproj index 63f1a0d..d8cede7 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test.csproj +++ b/test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test/Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test.csproj @@ -5,6 +5,7 @@ Unit test project for Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore net461;netcoreapp2.0 + 2.0.3 Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore.Test ASPNET Core;CircuitBreaker;Spring;Spring Cloud;Spring Cloud Hystrix;Hystrix diff --git a/test/Steeltoe.CircuitBreaker.HystrixAutofac.Test/HystrixContainerBuilderExtensionsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixAutofac.Test/HystrixContainerBuilderExtensionsTest.cs index 89c1651..2e365fb 100644 --- a/test/Steeltoe.CircuitBreaker.HystrixAutofac.Test/HystrixContainerBuilderExtensionsTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixAutofac.Test/HystrixContainerBuilderExtensionsTest.cs @@ -130,7 +130,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test var expectedCommandKey = HystrixCommandKeyDefault.AsKey(typeof(DummyCommand).Name); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ContainerBuilder(); config = new ConfigurationBuilder().Build(); @@ -143,7 +143,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test Assert.Equal(groupKey, command.CommandGroup); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ContainerBuilder(); HystrixContainerBuilderExtensions.RegisterHystrixCommand(services, "GroupKey", config); @@ -154,7 +154,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test expectedCommandKey = HystrixCommandKeyDefault.AsKey(typeof(DummyCommand).Name); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ContainerBuilder(); config = new ConfigurationBuilder().Build(); @@ -167,7 +167,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test Assert.Equal("GroupKey", command.CommandGroup.Name); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ContainerBuilder(); config = new ConfigurationBuilder().Build(); @@ -178,7 +178,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test Assert.Equal(groupKey, command.CommandGroup); Assert.Equal(commandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ContainerBuilder(); config = new ConfigurationBuilder().Build(); @@ -191,7 +191,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test Assert.Equal(groupKey, command.CommandGroup); Assert.Equal(commandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ContainerBuilder(); HystrixContainerBuilderExtensions.RegisterHystrixCommand(services, "GroupKey", "CommandKey", config); @@ -201,7 +201,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test Assert.Equal("GroupKey", command.CommandGroup.Name); Assert.Equal("CommandKey", command.CommandKey.Name); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ContainerBuilder(); config = new ConfigurationBuilder().Build(); @@ -214,7 +214,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Autofac.Test Assert.Equal("GroupKey", command.CommandGroup.Name); Assert.Equal("CommandKey", command.CommandKey.Name); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); } diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/CommonHystrixCommandTests.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/CommonHystrixCommandTests.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/CommonHystrixCommandTests.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/CommonHystrixCommandTests.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Config/HystrixConfigurationStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Config/HystrixConfigurationStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Config/HystrixConfigurationStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Config/HystrixConfigurationStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/CountDownEventExtensions.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/CountDownEventExtensions.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/CountDownEventExtensions.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/CountDownEventExtensions.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCircuitBreakerTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCircuitBreakerTest.cs similarity index 97% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCircuitBreakerTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCircuitBreakerTest.cs index c73164e..c47d0fd 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCircuitBreakerTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCircuitBreakerTest.cs @@ -53,7 +53,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test HystrixCommand cmd3 = new SuccessCommand(key, 1); HystrixCommand cmd4 = new SuccessCommand(key, 1); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; cmd1.Execute(); cmd2.Execute(); @@ -90,7 +90,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test String key = "cmd-B"; HystrixCommand cmd1 = new SuccessCommand(key, 60); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -128,7 +128,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test String key = "cmd-C"; HystrixCommand cmd1 = new SuccessCommand(key, 60); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -169,7 +169,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test String key = "cmd-D"; HystrixCommand cmd1 = new TimeoutCommand(key); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -200,7 +200,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test String key = "cmd-E"; HystrixCommand cmd1 = new SuccessCommand(key, 60); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -242,7 +242,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test int sleepWindow = 200; HystrixCommand cmd1 = new FailureCommand(key, 60); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -285,7 +285,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test int sleepWindow = 100; HystrixCommand cmd1 = new FailureCommand(key, 1, sleepWindow); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -346,7 +346,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test int sleepWindow = 200; HystrixCommand cmd1 = new FailureCommand(key, 60); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -454,7 +454,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test int lowVolume = 5; HystrixCommand cmd1 = new FailureCommand(key, 60, sleepWindow, lowVolume); - IHystrixCircuitBreaker cb = cmd1.circuitBreaker; + IHystrixCircuitBreaker cb = cmd1._circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); @@ -572,8 +572,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test protected override bool Run() { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, latencyToAdd); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, latencyToAdd); + _token.ThrowIfCancellationRequested(); if (shouldFail) { diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCollapserTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCollapserTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCollapserTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCollapserTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandMetricsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandMetricsTest.cs similarity index 98% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandMetricsTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandMetricsTest.cs index e74c80e..1f87a15 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandMetricsTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandMetricsTest.cs @@ -38,7 +38,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test String key = "cmd-metrics-A"; HystrixCommand cmd1 = new SuccessCommand(key, 1); - HystrixCommandMetrics metrics = cmd1.metrics; + HystrixCommandMetrics metrics = cmd1._metrics; cmd1.Execute(); Time.Wait( 200); output.WriteLine("ReqLog : " + HystrixRequestLog.CurrentRequestLog.GetExecutedCommandsAsString()); @@ -98,7 +98,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test String key = "cmd-metrics-B"; HystrixCommand cmd1 = new SuccessCommand(key, 1); - HystrixCommandMetrics metrics = cmd1.metrics; + HystrixCommandMetrics metrics = cmd1._metrics; cmd1.Execute(); Time.Wait( 200); @@ -159,7 +159,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test HystrixCommand cmd = new SuccessCommand(key, 900); if (metrics == null) { - metrics = cmd.metrics; + metrics = cmd._metrics; } IObservable eagerObservable = cmd.Observe(); cmdResults.Add(eagerObservable); diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandOptionsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandOptionsTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandOptionsTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandOptionsTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandTest.cs similarity index 98% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandTest.cs index 4009eac..3f05640 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandTest.cs @@ -1045,8 +1045,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True( result); Assert.False(cmd.IsResponseTimedOut); Assert.Null(cmd.ExecutionException); - output.WriteLine("CMD : " + cmd.currentRequestLog.GetExecutedCommandsAsString()); - Assert.True(cmd.executionResult.ExecutionLatency >= 900); + output.WriteLine("CMD : " + cmd._currentRequestLog.GetExecutedCommandsAsString()); + Assert.True(cmd._executionResult.ExecutionLatency >= 900); AssertCommandExecutionEvents(cmd, HystrixEventType.SUCCESS); } @@ -2231,7 +2231,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test output.WriteLine("Unsuccessful Execution took : " + ((DateTime.Now.Ticks / 10000) - timeMillis)); AssertCommandExecutionEvents(cmd, HystrixEventType.TIMEOUT, HystrixEventType.FALLBACK_MISSING); - Assert.Equal(0, cmd.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, cmd._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } } @@ -2256,7 +2256,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(command.IsFailedExecution); AssertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING); Assert.NotNull(command.ExecutionException); - Assert.Equal(0, command.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, command._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } [Fact] @@ -2269,7 +2269,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(command.IsFailedExecution); AssertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); Assert.NotNull(command.ExecutionException); - Assert.Equal(0, command.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, command._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } @@ -2294,7 +2294,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(command.IsFailedExecution); AssertCommandExecutionEvents(command, HystrixEventType.FAILURE); Assert.NotNull(command.ExecutionException); - Assert.Equal(0, command.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, command._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } @@ -2319,7 +2319,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(command.IsFailedExecution); AssertCommandExecutionEvents(command, HystrixEventType.FAILURE); Assert.NotNull(command.ExecutionException); - Assert.Equal(0, command.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, command._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } [Fact] @@ -2341,7 +2341,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(cmd.IsExecutionComplete); Assert.True(cmd.IsResponseTimedOut); - Assert.Equal(0, cmd.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, cmd._metrics.CurrentConcurrentExecutionCount); } [Fact] public void TestExecutionFailureWithFallbackImplementedButDisabled() @@ -2386,8 +2386,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test protected override string Run() { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 3000); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 3000); + _token.ThrowIfCancellationRequested(); return "hello"; } protected override string RunFallback() @@ -2750,7 +2750,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Time.Wait(10); // Let it get in queue Assert.Equal(1, pool.CurrentQueueSize); s.Dispose(); - Assert.True(command2.token.IsCancellationRequested); + Assert.True(command2._token.IsCancellationRequested); //Assert.Equal(0, pool.CurrentQueueSize); //make sure we wait for the command to finish so the state is clean for next test var result = poolFiller.Result; @@ -2791,7 +2791,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.False(onThreadStartInvoked.Value); Assert.False(onThreadCompleteInvoked.Value); Assert.False(executionAttempted.Value); - Assert.Equal(0, semaphoreCmd.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, semaphoreCmd._metrics.CurrentConcurrentExecutionCount); } [Fact] @@ -2821,7 +2821,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(onThreadStartInvoked.Value); Assert.True(onThreadCompleteInvoked.Value); Assert.False(executionAttempted.Value); - Assert.Equal(0, threadCmd.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, threadCmd._metrics.CurrentConcurrentExecutionCount); } @@ -2870,7 +2870,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(cmd.ExecutionTimeInMilliseconds > -1); Assert.False(cmd.IsSuccessfulExecution); AssertCommandExecutionEvents(cmd, HystrixEventType.CANCELLED); - Assert.Equal(0, cmd.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, cmd._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } catch (Exception ex) @@ -2922,7 +2922,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(cmd.ExecutionTimeInMilliseconds > -1); Assert.False(cmd.IsSuccessfulExecution); AssertCommandExecutionEvents(cmd, HystrixEventType.CANCELLED); - Assert.Equal(0, cmd.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, cmd._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } catch (Exception ex) @@ -2971,7 +2971,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.Equal(cmd.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, cmd.GetFallbackSemaphore().CurrentCount); Assert.False(cmd.IsExecutionComplete); - Assert.Equal(0, cmd.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, cmd._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(1); } @@ -3057,7 +3057,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test AssertCommandExecutionEvents(original, HystrixEventType.SUCCESS); Assert.NotNull(originalValue.Value); Assert.True((bool)originalValue.Value); - Assert.Equal(0, original.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, original._metrics.CurrentConcurrentExecutionCount); Assert.Equal(fromCache.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache.GetExecutionSemaphore().CurrentCount); @@ -3069,7 +3069,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test AssertCommandExecutionEvents(fromCache, HystrixEventType.RESPONSE_FROM_CACHE, HystrixEventType.CANCELLED); Assert.True(fromCache.ExecutionTimeInMilliseconds == -1); Assert.False(fromCache.IsSuccessfulExecution); - Assert.Equal(0, fromCache.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, fromCache._metrics.CurrentConcurrentExecutionCount); Assert.False(original.IsCancelled); //underlying work output.WriteLine("ReqLog : " + HystrixRequestLog.CurrentRequestLog.GetExecutedCommandsAsString()); @@ -3158,7 +3158,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.False(original.IsSuccessfulExecution); AssertCommandExecutionEvents(original, HystrixEventType.CANCELLED); Assert.Null(originalValue.Value); - Assert.Equal(0, original.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, original._metrics.CurrentConcurrentExecutionCount); Assert.Equal(fromCache.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache.GetExecutionSemaphore().CurrentCount); Assert.Equal(fromCache.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache.GetFallbackSemaphore().CurrentCount); @@ -3169,7 +3169,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test AssertCommandExecutionEvents(fromCache, HystrixEventType.SUCCESS, HystrixEventType.RESPONSE_FROM_CACHE); Assert.True(fromCache.ExecutionTimeInMilliseconds == -1); Assert.True(fromCache.IsSuccessfulExecution); - Assert.Equal(0, fromCache.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, fromCache._metrics.CurrentConcurrentExecutionCount); Assert.False(original.IsCancelled); //underlying work output.WriteLine("ReqLog : " + HystrixRequestLog.CurrentRequestLog.GetExecutedCommandsAsString()); @@ -3288,7 +3288,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test AssertCommandExecutionEvents(original, HystrixEventType.CANCELLED); Assert.Null(originalValue.Value); Assert.False(original.IsCancelled); //underlying work - Assert.Equal(0, original.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, original._metrics.CurrentConcurrentExecutionCount); Assert.Equal(fromCache1.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache1.GetExecutionSemaphore().CurrentCount); Assert.Equal(fromCache1.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache1.GetFallbackSemaphore().CurrentCount); @@ -3301,7 +3301,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(fromCache1.ExecutionTimeInMilliseconds == -1); Assert.True(fromCache1.IsSuccessfulExecution); Assert.True((bool)fromCache1Value.Value); - Assert.Equal(0, fromCache1.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, fromCache1._metrics.CurrentConcurrentExecutionCount); Assert.Equal(fromCache2.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache2.GetExecutionSemaphore().CurrentCount); Assert.Equal(fromCache2.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache2.GetFallbackSemaphore().CurrentCount); @@ -3314,7 +3314,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.True(fromCache2.ExecutionTimeInMilliseconds == -1); Assert.False(fromCache2.IsSuccessfulExecution); Assert.Null(fromCache2Value.Value); - Assert.Equal(0, fromCache2.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, fromCache2._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(3); } @@ -3430,7 +3430,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.False(original.IsSuccessfulExecution); AssertCommandExecutionEvents(original, HystrixEventType.CANCELLED); Assert.True(original.IsCancelled); - Assert.Equal(0, original.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, original._metrics.CurrentConcurrentExecutionCount); Assert.Equal(fromCache1.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache1.GetExecutionSemaphore().CurrentCount); Assert.Equal(fromCache1.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache1.GetFallbackSemaphore().CurrentCount); @@ -3442,7 +3442,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test AssertCommandExecutionEvents(fromCache1, HystrixEventType.RESPONSE_FROM_CACHE, HystrixEventType.CANCELLED); Assert.True(fromCache1.ExecutionTimeInMilliseconds == -1); Assert.False(fromCache1.IsSuccessfulExecution); - Assert.Equal(0, fromCache1.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, fromCache1._metrics.CurrentConcurrentExecutionCount); Assert.Equal(fromCache2.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache2.GetExecutionSemaphore().CurrentCount); Assert.Equal(fromCache2.CommandOptions.ExecutionIsolationSemaphoreMaxConcurrentRequests, fromCache2.GetFallbackSemaphore().CurrentCount); @@ -3454,7 +3454,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test AssertCommandExecutionEvents(fromCache2, HystrixEventType.RESPONSE_FROM_CACHE, HystrixEventType.CANCELLED); Assert.True(fromCache2.ExecutionTimeInMilliseconds == -1); Assert.False(fromCache2.IsSuccessfulExecution); - Assert.Equal(0, fromCache2.metrics.CurrentConcurrentExecutionCount); + Assert.Equal(0, fromCache2._metrics.CurrentConcurrentExecutionCount); AssertSaneHystrixRequestLog(3); } @@ -4695,8 +4695,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test try { //System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " About to sleep for : " + latency); - Time.WaitUntil(() => { return token.IsCancellationRequested; }, latency); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, latency); + _token.ThrowIfCancellationRequested(); //System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Woke up from sleep!"); } catch (Exception) @@ -4792,8 +4792,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test output?.WriteLine(">>> TestCommandRejection running " + sleepTime); try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, sleepTime); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, sleepTime); + _token.ThrowIfCancellationRequested(); output?.WriteLine(">>> TestCommandRejection finished " + ((DateTime.Now.Ticks / 10000) - start)); } catch (Exception e) @@ -5390,8 +5390,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 500); + _token.ThrowIfCancellationRequested(); } catch (Exception) @@ -5426,8 +5426,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 500); + _token.ThrowIfCancellationRequested(); } catch (Exception ) @@ -5472,8 +5472,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { sw.Start(); - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 500); + _token.ThrowIfCancellationRequested(); sw.Stop(); } catch (Exception) @@ -5695,8 +5695,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 2000); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 2000); + _token.ThrowIfCancellationRequested(); } catch (Exception ) @@ -5736,8 +5736,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test try { //output.WriteLine(Thread.CurrentThread.ManagedThreadId + " : In fallback => " + ExecutionEvents); - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 30000); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 30000); + _token.ThrowIfCancellationRequested(); } catch (Exception ) @@ -5843,8 +5843,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 1500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 1500); + _token.ThrowIfCancellationRequested(); return 1; } @@ -5966,8 +5966,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return this.token.IsCancellationRequested; }, 500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return this._token.IsCancellationRequested; }, 500); + _token.ThrowIfCancellationRequested(); return true; } catch (Exception ) @@ -5989,8 +5989,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 500); + _token.ThrowIfCancellationRequested(); return true; } catch (Exception ) @@ -6017,8 +6017,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 500); + _token.ThrowIfCancellationRequested(); return false; } catch (Exception ) @@ -6043,8 +6043,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 500); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 500); + _token.ThrowIfCancellationRequested(); return true; } catch (Exception ) diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandTimeoutConcurrencyTesting.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandTimeoutConcurrencyTesting.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixCommandTimeoutConcurrencyTesting.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixCommandTimeoutConcurrencyTesting.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixRequestCacheTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixRequestCacheTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixRequestCacheTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixRequestCacheTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixRequestLogTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixRequestLogTest.cs similarity index 98% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixRequestLogTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixRequestLogTest.cs index da188b3..02d5587 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixRequestLogTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixRequestLogTest.cs @@ -244,8 +244,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test { try { - Time.WaitUntil(() => { return token.IsCancellationRequested; }, 10000); - token.ThrowIfCancellationRequested(); + Time.WaitUntil(() => { return _token.IsCancellationRequested; }, 10000); + _token.ThrowIfCancellationRequested(); //output.WriteLine("Woke up from sleep!"); //token.ThrowIfCancellationRequested(); } diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixSubclassCommandTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixSubclassCommandTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixSubclassCommandTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixSubclassCommandTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixTestBase.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixTestBase.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixTestBase.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixTestBase.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixThreadPoolMetricsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixThreadPoolMetricsTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixThreadPoolMetricsTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixThreadPoolMetricsTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixThreadPoolOptionsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixThreadPoolOptionsTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixThreadPoolOptionsTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixThreadPoolOptionsTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixThreadPoolTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixThreadPoolTest.cs similarity index 96% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixThreadPoolTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixThreadPoolTest.cs index 3cd9ab5..fadb3df 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/HystrixThreadPoolTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/HystrixThreadPoolTest.cs @@ -35,18 +35,18 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test public void TestShutdown() { // other unit tests will probably have run before this so get the count - int count = HystrixThreadPoolFactory.threadPools.Count; + int count = HystrixThreadPoolFactory.ThreadPools.Count; IHystrixThreadPool pool = HystrixThreadPoolFactory.GetInstance(HystrixThreadPoolKeyDefault.AsKey("threadPoolFactoryTest"), HystrixThreadPoolOptionsTest.GetUnitTestPropertiesBuilder()); - Assert.Equal(count + 1, HystrixThreadPoolFactory.threadPools.Count); + Assert.Equal(count + 1, HystrixThreadPoolFactory.ThreadPools.Count); Assert.False(pool.GetScheduler().IsShutdown); HystrixThreadPoolFactory.Shutdown(); // ensure all pools were removed from the cache - Assert.Empty(HystrixThreadPoolFactory.threadPools); + Assert.Empty(HystrixThreadPoolFactory.ThreadPools); Assert.True(pool.GetScheduler().IsShutdown); } class HystrixMetricsPublisherThreadPoolContainer : IHystrixMetricsPublisherThreadPool diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/CommandStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/CommandStreamTest.cs similarity index 98% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/CommandStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/CommandStreamTest.cs index d130810..562cd5d 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/CommandStreamTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/CommandStreamTest.cs @@ -161,9 +161,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Test { try { sw.Start(); - Time.WaitUntil(() => { return this.token.IsCancellationRequested; }, executionLatency); + Time.WaitUntil(() => { return this._token.IsCancellationRequested; }, executionLatency); sw.Stop(); - this.token.ThrowIfCancellationRequested(); + this._token.ThrowIfCancellationRequested(); switch (executionResult2) { @@ -174,7 +174,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Test case HystrixEventType.BAD_REQUEST: throw new HystrixBadRequestException("induced bad request"); default: - throw new Exception("unhandled HystrixEventType : " + executionResult); + throw new Exception("unhandled HystrixEventType : " + _executionResult); } } catch (Exception ) { diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/CumulativeCollapserEventCounterStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/CumulativeCollapserEventCounterStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/CumulativeCollapserEventCounterStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/CumulativeCollapserEventCounterStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/CumulativeCommandEventCounterStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/CumulativeCommandEventCounterStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/CumulativeCommandEventCounterStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/CumulativeCommandEventCounterStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/CumulativeThreadPoolEventCounterStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/CumulativeThreadPoolEventCounterStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/CumulativeThreadPoolEventCounterStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/CumulativeThreadPoolEventCounterStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/HealthCountsStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/HealthCountsStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/HealthCountsStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/HealthCountsStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/HystrixDashboardStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/HystrixDashboardStreamTest.cs similarity index 99% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/HystrixDashboardStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/HystrixDashboardStreamTest.cs index 52c5fc8..441b3df 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/HystrixDashboardStreamTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/HystrixDashboardStreamTest.cs @@ -58,8 +58,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer.Test stream.Observe().Take(NUM).Subscribe( (dashboardData) => { - output.WriteLine(DateTime.Now.Ticks / 10000 + " : Received data with : " + dashboardData.commandMetrics.Count + " commands"); - foreach (HystrixCommandMetrics metrics in dashboardData.commandMetrics) + output.WriteLine(DateTime.Now.Ticks / 10000 + " : Received data with : " + dashboardData.CommandMetrics.Count + " commands"); + foreach (HystrixCommandMetrics metrics in dashboardData.CommandMetrics) { if (metrics.CommandKey.Equals(commandKey)) { diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCollapserBatchSizeDistributionStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCollapserBatchSizeDistributionStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCollapserBatchSizeDistributionStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCollapserBatchSizeDistributionStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCollapserEventCounterStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCollapserEventCounterStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCollapserEventCounterStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCollapserEventCounterStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCommandEventCounterStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCommandEventCounterStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCommandEventCounterStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCommandEventCounterStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCommandLatencyDistributionStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCommandLatencyDistributionStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCommandLatencyDistributionStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCommandLatencyDistributionStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCommandMaxConcurrencyStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCommandMaxConcurrencyStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingCommandMaxConcurrencyStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingCommandMaxConcurrencyStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingThreadPoolEventCounterStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingThreadPoolEventCounterStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingThreadPoolEventCounterStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingThreadPoolEventCounterStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingThreadPoolMaxConcurrencyStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingThreadPoolMaxConcurrencyStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Consumer/RollingThreadPoolMaxConcurrencyStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Consumer/RollingThreadPoolMaxConcurrencyStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/HystrixCommandCompletionStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/HystrixCommandCompletionStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/HystrixCommandCompletionStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/HystrixCommandCompletionStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/HystrixThreadEventStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/HystrixThreadEventStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/HystrixThreadEventStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/HystrixThreadEventStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Sample/HystrixUtilizationStreamTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Sample/HystrixUtilizationStreamTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Metric/Sample/HystrixUtilizationStreamTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Metric/Sample/HystrixUtilizationStreamTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/MetricsStream/HystrixMetricsStreamOptionsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/MetricsStream/HystrixMetricsStreamOptionsTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/MetricsStream/HystrixMetricsStreamOptionsTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/MetricsStream/HystrixMetricsStreamOptionsTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/MetricsStream/HystrixMetricsStreamPublisherTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/MetricsStream/HystrixMetricsStreamPublisherTest.cs similarity index 92% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/MetricsStream/HystrixMetricsStreamPublisherTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/MetricsStream/HystrixMetricsStreamPublisherTest.cs index 27460f6..504f6d9 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/MetricsStream/HystrixMetricsStreamPublisherTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/MetricsStream/HystrixMetricsStreamPublisherTest.cs @@ -33,8 +33,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test Value = new HystrixMetricsStreamOptions() }; var publisher = new HystrixMetricsStreamPublisher(options, stream); - Assert.NotNull(publisher.sampleSubscription); - publisher.sampleSubscription.Dispose(); + Assert.NotNull(publisher.SampleSubscription); + publisher.SampleSubscription.Dispose(); } } diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/MetricsStream/SerializeTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/MetricsStream/SerializeTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/MetricsStream/SerializeTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/MetricsStream/SerializeTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Properties/AssemblyInfo.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Properties/AssemblyInfo.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Properties/AssemblyInfo.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Properties/AssemblyInfo.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Serial/SerialHystrixRequestEventsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Serial/SerialHystrixRequestEventsTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Serial/SerialHystrixRequestEventsTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Serial/SerialHystrixRequestEventsTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Steeltoe.CircuitBreaker.Hystrix.Core.Test.csproj b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Steeltoe.CircuitBreaker.HystrixBase.Test.csproj similarity index 84% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Steeltoe.CircuitBreaker.Hystrix.Core.Test.csproj rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Steeltoe.CircuitBreaker.HystrixBase.Test.csproj index 5f304ba..e23243c 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Steeltoe.CircuitBreaker.Hystrix.Core.Test.csproj +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Steeltoe.CircuitBreaker.HystrixBase.Test.csproj @@ -3,10 +3,11 @@ - Unit test project for Steeltoe.CircuitBreaker.Hystrix.Core + Unit test project for Steeltoe.CircuitBreaker.HystrixBase net461;netcoreapp2.0 - Steeltoe.CircuitBreaker.Hystrix.Core.Test - Steeltoe.CircuitBreaker.Hystrix.Core.Test + 2.0.3 + Steeltoe.CircuitBreaker.HystrixBase.Test + Steeltoe.CircuitBreaker.HystrixBase.Test ASPNET Core;CircuitBreaker;Spring;Spring Cloud;Spring Cloud Hystrix;Hystrix http://steeltoe.io http://www.apache.org/licenses/LICENSE-2.0 @@ -31,7 +32,7 @@ - + @@ -44,8 +45,4 @@ - - - - \ No newline at end of file diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Strategy/Concurrency/HystrixConcurrencyStrategyTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Strategy/Concurrency/HystrixConcurrencyStrategyTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Strategy/Concurrency/HystrixConcurrencyStrategyTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Strategy/Concurrency/HystrixConcurrencyStrategyTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Strategy/Metrics/HystrixMetricsPublisherFactoryTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Strategy/Metrics/HystrixMetricsPublisherFactoryTest.cs similarity index 98% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Strategy/Metrics/HystrixMetricsPublisherFactoryTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Strategy/Metrics/HystrixMetricsPublisherFactoryTest.cs index a38395d..7a8689d 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Strategy/Metrics/HystrixMetricsPublisherFactoryTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Strategy/Metrics/HystrixMetricsPublisherFactoryTest.cs @@ -60,8 +60,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Strategy.Metrics.Test // wait for them to finish Task.WaitAll(threads.ToArray()); - Assert.Equal(2, factory.commandPublishers.Count); - Assert.Single(factory.threadPoolPublishers); + Assert.Equal(2, factory.CommandPublishers.Count); + Assert.Single(factory.ThreadPoolPublishers); // we should see 2 commands and 1 threadPool publisher created Assert.Equal(2, publisher.commandCounter.Value); diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestCircuitBreaker.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestCircuitBreaker.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestCircuitBreaker.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestCircuitBreaker.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestCommandBuilder.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestCommandBuilder.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestCommandBuilder.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestCommandBuilder.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestHystrixCommand.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestHystrixCommand.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestHystrixCommand.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestHystrixCommand.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestableExecutionHook.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestableExecutionHook.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/TestableExecutionHook.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/TestableExecutionHook.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixRollingNumberTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixRollingNumberTest.cs similarity index 83% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixRollingNumberTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixRollingNumberTest.cs index 5d70791..eda7d8d 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixRollingNumberTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixRollingNumberTest.cs @@ -34,26 +34,26 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test { HystrixRollingNumber counter = new HystrixRollingNumber(time, 200, 10); // confirm the initial settings - Assert.Equal(200, counter.timeInMilliseconds); - Assert.Equal(10, counter.numberOfBuckets); - Assert.Equal(20, counter.bucketSizeInMillseconds); + Assert.Equal(200, counter._timeInMilliseconds); + Assert.Equal(10, counter._numberOfBuckets); + Assert.Equal(20, counter._bucketSizeInMillseconds); // we start out with 0 buckets in the queue - Assert.Equal(0, counter.buckets.Size); + Assert.Equal(0, counter._buckets.Size); // add a success in each interval which should result in all 10 buckets being created with 1 success in each - for (int i = 0; i < counter.numberOfBuckets; i++) + for (int i = 0; i < counter._numberOfBuckets; i++) { counter.Increment(HystrixRollingNumberEvent.SUCCESS); - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); } // confirm we have all 10 buckets - Assert.Equal(10, counter.buckets.Size); + Assert.Equal(10, counter._buckets.Size); // add 1 more and we should still only have 10 buckets since that's the max counter.Increment(HystrixRollingNumberEvent.SUCCESS); - Assert.Equal(10, counter.buckets.Size); + Assert.Equal(10, counter._buckets.Size); } catch (Exception e) @@ -71,22 +71,22 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test HystrixRollingNumber counter = new HystrixRollingNumber(time, 200, 10); // we start out with 0 buckets in the queue - Assert.Equal(0, counter.buckets.Size); + Assert.Equal(0, counter._buckets.Size); // add 1 counter.Increment(HystrixRollingNumberEvent.SUCCESS); // confirm we have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // confirm we still have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // add 1 counter.Increment(HystrixRollingNumberEvent.SUCCESS); // we should now have a single bucket with no values in it instead of 2 or more buckets - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); } catch (Exception e) @@ -108,16 +108,16 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(HystrixRollingNumberEvent.SUCCESS); // we should have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // wait past 3 bucket time periods (the 1st bucket then 2 empty ones) - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); // add another counter.Increment(HystrixRollingNumberEvent.SUCCESS); // we should have 4 (1 + 2 empty + 1 new one) buckets - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); } catch (Exception e) @@ -145,12 +145,12 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(HystrixRollingNumberEvent.TIMEOUT); // we should have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // the count should be 4 - Assert.Equal(4, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.SUCCESS).Sum()); - Assert.Equal(2, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.FAILURE).Sum()); - Assert.Equal(1, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); + Assert.Equal(4, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.SUCCESS).Sum()); + Assert.Equal(2, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.FAILURE).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); } catch (Exception e) @@ -172,23 +172,23 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(HystrixRollingNumberEvent.TIMEOUT); // we should have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // the count should be 1 - Assert.Equal(1, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); Assert.Equal(1, counter.GetRollingSum(HystrixRollingNumberEvent.TIMEOUT)); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); // incremenet again in latest bucket counter.Increment(HystrixRollingNumberEvent.TIMEOUT); // we should have 4 buckets - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); // the counts of the last bucket - Assert.Equal(1, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); // the total counts Assert.Equal(2, counter.GetRollingSum(HystrixRollingNumberEvent.TIMEOUT)); @@ -213,23 +213,23 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(HystrixRollingNumberEvent.SHORT_CIRCUITED); // we should have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // the count should be 1 - Assert.Equal(1, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.SHORT_CIRCUITED).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.SHORT_CIRCUITED).Sum()); Assert.Equal(1, counter.GetRollingSum(HystrixRollingNumberEvent.SHORT_CIRCUITED)); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); // incremenet again in latest bucket counter.Increment(HystrixRollingNumberEvent.SHORT_CIRCUITED); // we should have 4 buckets - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); // the counts of the last bucket - Assert.Equal(1, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.SHORT_CIRCUITED).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.SHORT_CIRCUITED).Sum()); // the total counts Assert.Equal(2, counter.GetRollingSum(HystrixRollingNumberEvent.SHORT_CIRCUITED)); @@ -277,23 +277,23 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(type); // we should have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // the count should be 1 - Assert.Equal(1, counter.buckets.Last.GetAdder(type).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(type).Sum()); Assert.Equal(1, counter.GetRollingSum(type)); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); // Increment again in latest bucket counter.Increment(type); // we should have 4 buckets - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); // the counts of the last bucket - Assert.Equal(1, counter.buckets.Last.GetAdder(type).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(type).Sum()); // the total counts Assert.Equal(2, counter.GetRollingSum(type)); @@ -326,7 +326,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(HystrixRollingNumberEvent.SHORT_CIRCUITED); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); // Increment counter.Increment(HystrixRollingNumberEvent.SUCCESS); @@ -338,13 +338,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(HystrixRollingNumberEvent.SHORT_CIRCUITED); // we should have 4 buckets - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); // the counts of the last bucket - Assert.Equal(2, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.SUCCESS).Sum()); - Assert.Equal(3, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.FAILURE).Sum()); - Assert.Equal(1, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); - Assert.Equal(1, counter.buckets.Last.GetAdder(HystrixRollingNumberEvent.SHORT_CIRCUITED).Sum()); + Assert.Equal(2, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.SUCCESS).Sum()); + Assert.Equal(3, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.FAILURE).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.TIMEOUT).Sum()); + Assert.Equal(1, counter._buckets.Last.GetAdder(HystrixRollingNumberEvent.SHORT_CIRCUITED).Sum()); // the total counts Assert.Equal(6, counter.GetRollingSum(HystrixRollingNumberEvent.SUCCESS)); @@ -353,7 +353,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test Assert.Equal(2, counter.GetRollingSum(HystrixRollingNumberEvent.SHORT_CIRCUITED)); // wait until window passes - time.Increment(counter.timeInMilliseconds); + time.Increment(counter._timeInMilliseconds); // Increment counter.Increment(HystrixRollingNumberEvent.SUCCESS); @@ -388,20 +388,20 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(HystrixRollingNumberEvent.FAILURE); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); // we should have 1 bucket since nothing has triggered the update of buckets in the elapsed time - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // the total counts Assert.Equal(4, counter.GetRollingSum(HystrixRollingNumberEvent.SUCCESS)); Assert.Equal(2, counter.GetRollingSum(HystrixRollingNumberEvent.FAILURE)); // we should have 4 buckets as the counter 'gets' should have triggered the buckets being created to fill in time - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); // wait until window passes - time.Increment(counter.timeInMilliseconds); + time.Increment(counter._timeInMilliseconds); // the total counts should all be 0 (and the buckets cleared by the get, not only Increment) Assert.Equal(0, counter.GetRollingSum(HystrixRollingNumberEvent.SUCCESS)); @@ -434,23 +434,23 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.UpdateRollingMax(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE, 10); // we should have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // the count should be 10 - Assert.Equal(10, counter.buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); + Assert.Equal(10, counter._buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); Assert.Equal(10, counter.GetRollingMaxValue(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE)); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); // Increment again in latest bucket counter.UpdateRollingMax(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE, 20); // we should have 4 buckets - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); // the max - Assert.Equal(20, counter.buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); + Assert.Equal(20, counter._buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); // counts per bucket long[] values = counter.GetValues(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE); @@ -481,24 +481,24 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.UpdateRollingMax(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE, 20); // we should have 1 bucket - Assert.Equal(1, counter.buckets.Size); + Assert.Equal(1, counter._buckets.Size); // the count should be 30 - Assert.Equal(30, counter.buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); + Assert.Equal(30, counter._buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); Assert.Equal(30, counter.GetRollingMaxValue(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE)); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds * 3); + time.Increment(counter._bucketSizeInMillseconds * 3); counter.UpdateRollingMax(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE, 30); counter.UpdateRollingMax(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE, 30); counter.UpdateRollingMax(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE, 50); // we should have 4 buckets - Assert.Equal(4, counter.buckets.Size); + Assert.Equal(4, counter._buckets.Size); // the count - Assert.Equal(50, counter.buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); + Assert.Equal(50, counter._buckets.Last.GetMaxUpdater(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE).Max); Assert.Equal(50, counter.GetValueOfLatestBucket(HystrixRollingNumberEvent.THREAD_MAX_ACTIVE)); // values per bucket @@ -529,17 +529,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.UpdateRollingMax(type, 10); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); counter.UpdateRollingMax(type, 30); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); counter.UpdateRollingMax(type, 40); // sleep to get to a new bucket - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); counter.UpdateRollingMax(type, 15); @@ -593,7 +593,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.GetCurrentBucket(); try { - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); } catch (Exception ) { @@ -604,8 +604,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.GetValueOfLatestBucket(type); - // System.out.println("Head: " + counter.buckets.state.get().head); - // System.out.println("Tail: " + counter.buckets.state.get().tail); + // System.out.println("Head: " + counter._buckets.state.get().head); + // System.out.println("Tail: " + counter._buckets.state.get().tail); } } @@ -625,7 +625,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(type); try { - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); } catch (Exception ) { @@ -658,7 +658,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test counter.Increment(type); try { - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); } catch (Exception ) { @@ -699,7 +699,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test { try { - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); } catch (Exception ) { @@ -740,7 +740,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test { try { - time.Increment(counter.bucketSizeInMillseconds); + time.Increment(counter._bucketSizeInMillseconds); } catch (Exception ) { diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixRollingPercentileTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixRollingPercentileTest.cs similarity index 99% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixRollingPercentileTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixRollingPercentileTest.cs index aded617..4e12cb1 100644 --- a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixRollingPercentileTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixRollingPercentileTest.cs @@ -46,7 +46,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test p.AddValue(1000); p.AddValue(2000); - Assert.Equal(1, p.buckets.Size); + Assert.Equal(1, p._buckets.Size); // no bucket turnover yet so percentile not yet generated Assert.Equal(0, p.GetPercentile(50)); @@ -54,19 +54,19 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test time.Increment(6000); // still only 1 bucket until we touch it again - Assert.Equal(1, p.buckets.Size); + Assert.Equal(1, p._buckets.Size); // a bucket has been created so we have a new percentile Assert.Equal(1000, p.GetPercentile(50)); // now 2 buckets since getting a percentile causes bucket retrieval - Assert.Equal(2, p.buckets.Size); + Assert.Equal(2, p._buckets.Size); p.AddValue(1000); p.AddValue(500); // should still be 2 buckets - Assert.Equal(2, p.buckets.Size); + Assert.Equal(2, p._buckets.Size); p.AddValue(200); p.AddValue(200); @@ -111,7 +111,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test p.AddValue(2000); p.AddValue(4000); - Assert.Equal(1, p.buckets.Size); + Assert.Equal(1, p._buckets.Size); // no bucket turnover yet so percentile not yet generated Assert.Equal(0, p.GetPercentile(50)); @@ -119,7 +119,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test time.Increment(6000); // still only 1 bucket until we touch it again - Assert.Equal(1, p.buckets.Size); + Assert.Equal(1, p._buckets.Size); // a bucket has been created so we have a new percentile Assert.Equal(1500, p.GetPercentile(50)); @@ -451,7 +451,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Util.Test try { latch.Wait(TimeSpan.FromSeconds(100)); - Assert.Equal(added.Value, p.buckets.PeekLast.data.Length); + Assert.Equal(added.Value, p._buckets.PeekLast._data.Length); } catch (Exception ) { diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixTimerTest.cs b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixTimerTest.cs similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/Util/HystrixTimerTest.cs rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/Util/HystrixTimerTest.cs diff --git a/test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/xunit.runner.json b/test/Steeltoe.CircuitBreaker.HystrixBase.Test/xunit.runner.json similarity index 100% rename from test/Steeltoe.CircuitBreaker.Hystrix.Core.Test/xunit.runner.json rename to test/Steeltoe.CircuitBreaker.HystrixBase.Test/xunit.runner.json diff --git a/test/Steeltoe.CircuitBreaker.HystrixCore.Test/HystrixServiceCollectionExtensionsTest.cs b/test/Steeltoe.CircuitBreaker.HystrixCore.Test/HystrixServiceCollectionExtensionsTest.cs index 1dd7725..4694f60 100644 --- a/test/Steeltoe.CircuitBreaker.HystrixCore.Test/HystrixServiceCollectionExtensionsTest.cs +++ b/test/Steeltoe.CircuitBreaker.HystrixCore.Test/HystrixServiceCollectionExtensionsTest.cs @@ -130,7 +130,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test var expectedCommandKey = HystrixCommandKeyDefault.AsKey(typeof(DummyCommand).Name); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ServiceCollection(); config = new ConfigurationBuilder().Build(); @@ -143,7 +143,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.Equal(groupKey, command.CommandGroup); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ServiceCollection(); HystrixServiceCollectionExtensions.AddHystrixCommand(services, "GroupKey", config); @@ -154,7 +154,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test expectedCommandKey = HystrixCommandKeyDefault.AsKey(typeof(DummyCommand).Name); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ServiceCollection(); config = new ConfigurationBuilder().Build(); @@ -167,7 +167,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.Equal("GroupKey", command.CommandGroup.Name); Assert.Equal(expectedCommandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ServiceCollection(); config = new ConfigurationBuilder().Build(); @@ -178,7 +178,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.Equal(groupKey, command.CommandGroup); Assert.Equal(commandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ServiceCollection(); config = new ConfigurationBuilder().Build(); @@ -191,7 +191,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.Equal(groupKey, command.CommandGroup); Assert.Equal(commandKey, command.CommandKey); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ServiceCollection(); @@ -202,7 +202,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.Equal("GroupKey", command.CommandGroup.Name); Assert.Equal("CommandKey", command.CommandKey.Name); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); services = new ServiceCollection(); config = new ConfigurationBuilder().Build(); @@ -215,7 +215,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Test Assert.Equal("GroupKey", command.CommandGroup.Name); Assert.Equal("CommandKey", command.CommandKey.Name); Assert.NotNull(command.Options); - Assert.NotNull(command.Options.dynamic); + Assert.NotNull(command.Options._dynamic); } diff --git a/test/Steeltoe.CircuitBreaker.HystrixCore.Test/Steeltoe.CircuitBreaker.HystrixCore.Test.csproj b/test/Steeltoe.CircuitBreaker.HystrixCore.Test/Steeltoe.CircuitBreaker.HystrixCore.Test.csproj index 9b2b112..fa53854 100644 --- a/test/Steeltoe.CircuitBreaker.HystrixCore.Test/Steeltoe.CircuitBreaker.HystrixCore.Test.csproj +++ b/test/Steeltoe.CircuitBreaker.HystrixCore.Test/Steeltoe.CircuitBreaker.HystrixCore.Test.csproj @@ -5,6 +5,7 @@ Unit test project for Steeltoe.CircuitBreaker.HystrixCore net461;netcoreapp2.0 + 2.0.3 Steeltoe.CircuitBreaker.HystrixCore.Test Steeltoe.CircuitBreaker.HystrixCore.Test ASPNET Core;CircuitBreaker;Spring;Spring Cloud;Spring Cloud Hystrix;Hystrix