Apply StyleCop to src packages

This commit is contained in:
Dave Tillman 2017-12-19 08:58:09 -07:00
Родитель 304b55e149
Коммит 1578b4a95c
265 изменённых файлов: 4854 добавлений и 5345 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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}

Просмотреть файл

@ -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.

Просмотреть файл

@ -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'

Просмотреть файл

@ -2,19 +2,20 @@
<PropertyGroup>
<SteeltoeVersion>$(STEELTOE_VERSION)</SteeltoeVersion>
<SteeltoeVersionSuffix>$(STEELTOE_DASH_VERSION_SUFFIX)</SteeltoeVersionSuffix>
<SteeltoeConnectorVersion>2.0.0-dev-00192</SteeltoeConnectorVersion>
<SteeltoeCommonVersion>2.0.0-dev-00018</SteeltoeCommonVersion>
<SteeltoeConnectorVersion>2.0.0-dev-00200</SteeltoeConnectorVersion>
<SteeltoeCommonVersion>2.0.0-dev-00040</SteeltoeCommonVersion>
<AspNetCoreVersion>2.0.0</AspNetCoreVersion>
<AspNetCoreTestVersion>2.0.0</AspNetCoreTestVersion>
<AspNetCoreMvcTestVersion>2.0.0</AspNetCoreMvcTestVersion>
<AspNetCoreDepTestVersion>2.0.0</AspNetCoreDepTestVersion>
<HttpVersion>4.3.1</HttpVersion>
<CoreFxVersion>4.3.0</CoreFxVersion>
<JsonNetVersion>10.0.1</JsonNetVersion>
<HttpVersion>4.3.3</HttpVersion>
<CoreFxVersion>4.4.0</CoreFxVersion>
<StyleCopVersion>1.0.2</StyleCopVersion>
<JsonNetVersion>10.0.3</JsonNetVersion>
<RabbitClientVersion>5.0.1</RabbitClientVersion>
<TestSdkVersion>15.3.0</TestSdkVersion>
<XunitVersion>2.3.0-beta4-build3742</XunitVersion>
<XunitStudioVersion>2.3.0-beta4-build3742</XunitStudioVersion>
<TestSdkVersion>15.5.0</TestSdkVersion>
<XunitVersion>2.3.1</XunitVersion>
<XunitStudioVersion>2.3.1</XunitStudioVersion>
<HdrHistogramVersion>2.0.0</HdrHistogramVersion>
<ReactiveVersion>3.1.1</ReactiveVersion>
</PropertyGroup>

Просмотреть файл

@ -2,19 +2,20 @@
<PropertyGroup>
<SteeltoeVersion>$(STEELTOE_VERSION)</SteeltoeVersion>
<SteeltoeVersionSuffix>$(STEELTOE_DASH_VERSION_SUFFIX)</SteeltoeVersionSuffix>
<SteeltoeConnectorVersion>2.0.0-master-00173</SteeltoeConnectorVersion>
<SteeltoeCommonVersion>2.0.0-master-00018</SteeltoeCommonVersion>
<SteeltoeConnectorVersion>2.0.0-master-00201</SteeltoeConnectorVersion>
<SteeltoeCommonVersion>2.0.0-master-00041</SteeltoeCommonVersion>
<AspNetCoreVersion>2.0.0</AspNetCoreVersion>
<AspNetCoreTestVersion>2.0.0</AspNetCoreTestVersion>
<AspNetCoreMvcTestVersion>2.0.0</AspNetCoreMvcTestVersion>
<AspNetCoreDepTestVersion>2.0.0</AspNetCoreDepTestVersion>
<HttpVersion>4.3.1</HttpVersion>
<CoreFxVersion>4.3.0</CoreFxVersion>
<JsonNetVersion>10.0.1</JsonNetVersion>
<RabbitClientVersion>4.1.3</RabbitClientVersion>
<TestSdkVersion>15.3.0</TestSdkVersion>
<XunitVersion>2.3.0-beta4-build3742</XunitVersion>
<XunitStudioVersion>2.3.0-beta4-build3742</XunitStudioVersion>
<HttpVersion>4.3.3</HttpVersion>
<CoreFxVersion>4.4.0</CoreFxVersion>
<StyleCopVersion>1.0.2</StyleCopVersion>
<JsonNetVersion>10.0.3</JsonNetVersion>
<RabbitClientVersion>5.0.1</RabbitClientVersion>
<TestSdkVersion>15.5.0</TestSdkVersion>
<XunitVersion>2.3.1</XunitVersion>
<XunitStudioVersion>2.3.1</XunitStudioVersion>
<HdrHistogramVersion>2.0.0</HdrHistogramVersion>
<ReactiveVersion>3.1.1</ReactiveVersion>
</PropertyGroup>

Просмотреть файл

@ -2,19 +2,20 @@
<PropertyGroup>
<SteeltoeVersion>$(STEELTOE_VERSION)</SteeltoeVersion>
<SteeltoeVersionSuffix>$(STEELTOE_DASH_VERSION_SUFFIX)</SteeltoeVersionSuffix>
<SteeltoeConnectorVersion>2.0.0</SteeltoeConnectorVersion>
<SteeltoeCommonVersion>2.0.0-dev</SteeltoeCommonVersion>
<SteeltoeConnectorVersion>2.0.0-rc1</SteeltoeConnectorVersion>
<SteeltoeCommonVersion>2.0.0-rc1</SteeltoeCommonVersion>
<AspNetCoreVersion>2.0.0</AspNetCoreVersion>
<AspNetCoreTestVersion>2.0.0</AspNetCoreTestVersion>
<AspNetCoreMvcTestVersion>2.0.0</AspNetCoreMvcTestVersion>
<AspNetCoreDepTestVersion>2.0.0</AspNetCoreDepTestVersion>
<HttpVersion>4.3.1</HttpVersion>
<CoreFxVersion>4.3.0</CoreFxVersion>
<JsonNetVersion>10.0.1</JsonNetVersion>
<RabbitClientVersion>4.1.3</RabbitClientVersion>
<TestSdkVersion>15.3.0</TestSdkVersion>
<XunitVersion>2.3.0-beta4-build3742</XunitVersion>
<XunitStudioVersion>2.3.0-beta4-build3742</XunitStudioVersion>
<HttpVersion>4.3.3</HttpVersion>
<CoreFxVersion>4.4.0</CoreFxVersion>
<StyleCopVersion>1.0.2</StyleCopVersion>
<JsonNetVersion>10.0.3</JsonNetVersion>
<RabbitClientVersion>5.0.1</RabbitClientVersion>
<TestSdkVersion>15.5.0</TestSdkVersion>
<XunitVersion>2.3.1</XunitVersion>
<XunitStudioVersion>2.3.1</XunitStudioVersion>
<HdrHistogramVersion>2.0.0</HdrHistogramVersion>
<ReactiveVersion>3.1.1</ReactiveVersion>
</PropertyGroup>

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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 ../..

Просмотреть файл

@ -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

Просмотреть файл

@ -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;
}
}
}

Просмотреть файл

@ -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<Boolean>}
*/
public bool RequestCacheEnabled { get; set; }
/**
* The maximum number of requests allowed in a batch before triggering a batch execution.
*
* @return {@code HystrixProperty<Integer>}
*/
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<Integer>}
*/
public int TimerDelayInMilliseconds { get; set; }
/**
* Duration of statistical rolling window in milliseconds. This is passed into {@link HystrixRollingNumber} inside {@link HystrixCommandMetrics}.
*
* @return {@code HystrixProperty<Integer>}
*/
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<Integer>}
*/
public int MetricsRollingStatisticalWindowBuckets { get; set; }
/**
* Whether percentile metrics should be captured using {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}.
*
* @return {@code HystrixProperty<Boolean>}
*/
public bool MetricsRollingPercentileEnabled { get; set; }
/**
* Duration of percentile rolling window in milliseconds. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}.
*
* @return {@code HystrixProperty<Integer>}
*/
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<Integer>}
*/
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<Integer>}
*/
public int MetricsRollingPercentileBucketSize { get; set; }
}
}

Просмотреть файл

@ -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<Boolean>}
*/
bool RequestCacheEnabled { get; set; }
/**
* The maximum number of requests allowed in a batch before triggering a batch execution.
*
* @return {@code HystrixProperty<Integer>}
*/
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<Integer>}
*/
int TimerDelayInMilliseconds { get; set; }
/**
* Duration of statistical rolling window in milliseconds. This is passed into {@link HystrixRollingNumber} inside {@link HystrixCommandMetrics}.
*
* @return {@code HystrixProperty<Integer>}
*/
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<Integer>}
*/
int MetricsRollingStatisticalWindowBuckets { get; set; }
/**
* Whether percentile metrics should be captured using {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}.
*
* @return {@code HystrixProperty<Boolean>}
*/
bool MetricsRollingPercentileEnabled { get; set; }
/**
* Duration of percentile rolling window in milliseconds. This is passed into {@link HystrixRollingPercentile} inside {@link HystrixCollapserMetrics}.
*
* @return {@code HystrixProperty<Integer>}
*/
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<Integer>}
*/
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<Integer>}
*/
int MetricsRollingPercentileBucketSize { get; set; }
}
}

Просмотреть файл

@ -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; }
/// <summary>
/// Whether to use a <seealso cref="HystrixCircuitBreaker"/> or not. If false no circuit-breaker logic will be used and all requests permitted.
/// <para>
/// This is similar in effect to <seealso cref="#circuitBreakerForceClosed"/> except that continues tracking metrics and knowing whether it
/// should be open/closed, this property results in not even instantiating a circuit-breaker.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
bool CircuitBreakerEnabled { get; set; }
/// <summary>
/// Error percentage threshold (as whole number such as 50) at which point the circuit breaker will trip open and reject requests.
/// <para>
/// It will stay tripped for the duration defined in <seealso cref="#circuitBreakerSleepWindowInMilliseconds()"/>;
/// </para>
/// <para>
/// The error percentage this is compared against comes from <seealso cref="HystrixCommandMetrics#getHealthCounts()"/>.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
int CircuitBreakerErrorThresholdPercentage { get; set; }
/// <summary>
/// If true the <seealso cref="HystrixCircuitBreaker#allowRequest()"/> will always return true to allow requests regardless of the error percentage from <seealso cref="HystrixCommandMetrics#getHealthCounts()"/>.
/// <para>
/// The <seealso cref="#circuitBreakerForceOpen()"/> property takes precedence so if it set to true this property does nothing.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
bool CircuitBreakerForceClosed { get; set; }
/// <summary>
/// If true the <seealso cref="HystrixCircuitBreaker#allowRequest()"/> will always return false, causing the circuit to be open (tripped) and reject all requests.
/// <para>
/// This property takes precedence over <seealso cref="#circuitBreakerForceClosed()"/>;
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
bool CircuitBreakerForceOpen { get; set; }
/// <summary>
/// Minimum number of requests in the <seealso cref="#metricsRollingStatisticalWindowInMilliseconds()"/> that must exist before the <seealso cref="HystrixCircuitBreaker"/> will trip.
/// <para>
/// If below this number the circuit will not trip regardless of error percentage.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
int CircuitBreakerRequestVolumeThreshold { get; set; }
/// <summary>
/// The time in milliseconds after a <seealso cref="HystrixCircuitBreaker"/> trips open that it should wait before trying requests again.
/// </summary>
/// <returns> {@code Integer>} </returns>
int CircuitBreakerSleepWindowInMilliseconds { get; set; }
/// <summary>
/// Number of concurrent requests permitted to <seealso cref="HystrixCommand#run()"/>. Requests beyond the concurrent limit will be rejected.
/// <para>
/// Applicable only when <seealso cref="#executionIsolationStrategy()"/> == SEMAPHORE.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
int ExecutionIsolationSemaphoreMaxConcurrentRequests { get; set; }
/// <summary>
/// What isolation strategy <seealso cref="HystrixCommand#run()"/> will be executed with.
/// <para>
/// If <seealso cref="ExecutionIsolationStrategy#THREAD"/> then it will be executed on a separate thread and concurrent requests limited by the number of threads in the thread-pool.
/// </para>
/// <para>
/// If <seealso cref="ExecutionIsolationStrategy#SEMAPHORE"/> then it will be executed on the calling thread and concurrent requests limited by the semaphore count.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
ExecutionIsolationStrategy ExecutionIsolationStrategy { get; set; }
/// <summary>
/// Whether the execution thread should attempt an interrupt (using <seealso cref="Future#cancel"/>) when a thread times out.
/// <para>
/// Applicable only when <seealso cref="#executionIsolationStrategy()"/> == THREAD.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
//public virtual bool ExecutionIsolationThreadInterruptOnTimeout { get; set; }
/// <summary>
/// Whether the execution thread should be interrupted if the execution observable is unsubscribed or the future is cancelled via <seealso cref="Future#cancel(true)"/>).
/// <para>
/// Applicable only when <seealso cref="#executionIsolationStrategy()"/> == THREAD.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
//public virtual bool ExecutionIsolationThreadInterruptOnFutureCancel { get; set; }
/// <summary>
/// Allow a dynamic override of the <seealso cref="HystrixThreadPoolKey"/> that will dynamically change which <seealso cref="HystrixThreadPool"/> a <seealso cref="HystrixCommand"/> executes on.
/// <para>
/// Typically this should return NULL which will cause it to use the <seealso cref="HystrixThreadPoolKey"/> injected into a <seealso cref="HystrixCommand"/> or derived from the <seealso cref="HystrixCommandGroupKey"/>.
/// </para>
/// <para>
/// When set the injected or derived values will be ignored and a new <seealso cref="HystrixThreadPool"/> created (if necessary) and the <seealso cref="HystrixCommand"/> will begin using the newly defined pool.
///
/// </para>
/// </summary>
/// <returns> {@code String>} </returns>
string ExecutionIsolationThreadPoolKeyOverride { get; set; }
/// <summary>
/// Time in milliseconds at which point the command will timeout and halt execution.
/// <para>
/// If <seealso cref="#executionIsolationThreadInterruptOnTimeout"/> == true and the command is thread-isolated, the executing thread will be interrupted.
/// If the command is semaphore-isolated and a <seealso cref="HystrixObservableCommand"/>, that command will get unsubscribed.
/// </para>
/// <para>
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
int ExecutionTimeoutInMilliseconds { get; set; }
/// <summary>
/// Whether the timeout mechanism is enabled for this command
/// </summary>
/// <returns> {@code Boolean>}
///
/// @since 1.4.4 </returns>
bool ExecutionTimeoutEnabled { get; set; }
/// <summary>
/// Number of concurrent requests permitted to <seealso cref="HystrixCommand#getFallback()"/>. Requests beyond the concurrent limit will fail-fast and not attempt retrieving a fallback.
/// </summary>
/// <returns> {@code Integer>} </returns>
int FallbackIsolationSemaphoreMaxConcurrentRequests { get; set; }
/// <summary>
/// Whether <seealso cref="HystrixCommand#getFallback()"/> should be attempted when failure occurs.
/// </summary>
/// <returns> {@code Boolean>}
///
/// @since 1.2 </returns>
bool FallbackEnabled { get; set; }
/// <summary>
/// Time in milliseconds to wait between allowing health snapshots to be taken that calculate success and error percentages and affect <seealso cref="HystrixCircuitBreaker#isOpen()"/> status.
/// <para>
/// On high-volume circuits the continual calculation of error percentage can become CPU intensive thus this controls how often it is calculated.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
int MetricsHealthSnapshotIntervalInMilliseconds { get; set; }
/// <summary>
/// Maximum number of values stored in each bucket of the rolling percentile. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
int MetricsRollingPercentileBucketSize { get; set; }
/// <summary>
/// Whether percentile metrics should be captured using <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Boolean>} </returns>
bool MetricsRollingPercentileEnabled { get; set; }
/// <summary>
/// Duration of percentile rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
/// @deprecated Use <seealso cref="#metricsRollingPercentileWindowInMilliseconds()"/>
int MetricsRollingPercentileWindow { get; set; }
/// <summary>
/// Duration of percentile rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
int MetricsRollingPercentileWindowInMilliseconds { get; set; }
/// <summary>
/// Number of buckets the rolling percentile window is broken into. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
int MetricsRollingPercentileWindowBuckets { get; set; }
/// <summary>
/// Duration of statistical rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingNumber"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
int MetricsRollingStatisticalWindowInMilliseconds { get; set; }
/// <summary>
/// Number of buckets the rolling statistical window is broken into. This is passed into <seealso cref="HystrixRollingNumber"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
int MetricsRollingStatisticalWindowBuckets { get; set; }
/// <summary>
/// Whether <seealso cref="HystrixCommand#getCacheKey()"/> should be used with <seealso cref="HystrixRequestCache"/> to provide de-duplication functionality via request-scoped caching.
/// </summary>
/// <returns> {@code Boolean>} </returns>
bool RequestCacheEnabled { get; set; }
/// <summary>
/// Whether <seealso cref="HystrixCommand"/> execution and events should be logged to <seealso cref="HystrixRequestLog"/>.
/// </summary>
/// <returns> {@code Boolean>} </returns>
bool RequestLogEnabled { get; set; }
IHystrixThreadPoolOptions ThreadPoolOptions { get; set; }
}
}

Просмотреть файл

@ -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; }
/// <summary>
/// Core thread-pool size that gets passed to <seealso cref="ThreadPoolExecutor#setCorePoolSize(int)"/>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
int CoreSize { get; set; }
/// <summary>
/// Maximum thread-pool size that gets passed to <seealso cref="ThreadPoolExecutor#setMaximumPoolSize(int)"/>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
int MaximumSize { get; set; }
/// <summary>
/// Keep-alive time in minutes that gets passed to <seealso cref="ThreadPoolExecutor#setKeepAliveTime(long, TimeUnit)"/>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
int KeepAliveTimeMinutes { get; set; }
/// <summary>
/// Max queue size that gets passed to <seealso cref="BlockingQueue"/> in <seealso cref="HystrixConcurrencyStrategy#getBlockingQueue(int)"/>
///
/// This should only affect the instantiation of a threadpool - it is not eliglible to change a queue size on the fly.
/// For that, use <seealso cref="#queueSizeRejectionThreshold()"/>.
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
int MaxQueueSize { get; set; }
/// <summary>
/// Queue size rejection threshold is an artificial "max" size at which rejections will occur even if <seealso cref="#maxQueueSize"/> has not been reached. This is done because the <seealso cref="#maxQueueSize"/> of a
/// <seealso cref="BlockingQueue"/> can not be dynamically changed and we want to support dynamically changing the queue size that affects rejections.
/// <para>
/// This is used by <seealso cref="HystrixCommand"/> when queuing a thread for execution.
///
/// </para>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
int QueueSizeRejectionThreshold { get; set; }
bool AllowMaximumSizeToDivergeFromCoreSize { get; set; }
/// <summary>
/// Duration of statistical rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingNumber"/> inside each <seealso cref="HystrixThreadPoolMetrics"/> instance.
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
int MetricsRollingStatisticalWindowInMilliseconds { get; set; }
/// <summary>
/// Number of buckets the rolling statistical window is broken into. This is passed into <seealso cref="HystrixRollingNumber"/> inside each <seealso cref="HystrixThreadPoolMetrics"/> instance.
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
int MetricsRollingStatisticalWindowBuckets { get; set; }
}
}

Просмотреть файл

@ -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<IHystrixInvokableInfo> executions;
public HystrixRequestEvents(ICollection<IHystrixInvokableInfo> executions)
{
this.executions = executions;
}
public ICollection<IHystrixInvokableInfo> Executions
{
get { return executions; }
}
public IDictionary<ExecutionSignature, List<int>> ExecutionsMappedToLatencies
{
get {
Dictionary<CommandAndCacheKey, int> cachingDetector = new Dictionary<CommandAndCacheKey, int>();
List <IHystrixInvokableInfo> nonCachedExecutions = new List<IHystrixInvokableInfo>(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<ExecutionSignature, List<int>> commandDeduper = new Dictionary<ExecutionSignature, List<int>>();
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<int> currentLatencyList = null;
if (commandDeduper.TryGetValue(signature, out currentLatencyList))
{
currentLatencyList.Add(execution.ExecutionTimeInMilliseconds);
}
else
{
List<int> newLatencyList = new List<int>();
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; }
}
}
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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<HystrixConfiguration> 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();
}
}
}

Просмотреть файл

@ -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<HystrixDashboardStream.DashboardData> 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();
}
}
}

Просмотреть файл

@ -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<HystrixRequestEvents> 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();
}
}
}

Просмотреть файл

@ -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<string> sampleStream;
private IObservable<string> sampleStream;
internal IDisposable sampleSubscription = null;
private IDisposable sampleSubscription = null;
protected internal IObservable<string> SampleStream { get => sampleStream; set => sampleStream = value; }
protected internal IDisposable SampleSubscription { get => sampleSubscription; set => sampleSubscription = value; }
public HystrixStreamBaseController(IObservable<string> 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();

Просмотреть файл

@ -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<HystrixUtilization> 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();
}
}
}

Просмотреть файл

@ -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
{

Просмотреть файл

@ -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>(HystrixDashboardStream.GetInstance());
}
@ -80,6 +76,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix
services.AddHystrixRequestEventStream(config);
services.AddHystrixUtilizationStream(config);
}
}
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -20,22 +20,28 @@
</PropertyGroup>
<ItemGroup Condition="'$(CI_BUILD)' == ''">
<ProjectReference Include="..\Steeltoe.CircuitBreaker.Hystrix.Core\Steeltoe.CircuitBreaker.Hystrix.Core.csproj" />
<ProjectReference Include="..\Steeltoe.CircuitBreaker.HystrixBase\Steeltoe.CircuitBreaker.HystrixBase.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(CI_BUILD)' == 'True'">
<PackageReference Include="Steeltoe.CircuitBreaker.Hystrix.Core" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
<PackageReference Include="Steeltoe.CircuitBreaker.HystrixBase" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="System.Reactive" Version="$(ReactiveVersion)" />
<PackageReference Include="System.Reactive.Observable.Aliases" Version="$(ReactiveVersion)" />
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopVersion)">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<NoWarn>SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json">
<Link>stylecop.json</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AdditionalFiles>
</ItemGroup>
<!-- <ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup> -->
</Project>

Просмотреть файл

@ -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<HystrixMetricsStreamOptions>(config.GetSection(HYSTRIX_STREAM_PREFIX));
container.RegisterType<RabbitMetricsStreamPublisher>().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();
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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<HystrixMetricsStreamOptions> options, HystrixDashboardStream stream, HystrixConnectionFactory factory, ILogger<RabbitMetricsStreamPublisher> 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<string> 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;
}
}
}
}

Просмотреть файл

@ -20,19 +20,29 @@
</PropertyGroup>
<ItemGroup Condition="'$(CI_BUILD)' == ''">
<ProjectReference Include="..\Steeltoe.CircuitBreaker.Hystrix.Core\Steeltoe.CircuitBreaker.Hystrix.Core.csproj" />
<ProjectReference Include="..\Steeltoe.CircuitBreaker.HystrixBase\Steeltoe.CircuitBreaker.HystrixBase.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(CI_BUILD)' == 'True'">
<PackageReference Include="Steeltoe.CircuitBreaker.Hystrix.Core" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
<PackageReference Include="Steeltoe.CircuitBreaker.HystrixBase" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="RabbitMQ.Client" Version="$(RabbitClientVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Steeltoe.CloudFoundry.Connector" Version="$(SteeltoeConnectorVersion)" />
<PackageReference Include="Steeltoe.CloudFoundry.ConnectorBase" Version="$(SteeltoeConnectorVersion)" />
<PackageReference Include="Steeltoe.Common.Autofac" Version="$(SteeltoeCommonVersion)" />
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopVersion)">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<NoWarn>SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json">
<Link>stylecop.json</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AdditionalFiles>
</ItemGroup>
</Project>

Просмотреть файл

@ -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;

Просмотреть файл

@ -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>(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);
}
}
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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<HystrixMetricsStreamOptions> options, HystrixDashboardStream stream, HystrixConnectionFactory factory, ILogger<RabbitMetricsStreamPublisher> 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<string> 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;
}
}
}
}

Просмотреть файл

@ -20,11 +20,11 @@
</PropertyGroup>
<ItemGroup Condition="'$(CI_BUILD)' == ''">
<ProjectReference Include="..\Steeltoe.CircuitBreaker.Hystrix.Core\Steeltoe.CircuitBreaker.Hystrix.Core.csproj" />
<ProjectReference Include="..\Steeltoe.CircuitBreaker.HystrixBase\Steeltoe.CircuitBreaker.HystrixBase.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(CI_BUILD)' == 'True'">
<PackageReference Include="Steeltoe.CircuitBreaker.Hystrix.Core" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
<PackageReference Include="Steeltoe.CircuitBreaker.HystrixBase" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
</ItemGroup>
<ItemGroup>
@ -32,7 +32,17 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Steeltoe.CloudFoundry.ConnectorCore" Version="$(SteeltoeConnectorVersion)" />
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopVersion)">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<NoWarn>SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json">
<Link>stylecop.json</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AdditionalFiles>
</ItemGroup>
</Project>

Просмотреть файл

@ -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<TService, TImplementation>(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<TService, TImplementation>(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<TImplementation>().As<TService>().WithParameter(new TypedParameter(typeof(IHystrixCommandOptions), opts)).InstancePerDependency();
}
public static void RegisterHystrixCommand<TService>(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IConfiguration config) where TService : class
public static void RegisterHystrixCommand<TService>(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IConfiguration config)
where TService : class
{
if (container == null)
{
@ -99,7 +116,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix
container.RegisterType<TService>().WithParameter(new TypedParameter(typeof(IHystrixCommandOptions), opts)).InstancePerDependency();
}
public static void RegisterHystrixCommand<TService>(this ContainerBuilder container, IHystrixCommandGroupKey groupKey, IHystrixCommandKey commandKey, IConfiguration config) where TService : class
public static void RegisterHystrixCommand<TService>(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<TService>().WithParameter(new TypedParameter(typeof(IHystrixCommandOptions), opts)).InstancePerDependency();
}
public static void RegisterHystrixCommand<TService>(this ContainerBuilder container, string groupKey, IConfiguration config) where TService : class
public static void RegisterHystrixCommand<TService>(this ContainerBuilder container, string groupKey, IConfiguration config)
where TService : class
{
if (container == null)
{
@ -151,9 +170,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix
RegisterHystrixCommand<TService>(container, HystrixCommandGroupKeyDefault.AsKey(groupKey), config);
}
public static void RegisterHystrixCommand<TService>(this ContainerBuilder container, string groupKey, string commandKey, IConfiguration config) where TService : class
public static void RegisterHystrixCommand<TService>(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<TService, TImplementation>(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<TService, TImplementation>(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<TService, TImplementation>(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<TImplementation>().As<TService>().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency();
}
public static void RegisterHystrixCollapser<TService, TImplementation>(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<TImplementation>().As<TService>().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency();
}
public static void RegisterHystrixCollapser<TService>(this ContainerBuilder container, IHystrixCollapserKey collapserKey, IConfiguration config) where TService : class
public static void RegisterHystrixCollapser<TService>(this ContainerBuilder container, IHystrixCollapserKey collapserKey, IConfiguration config)
where TService : class
{
if (container == null)
{
@ -302,7 +323,8 @@ namespace Steeltoe.CircuitBreaker.Hystrix
container.RegisterType<TService>().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency();
}
public static void RegisterHystrixCollapser<TService>(this ContainerBuilder container, IHystrixCollapserKey collapserKey, RequestCollapserScope scope, IConfiguration config) where TService : class
public static void RegisterHystrixCollapser<TService>(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<TService>().WithParameter(new TypedParameter(typeof(IHystrixCollapserOptions), opts)).InstancePerDependency();
}
public static void RegisterHystrixCollapser<TService>(this ContainerBuilder container, string collapserKey, IConfiguration config) where TService : class
public static void RegisterHystrixCollapser<TService>(this ContainerBuilder container, string collapserKey, IConfiguration config)
where TService : class
{
if (container == null)
{
@ -347,9 +369,9 @@ namespace Steeltoe.CircuitBreaker.Hystrix
RegisterHystrixCollapser<TService>(container, HystrixCollapserKeyDefault.AsKey(collapserKey), config);
}
public static void RegisterHystrixCollapser<TService>(this ContainerBuilder container, string collapserKey, RequestCollapserScope scope, IConfiguration config) where TService : class
public static void RegisterHystrixCollapser<TService>(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<TService, TImplementation>(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<TService, TImplementation>(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<TService, TImplementation>(container, HystrixCollapserKeyDefault.AsKey(collapserKey), scope, config);
}
}
}

Просмотреть файл

@ -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();
}
}
}
}
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -20,15 +20,27 @@
</PropertyGroup>
<ItemGroup Condition="'$(CI_BUILD)' == ''">
<ProjectReference Include="..\Steeltoe.CircuitBreaker.Hystrix.Core\Steeltoe.CircuitBreaker.Hystrix.Core.csproj" />
<ProjectReference Include="..\Steeltoe.CircuitBreaker.HystrixBase\Steeltoe.CircuitBreaker.HystrixBase.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(CI_BUILD)' == 'True'">
<PackageReference Include="Steeltoe.CircuitBreaker.Hystrix.Core" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
<PackageReference Include="Steeltoe.CircuitBreaker.HystrixBase" Version="$(SteeltoeVersion)$(SteeltoeVersionSuffix)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Steeltoe.Common.Autofac" Version="$(SteeltoeCommonVersion)" />
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopVersion)">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<NoWarn>SA1101;SA1124;SA1201;SA1309;SA1310;SA1401;SA1600;SA1652;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json">
<Link>stylecop.json</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AdditionalFiles>
</ItemGroup>
<ItemGroup>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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<string, IHystrixCircuitBreaker> circuitBreakersByCommand = new ConcurrentDictionary<string, IHystrixCircuitBreaker>();
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();
}
}
}

Просмотреть файл

@ -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
}
}
}
}
}

Просмотреть файл

@ -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()
{
}

Просмотреть файл

@ -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<RequestResponseType, RequestArgumentType> : ICollapsedRequest<RequestResponseType, RequestArgumentType>
{
private readonly RequestArgumentType argument;
private readonly CancellationToken token;
private readonly ConcurrentQueue<CancellationToken> linkedTokens = new ConcurrentQueue<CancellationToken>();
private RequestResponseType response;
private Exception exception;
private bool complete;
private TaskCompletionSource<RequestResponseType> tcs;
private readonly CancellationToken token;
private readonly ConcurrentQueue<CancellationToken> linkedTokens = new ConcurrentQueue<CancellationToken>();
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;
}
}

Просмотреть файл

@ -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<BatchReturnType, ResponseType, RequestArgumentType> : ITimerListener
{
private readonly RequestCollapser<BatchReturnType, ResponseType, RequestArgumentType> rq;
public CollapsedTask(RequestCollapser<BatchReturnType, ResponseType, RequestArgumentType> 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<BatchReturnType, ResponseType, RequestArgumentType> 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;
}
}
}
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
}
}
}

Просмотреть файл

@ -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<RequestResponseType, RequestArgumentType> 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<RequestResponseType, RequestArgumentType> collapsedRequest = new CollapsedRequest<RequestResponseType, RequestArgumentType>(arg, token);
TaskCompletionSource<RequestResponseType> tcs = new TaskCompletionSource<RequestResponseType>(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<RequestResponseType, RequestArgumentType> GetOrAddNullArg(CollapsedRequest<RequestResponseType, RequestArgumentType> 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<RequestResponseType, RequestArgumentType> 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.
* <p>
* IMPORTANT IMPLEMENTATION DETAILS => The expected contract (responsibilities) of this method implementation is:
* <p>
* <ul>
* <li>Do NOT block => Do the work on a separate worker thread. Do not perform inline otherwise it will block other requests.</li>
* <li>Set ALL CollapsedRequest response values => Set the response values T on each CollapsedRequest<T, R>, 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.</li>
* </ul>
*
*/
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<ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>>> shards = commandCollapser.DoShardRequests(args);
// for each shard execute its requests
// for each shard execute its requests
foreach (ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>> 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<RequestResponseType, RequestArgumentType> 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<RequestResponseType, RequestArgumentType> 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<RequestResponseType, RequestArgumentType> 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<RequestResponseType, RequestArgumentType> 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<RequestResponseType, RequestArgumentType> GetOrAddNullArg(CollapsedRequest<RequestResponseType, RequestArgumentType> 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<RequestResponseType, RequestArgumentType> existing))
{
// Log
}
}
finally
{
batchLock.ExitReadLock();
}
}
}
}
}

Просмотреть файл

@ -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<BatchReturnType, RequestResponseType, RequestArgumentType>
{
//static readonly Logger logger = LoggerFactory.getLogger(RequestCollapser.class);
//private readonly RequestArgumentType NULL_SENTINEL = default(RequestArgumentType);
private readonly HystrixCollapser<BatchReturnType, RequestResponseType, RequestArgumentType> commandCollapser;
// batch can be null once shutdown
internal readonly AtomicReference<RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType>> batch = new AtomicReference<RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType>>();
private readonly AtomicReference<RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType>> batch = new AtomicReference<RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType>>();
private readonly AtomicReference<TimerReference> timerListenerReference = new AtomicReference<TimerReference>();
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<RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType>> Batch => batch;
public IHystrixCollapserOptions Properties => properties;
internal RequestCollapser(HystrixCollapser<BatchReturnType, RequestResponseType, RequestArgumentType> 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<BatchReturnType, RequestResponseType, RequestArgumentType>(properties, commandCollapser, properties.MaxRequestsInBatch);
}
public CollapsedRequest<RequestResponseType, RequestArgumentType> 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<BatchReturnType, RequestResponseType, RequestArgumentType> b = batch.Value;
RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType> 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<BatchReturnType, RequestResponseType, RequestArgumentType> previousBatch)
{
if (previousBatch == null)
{
throw new InvalidOperationException("Trying to start null batch which means it was shutdown already.");
}
if (batch.CompareAndSet(previousBatch, new RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType>(properties, commandCollapser, properties.MaxRequestsInBatch)))
{
previousBatch.ExecuteBatchIfNotAlreadyStarted();
}
}
public void Shutdown()
{
RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType> currentBatch = batch.GetAndSet(null);
RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType> currentBatch = Batch.GetAndSet(null);
if (currentBatch != null)
{
currentBatch.Shutdown();
@ -108,42 +94,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser
timerListenerReference.Value.Dispose();
}
}
}
class CollapsedTask<BatchReturnType, ResponseType, RequestArgumentType> : ITimerListener
{
private readonly RequestCollapser<BatchReturnType, ResponseType, RequestArgumentType> rq;
public CollapsedTask(RequestCollapser<BatchReturnType, ResponseType, RequestArgumentType> rq)
internal void CreateNewBatchAndExecutePreviousIfNeeded(RequestBatch<BatchReturnType, RequestResponseType, RequestArgumentType> 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<BatchReturnType, ResponseType, RequestArgumentType> 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<BatchReturnType, RequestResponseType, RequestArgumentType>(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();
}
}
}

Просмотреть файл

@ -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<BatchReturnType, ResponseType, RequestArgumentType>
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<BatchReturnType, ResponseType, RequestArgumentType> GetRequestVariable<BatchReturnType, ResponseType, RequestArgumentType>(string key)
{
if (!requestScopedCollapsers.TryGetValue(key, out object result))
{
return null;
}
return (RequestCollapserRequestVariable<BatchReturnType, ResponseType, RequestArgumentType>)result;
}
public IHystrixCollapserKey CollapserKey
@ -65,17 +77,17 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser
public RequestCollapser<BatchReturnType, ResponseType, RequestArgumentType> GetRequestCollapser<BatchReturnType, ResponseType, RequestArgumentType>(HystrixCollapser<BatchReturnType, ResponseType, RequestArgumentType> 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<BatchReturnType, ResponseType, RequestArgumentType>)result;
}
// String is HystrixCollapserKey.name() (we can't use HystrixCollapserKey directly as we can't guarantee it implements hashcode/equals correctly)
private static ConcurrentDictionary<string, object> requestScopedCollapsers = new ConcurrentDictionary<string, object>();
@ -97,37 +108,13 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser
{
return GetRequestVariableForCommand(commandCollapser).Value;
}
private RequestCollapserRequestVariable<BatchReturnType, ResponseType, RequestArgumentType> GetRequestVariableForCommand<BatchReturnType, ResponseType, RequestArgumentType>(HystrixCollapser<BatchReturnType, ResponseType, RequestArgumentType> commandCollapser)
{
var result = requestScopedCollapsers.GetOrAddEx(commandCollapser.CollapserKey.Name, (k) => new RequestCollapserRequestVariable<BatchReturnType, ResponseType, RequestArgumentType>(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<BatchReturnType, ResponseType, RequestArgumentType> GetRequestVariable<BatchReturnType, ResponseType, RequestArgumentType>(String key)
{
object result = null;
if(! requestScopedCollapsers.TryGetValue(key, out result))
{
return null;
}
return (RequestCollapserRequestVariable<BatchReturnType, ResponseType, RequestArgumentType>)result;
}
internal class RequestCollapserRequestVariable<BatchReturnType, ResponseType, RequestArgumentType> : HystrixRequestVariableDefault<RequestCollapser<BatchReturnType, ResponseType, RequestArgumentType>>
{
public RequestCollapserRequestVariable(HystrixCollapser<BatchReturnType, ResponseType, RequestArgumentType> commandCollapser, IHystrixCollapserOptions properties, ICollapserTimer timer, HystrixConcurrencyStrategy concurrencyStrategy)
@ -137,5 +124,3 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Collapser
}
}
}

Просмотреть файл

@ -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<CollapserEventType> ValueList = new List<CollapserEventType>();
public static IList<CollapserEventType> 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);
}
}
}
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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
}
}
}
}

Просмотреть файл

@ -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<IHystrixThreadPoolKey, HystrixThreadPoolConfiguration> threadPoolConfig;
private readonly Dictionary<IHystrixCollapserKey, HystrixCollapserConfiguration> collapserConfig;
public HystrixConfiguration(Dictionary<IHystrixCommandKey, HystrixCommandConfiguration> commandConfig,
Dictionary<IHystrixThreadPoolKey, HystrixThreadPoolConfiguration> threadPoolConfig,
Dictionary<IHystrixCollapserKey, HystrixCollapserConfiguration> collapserConfig)
public HystrixConfiguration(
Dictionary<IHystrixCommandKey, HystrixCommandConfiguration> commandConfig,
Dictionary<IHystrixThreadPoolKey, HystrixThreadPoolConfiguration> threadPoolConfig,
Dictionary<IHystrixCollapserKey, HystrixCollapserConfiguration> collapserConfig)
{
this.commandConfig = commandConfig;
this.threadPoolConfig = threadPoolConfig;
this.collapserConfig = collapserConfig;
}
public static HystrixConfiguration From(Dictionary<IHystrixCommandKey, HystrixCommandConfiguration> commandConfig,
Dictionary<IHystrixThreadPoolKey, HystrixThreadPoolConfiguration> threadPoolConfig,
Dictionary<IHystrixCollapserKey, HystrixCollapserConfiguration> collapserConfig)
public static HystrixConfiguration From(
Dictionary<IHystrixCommandKey, HystrixCommandConfiguration> commandConfig,
Dictionary<IHystrixThreadPoolKey, HystrixThreadPoolConfiguration> threadPoolConfig,
Dictionary<IHystrixCollapserKey, HystrixCollapserConfiguration> collapserConfig)
{
return new HystrixConfiguration(commandConfig, threadPoolConfig, collapserConfig);
}

Просмотреть файл

@ -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<HystrixConfiguration> 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<long, HystrixConfiguration> 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<HystrixConfiguration> 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<long, Dictionary<IHystrixThreadPoolKey, HystrixThreadPoolConfiguration>> 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<long, Dictionary<IHystrixCollapserKey, HystrixCollapserConfiguration>> 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<HystrixConfiguration, Dictionary<IHystrixCommandKey, HystrixCommandConfiguration>> OnlyCommandConfig { get; } =
(HystrixConfiguration hystrixConfiguration) =>
{
return hystrixConfiguration.CommandConfig;
};
private static Func<HystrixConfiguration, Dictionary<IHystrixThreadPoolKey, HystrixThreadPoolConfiguration>> OnlyThreadPoolConfig { get; } =
@ -182,9 +173,6 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Config
(HystrixConfiguration hystrixConfiguration) =>
{
return hystrixConfiguration.CollapserConfig;
};
}
}

Просмотреть файл

@ -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; }
}
}
}

Просмотреть файл

@ -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
}
}

Просмотреть файл

@ -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)
{
}
}

Просмотреть файл

@ -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; }

Просмотреть файл

@ -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)
{
}
}

Просмотреть файл

@ -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)
{
}
}

Просмотреть файл

@ -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<HystrixEventType> 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<HystrixEventType> OrderedList
{
get {
get
{
List<HystrixEventType> eventList = new List<HystrixEventType>();
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;
}
}
}
}

Просмотреть файл

@ -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 + "%]";
}
}
}

Просмотреть файл

@ -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;
}
}
}

Просмотреть файл

@ -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<T> CachedTask
{
get; set;
}
//public override bool Equals(object obj)
//{
// HystrixCachedTask<T> ct = obj as HystrixCachedTask<T>;
// if (ct == null)
// return false;
// if (ct.CachedTask == null)
// {
// return this.CachedTask == null;
// }
// return ct.CachedTask.Equals(this.CachedTask);
//}
}
}

Просмотреть файл

@ -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<BatchReturnType, RequestResponseType, RequestArgumentType> : IHystrixExecutable<RequestResponseType>, IHystrixObservable<RequestResponseType>
{
//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<BatchReturnType> CreateCommand(ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>> requests);
protected abstract void MapResponseToRequests(BatchReturnType batchResponse, ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>> requests);
protected virtual ICollection<ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>>> ShardRequests(ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>> requests)
private IHystrixCollapserOptions Properties
{
return new List<ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>>>() { 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<RequestResponseType> ExecuteAsync(CancellationToken token)
{
this.token = token;
this._token = token;
Task<RequestResponseType> toStart = ToTask();
return toStart;
}
public Task<RequestResponseType> ToTask()
{
RequestCollapser<BatchReturnType, RequestResponseType, RequestArgumentType> requestCollapser = collapserFactory.GetRequestCollapser(this);
CollapsedRequest<RequestResponseType, RequestArgumentType> request = null;
HystrixCachedTask<RequestResponseType> 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<RequestResponseType, RequestArgumentType>;
request.AddLinkedToken(token);
var continued = origTask.ContinueWith<RequestResponseType>((parent) =>
{
CollapsedRequest<RequestResponseType, RequestArgumentType> req = parent.AsyncState as CollapsedRequest<RequestResponseType, RequestArgumentType>;
if (req != null)
request.AddLinkedToken(_token);
var continued = origTask.ContinueWith<RequestResponseType>(
(parent) =>
{
if (req.Exception != null)
CollapsedRequest<RequestResponseType, RequestArgumentType> req =
parent.AsyncState as CollapsedRequest<RequestResponseType, RequestArgumentType>;
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<RequestResponseType>(ex);
}
}
protected bool AddCacheEntryIfAbsent(string cacheKey, out HystrixCachedTask<RequestResponseType> entry)
{
entry = null;
var newEntry = new HystrixCachedTask<RequestResponseType> ();
if (Properties.RequestCacheEnabled && cacheKey != null)
{
entry = requestCache.PutIfAbsent<HystrixCachedTask<RequestResponseType>>(cacheKey, newEntry);
if (entry != null)
{
return true;
}
}
entry = newEntry;
return false;
}
public IObservable<RequestResponseType> Observe()
@ -220,36 +195,48 @@ namespace Steeltoe.CircuitBreaker.Hystrix
public IObservable<RequestResponseType> Observe(CancellationToken token)
{
ReplaySubject<RequestResponseType> subject = new ReplaySubject<RequestResponseType>();
IObservable<RequestResponseType> observable = ToObservable();
observable.Subscribe(subject, token);
return observable;
}
//public IObservable<RequestResponseType> Observe()
//{
// return ExecuteAsync().ToObservable();
//}
public IObservable<RequestResponseType> ToObservable()
{
IObservable<RequestResponseType> observable = Observable.FromAsync<RequestResponseType>((ct) =>
{
this.token = ct;
this._token = ct;
Task<RequestResponseType> toStart = ToTask();
return toStart;
});
return observable;
}
//public IObservable<RequestResponseType> ToObservable()
//{
// Task<RequestResponseType> task = ToTask();
// return task.ToObservable<RequestResponseType>();
//}
protected abstract HystrixCommand<BatchReturnType> CreateCommand(ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>> requests);
protected abstract void MapResponseToRequests(BatchReturnType batchResponse, ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>> requests);
protected virtual ICollection<ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>>> ShardRequests(ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>> requests)
{
return new List<ICollection<ICollapsedRequest<RequestResponseType, RequestArgumentType>>>() { requests };
}
protected bool AddCacheEntryIfAbsent(string cacheKey, out HystrixCachedTask<RequestResponseType> entry)
{
entry = null;
var newEntry = new HystrixCachedTask<RequestResponseType>();
if (Properties.RequestCacheEnabled && cacheKey != null)
{
entry = requestCache.PutIfAbsent<HystrixCachedTask<RequestResponseType>>(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<Type, string> defaultNameCache = new ConcurrentDictionary<Type, string>();
@ -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);
}
}
}

Просмотреть файл

@ -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<string, HystrixCollapserMetrics> metrics = new ConcurrentDictionary<string, HystrixCollapserMetrics>();
private static readonly ConcurrentDictionary<string, HystrixCollapserMetrics> Metrics = new ConcurrentDictionary<string, HystrixCollapserMetrics>();
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<HystrixCollapserMetrics> GetInstances()
{
List<HystrixCollapserMetrics> collapserMetrics = new List<HystrixCollapserMetrics>();
foreach (HystrixCollapserMetrics tpm in metrics.Values)
foreach (HystrixCollapserMetrics tpm in Metrics.Values)
{
collapserMetrics.Add(tpm);
}
return collapserMetrics.AsReadOnly();
}
private static readonly IList<CollapserEventType> ALL_EVENT_TYPES = CollapserEventTypeHelper.Values;
public static Func<long[], HystrixCollapserEvent, long[]> 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<long[], long[], long[]> 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
}
}
}

Просмотреть файл

@ -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; }
}
}

Просмотреть файл

@ -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<Unit>, 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<TResult> : AbstractCommand<TResult>, IHystrixExecutable<TResult>
#pragma warning restore SA1402 // File may only contain a single class
{
protected readonly Func<TResult> _run;
protected readonly Func<TResult> _fallback;
public HystrixCommand(IHystrixCommandGroupKey group, Func<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run = null, Func<TResult> 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<TResult> run, Func<TResult> 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<TResult> run,
Func<TResult> 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<TResult> ToTask()
{
Setup();
Task<TResult> fromCache = null;
if (PutInCacheIfAbsent(tcs.Task, out fromCache))
{
var task = fromCache;
return task;
}
ApplyHystrixSemantics();
return tcs.Task;
}
public Task<TResult> ExecuteAsync(CancellationToken token)
{
this.usersToken = token;
_usersToken = token;
Task<TResult> 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<TResult> Observe(CancellationToken token)
{
ReplaySubject<TResult> subject = new ReplaySubject<TResult>();
IObservable<TResult> observable = ToObservable();
observable.Subscribe(subject, token);
@ -238,27 +262,41 @@ namespace Steeltoe.CircuitBreaker.Hystrix
}
public IObservable<TResult> ToObservable()
{
{
IObservable<TResult> observable = Observable.FromAsync<TResult>((ct) =>
{
this.usersToken = ct;
Task<TResult> 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<TResult> 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<TResult> ToTask()
{
Setup();
if (PutInCacheIfAbsent(tcs.Task, out Task<TResult> 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();
}
}
}

Просмотреть файл

@ -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<HystrixEventType> ALL_EVENT_TYPES = HystrixEventTypeHelper.Values;
public static Func<long[], HystrixCommandCompletion, long[]> 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<long[], long[], long[]> 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<string, HystrixCommandMetrics> metrics = new ConcurrentDictionary<string, HystrixCommandMetrics>();
private static readonly ConcurrentDictionary<string, HystrixCommandMetrics> Metrics = new ConcurrentDictionary<string, HystrixCommandMetrics>();
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<HystrixCommandMetrics> GetInstances()
{
List<HystrixCommandMetrics> commandMetrics = new List<HystrixCommandMetrics>();
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 + "%]";
}
}
}

Просмотреть файл

@ -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; }
/// <summary>
/// Whether to use a <seealso cref="HystrixCircuitBreaker"/> or not. If false no circuit-breaker logic will be used and all requests permitted.
/// <para>
/// This is similar in effect to <seealso cref="#circuitBreakerForceClosed"/> except that continues tracking metrics and knowing whether it
/// should be open/closed, this property results in not even instantiating a circuit-breaker.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
public virtual bool CircuitBreakerEnabled { get; set; }
/// <summary>
/// Error percentage threshold (as whole number such as 50) at which point the circuit breaker will trip open and reject requests.
/// <para>
/// It will stay tripped for the duration defined in <seealso cref="#circuitBreakerSleepWindowInMilliseconds()"/>;
/// </para>
/// <para>
/// The error percentage this is compared against comes from <seealso cref="HystrixCommandMetrics#getHealthCounts()"/>.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int CircuitBreakerErrorThresholdPercentage { get; set; }
/// <summary>
/// If true the <seealso cref="HystrixCircuitBreaker#allowRequest()"/> will always return true to allow requests regardless of the error percentage from <seealso cref="HystrixCommandMetrics#getHealthCounts()"/>.
/// <para>
/// The <seealso cref="#circuitBreakerForceOpen()"/> property takes precedence so if it set to true this property does nothing.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
public virtual bool CircuitBreakerForceClosed { get; set; }
/// <summary>
/// If true the <seealso cref="HystrixCircuitBreaker#allowRequest()"/> will always return false, causing the circuit to be open (tripped) and reject all requests.
/// <para>
/// This property takes precedence over <seealso cref="#circuitBreakerForceClosed()"/>;
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
public virtual bool CircuitBreakerForceOpen { get; set; }
/// <summary>
/// Minimum number of requests in the <seealso cref="#metricsRollingStatisticalWindowInMilliseconds()"/> that must exist before the <seealso cref="HystrixCircuitBreaker"/> will trip.
/// <para>
/// If below this number the circuit will not trip regardless of error percentage.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int CircuitBreakerRequestVolumeThreshold { get; set; }
/// <summary>
/// The time in milliseconds after a <seealso cref="HystrixCircuitBreaker"/> trips open that it should wait before trying requests again.
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int CircuitBreakerSleepWindowInMilliseconds { get; set; }
/// <summary>
/// Number of concurrent requests permitted to <seealso cref="HystrixCommand#run()"/>. Requests beyond the concurrent limit will be rejected.
/// <para>
/// Applicable only when <seealso cref="#executionIsolationStrategy()"/> == SEMAPHORE.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int ExecutionIsolationSemaphoreMaxConcurrentRequests { get; set; }
/// <summary>
/// What isolation strategy <seealso cref="HystrixCommand#run()"/> will be executed with.
/// <para>
/// If <seealso cref="ExecutionIsolationStrategy#THREAD"/> then it will be executed on a separate thread and concurrent requests limited by the number of threads in the thread-pool.
/// </para>
/// <para>
/// If <seealso cref="ExecutionIsolationStrategy#SEMAPHORE"/> then it will be executed on the calling thread and concurrent requests limited by the semaphore count.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
public virtual ExecutionIsolationStrategy ExecutionIsolationStrategy { get; set; }
/// <summary>
/// Whether the execution thread should attempt an interrupt (using <seealso cref="Future#cancel"/>) when a thread times out.
/// <para>
/// Applicable only when <seealso cref="#executionIsolationStrategy()"/> == THREAD.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
//public virtual bool ExecutionIsolationThreadInterruptOnTimeout { get; set; }
/// <summary>
/// Whether the execution thread should be interrupted if the execution observable is unsubscribed or the future is cancelled via <seealso cref="Future#cancel(true)"/>).
/// <para>
/// Applicable only when <seealso cref="#executionIsolationStrategy()"/> == THREAD.
///
/// </para>
/// </summary>
/// <returns> {@code Boolean>} </returns>
//public virtual bool ExecutionIsolationThreadInterruptOnFutureCancel { get; set; }
/// <summary>
/// Allow a dynamic override of the <seealso cref="HystrixThreadPoolKey"/> that will dynamically change which <seealso cref="HystrixThreadPool"/> a <seealso cref="HystrixCommand"/> executes on.
/// <para>
/// Typically this should return NULL which will cause it to use the <seealso cref="HystrixThreadPoolKey"/> injected into a <seealso cref="HystrixCommand"/> or derived from the <seealso cref="HystrixCommandGroupKey"/>.
/// </para>
/// <para>
/// When set the injected or derived values will be ignored and a new <seealso cref="HystrixThreadPool"/> created (if necessary) and the <seealso cref="HystrixCommand"/> will begin using the newly defined pool.
///
/// </para>
/// </summary>
/// <returns> {@code String>} </returns>
public virtual string ExecutionIsolationThreadPoolKeyOverride { get; set; }
/// <summary>
/// Time in milliseconds at which point the command will timeout and halt execution.
/// <para>
/// If <seealso cref="#executionIsolationThreadInterruptOnTimeout"/> == true and the command is thread-isolated, the executing thread will be interrupted.
/// If the command is semaphore-isolated and a <seealso cref="HystrixObservableCommand"/>, that command will get unsubscribed.
/// </para>
/// <para>
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int ExecutionTimeoutInMilliseconds { get; set; }
/// <summary>
/// Whether the timeout mechanism is enabled for this command
/// </summary>
/// <returns> {@code Boolean>}
///
/// @since 1.4.4 </returns>
public virtual bool ExecutionTimeoutEnabled { get; set; }
/// <summary>
/// Number of concurrent requests permitted to <seealso cref="HystrixCommand#getFallback()"/>. Requests beyond the concurrent limit will fail-fast and not attempt retrieving a fallback.
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int FallbackIsolationSemaphoreMaxConcurrentRequests { get; set; }
/// <summary>
/// Whether <seealso cref="HystrixCommand#getFallback()"/> should be attempted when failure occurs.
/// </summary>
/// <returns> {@code Boolean>}
///
/// @since 1.2 </returns>
public virtual bool FallbackEnabled { get; set; }
/// <summary>
/// Time in milliseconds to wait between allowing health snapshots to be taken that calculate success and error percentages and affect <seealso cref="HystrixCircuitBreaker#isOpen()"/> status.
/// <para>
/// On high-volume circuits the continual calculation of error percentage can become CPU intensive thus this controls how often it is calculated.
///
/// </para>
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int MetricsHealthSnapshotIntervalInMilliseconds { get; set; }
/// <summary>
/// Maximum number of values stored in each bucket of the rolling percentile. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int MetricsRollingPercentileBucketSize { get; set; }
/// <summary>
/// Whether percentile metrics should be captured using <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Boolean>} </returns>
public virtual bool MetricsRollingPercentileEnabled { get; set; }
/// <summary>
/// Duration of percentile rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
/// @deprecated Use <seealso cref="#metricsRollingPercentileWindowInMilliseconds()"/>
public virtual int MetricsRollingPercentileWindow { get; set; }
/// <summary>
/// Duration of percentile rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int MetricsRollingPercentileWindowInMilliseconds { get; set; }
/// <summary>
/// Number of buckets the rolling percentile window is broken into. This is passed into <seealso cref="HystrixRollingPercentile"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int MetricsRollingPercentileWindowBuckets { get; set; }
/// <summary>
/// Duration of statistical rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingNumber"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int MetricsRollingStatisticalWindowInMilliseconds { get; set; }
/// <summary>
/// Number of buckets the rolling statistical window is broken into. This is passed into <seealso cref="HystrixRollingNumber"/> inside <seealso cref="HystrixCommandMetrics"/>.
/// </summary>
/// <returns> {@code Integer>} </returns>
public virtual int MetricsRollingStatisticalWindowBuckets { get; set; }
/// <summary>
/// Whether <seealso cref="HystrixCommand#getCacheKey()"/> should be used with <seealso cref="HystrixRequestCache"/> to provide de-duplication functionality via request-scoped caching.
/// </summary>
/// <returns> {@code Boolean>} </returns>
public virtual bool RequestCacheEnabled { get; set; }
/// <summary>
/// Whether <seealso cref="HystrixCommand"/> execution and events should be logged to <seealso cref="HystrixRequestLog"/>.
/// </summary>
/// <returns> {@code Boolean>} </returns>
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;
}

Просмотреть файл

@ -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; }
}
}
}

Просмотреть файл

@ -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
}
}

Просмотреть файл

@ -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
{
/// <summary>
/// Various states/events that execution can result in or have tracked.
/// <para>
/// These are most often accessed via <seealso cref="HystrixRequestLog"/> or <seealso cref="HystrixCommand#getExecutionEvents()"/>.
/// </para>
/// </summary>
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<HystrixEventType> valueList = new List<HystrixEventType>();
/// <summary>
/// List of events that throw an Exception to the caller
/// </summary>
public static readonly IList<HystrixEventType> EXCEPTION_PRODUCING_EVENT_TYPES = new List<HystrixEventType>();
/// <summary>
/// List of events that are terminal
/// </summary>
public static readonly IList<HystrixEventType> TERMINAL_EVENT_TYPES = new List<HystrixEventType>();
private static readonly IList<HystrixEventType> ValueList = new List<HystrixEventType>();
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<HystrixEventType> Values
{
get { return valueList; }
}
}
public enum ThreadPoolEventType
{
EXECUTED,
REJECTED,
UNKNOWN
};
public static class ThreadPoolEventTypeHelper
{
private static readonly IList<ThreadPoolEventType> valueList = new List<ThreadPoolEventType>();
public static IList<ThreadPoolEventType> 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<CollapserEventType> valueList = new List<CollapserEventType>();
public static IList<CollapserEventType> 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; }
}
}
}

Просмотреть файл

@ -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);
}
}
}

Просмотреть файл

@ -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<RequestCacheKey, HystrixRequestCache> caches = new ConcurrentDictionary<RequestCacheKey, HystrixRequestCache>();
class HystrixRequestCacheVariable : HystrixRequestVariableDefault<ConcurrentDictionary<ValueCacheKey, object>>
private static readonly ConcurrentDictionary<RequestCacheKey, HystrixRequestCache> Caches = new ConcurrentDictionary<RequestCacheKey, HystrixRequestCache>();
private class HystrixRequestCacheVariable : HystrixRequestVariableDefault<ConcurrentDictionary<ValueCacheKey, object>>
{
public HystrixRequestCacheVariable()
: base(() => {
: base(() =>
{
return new ConcurrentDictionary<ValueCacheKey, object>();
})
{
}
}
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<T>(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<T>(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;
}
}
}
}

Просмотреть файл

@ -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<HystrixRequestLog>
private class HystrixRequestLogVariable : HystrixRequestVariableDefault<HystrixRequestLog>
{
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<IHystrixInvokableInfo> allExecutedCommands = new BlockingCollection<IHystrixInvokableInfo>(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<HystrixRequestLog>
//{
// 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();
// }
//}
}

Просмотреть файл

@ -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<string, HystrixThreadPoolMetrics> metrics = new ConcurrentDictionary<string, HystrixThreadPoolMetrics>();
private static readonly ConcurrentDictionary<string, HystrixThreadPoolMetrics> Metrics = new ConcurrentDictionary<string, HystrixThreadPoolMetrics>();
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<HystrixThreadPoolMetrics> GetInstances()
{
List<HystrixThreadPoolMetrics> threadPoolMetrics = new List<HystrixThreadPoolMetrics>();
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<long[], long[], long[]> 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<int> 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<int> GetCurrentConcurrencyThunk(IHystrixThreadPoolKey threadPoolKey)
{
return () =>
{
return HystrixThreadPoolMetrics.GetInstance(threadPoolKey).concurrentExecutionCount.Value;
};
}
}
}

Просмотреть файл

@ -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;}
/// <summary>
/// Core thread-pool size that gets passed to <seealso cref="ThreadPoolExecutor#setCorePoolSize(int)"/>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
public virtual int CoreSize { get; set; }
/// <summary>
/// Maximum thread-pool size that gets passed to <seealso cref="ThreadPoolExecutor#setMaximumPoolSize(int)"/>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
public virtual int MaximumSize { get; set; }
/// <summary>
/// Keep-alive time in minutes that gets passed to <seealso cref="ThreadPoolExecutor#setKeepAliveTime(long, TimeUnit)"/>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
public virtual int KeepAliveTimeMinutes { get; set; }
/// <summary>
/// Max queue size that gets passed to <seealso cref="BlockingQueue"/> in <seealso cref="HystrixConcurrencyStrategy#getBlockingQueue(int)"/>
///
/// This should only affect the instantiation of a threadpool - it is not eliglible to change a queue size on the fly.
/// For that, use <seealso cref="#queueSizeRejectionThreshold()"/>.
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
public virtual int MaxQueueSize { get; set; }
/// <summary>
/// Queue size rejection threshold is an artificial "max" size at which rejections will occur even if <seealso cref="#maxQueueSize"/> has not been reached. This is done because the <seealso cref="#maxQueueSize"/> of a
/// <seealso cref="BlockingQueue"/> can not be dynamically changed and we want to support dynamically changing the queue size that affects rejections.
/// <para>
/// This is used by <seealso cref="HystrixCommand"/> when queuing a thread for execution.
///
/// </para>
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
public virtual int QueueSizeRejectionThreshold { get; set; }
public virtual bool AllowMaximumSizeToDivergeFromCoreSize { get; set; }
public virtual bool AllowMaximumSizeToDivergeFromCoreSize { get; set; }
/// <summary>
/// Duration of statistical rolling window in milliseconds. This is passed into <seealso cref="HystrixRollingNumber"/> inside each <seealso cref="HystrixThreadPoolMetrics"/> instance.
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
public virtual int MetricsRollingStatisticalWindowInMilliseconds { get; set; }
/// <summary>
/// Number of buckets the rolling statistical window is broken into. This is passed into <seealso cref="HystrixRollingNumber"/> inside each <seealso cref="HystrixThreadPoolMetrics"/> instance.
/// </summary>
/// <returns> {@code HystrixProperty<Integer>} </returns>
public virtual int MetricsRollingStatisticalWindowBuckets { get; set; }
}
}

Просмотреть файл

@ -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<RequestResponseType, RequestArgumentType>
{
RequestArgumentType Argument { get; }
RequestResponseType Response { set; }
@ -28,6 +25,5 @@ namespace Steeltoe.CircuitBreaker.Hystrix
Exception Exception { set; }
bool Complete { set; }
}
}

Просмотреть файл

@ -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();
}
}

Просмотреть файл

@ -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<HystrixCollapserKeyDefault>, 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));
}
}
}

Просмотреть файл

@ -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; }
}
}

Просмотреть файл

@ -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
{
/// <summary>
/// A group name for a <seealso cref="HystrixCommand"/>. This is used for grouping together commands such as for reporting, alerting, dashboards or team/library ownership.
/// <para>
/// By default this will be used to define the <seealso cref="IHystrixThreadPoolKey"/> unless a separate one is defined.
/// </para>
/// </summary>
public interface IHystrixCommandGroupKey : IHystrixKey
{
}
/// <summary>
/// Default implementation of the interface
/// </summary>
public class HystrixCommandGroupKeyDefault : HystrixKeyDefault<HystrixCommandGroupKeyDefault>, IHystrixCommandGroupKey
{
internal HystrixCommandGroupKeyDefault(string name)
: base(name)
{
}
internal HystrixCommandGroupKeyDefault(string name) : base(name) { }
/// <summary>
/// Retrieve (or create) an interned IHystrixCommandGroupKey instance for a given name.
/// </summary>
/// <param name="name"> command name </param>
/// <returns> IHystrixCommandGroupKey instance that is interned (cached) so a given name will always retrieve the same instance. </returns>
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; }
}
}
}

Просмотреть файл

@ -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
{
/// <summary>
/// A key to represent a <seealso cref="IHystrixCommand"/> for monitoring, circuit-breakers, metrics publishing, caching and other such uses.
/// </summary>
public interface IHystrixCommandKey : IHystrixKey
{
}
/// <summary>
/// Default implementation of the interface
/// </summary>
public class HystrixCommandKeyDefault : HystrixKeyDefault<HystrixCommandKeyDefault>, IHystrixCommandKey
{
internal HystrixCommandKeyDefault(string name) : base(name) { }
internal HystrixCommandKeyDefault(string name)
: base(name)
{
}
/// <summary>
/// Retrieve (or create) an interned IHystrixCommandKey instance for a given name.
/// </summary>
/// <param name="name"> command name </param>
/// <returns> IHystrixCommandKey instance that is interned (cached) so a given name will always retrieve the same instance. </returns>
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; }
}
}
}

Просмотреть файл

@ -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; }
}
}

Просмотреть файл

@ -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<TResult> : IHystrixObservable<TResult>
{
TResult Execute();
Task<TResult> ExecuteAsync();
}
}

Просмотреть файл

@ -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<TResult>
//{
//}
}

Просмотреть файл

@ -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; }

Просмотреть файл

@ -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<T> : IHystrixKey
{
internal protected static readonly ConcurrentDictionary<string, T> intern = new ConcurrentDictionary<string, T>();
protected internal static readonly ConcurrentDictionary<string, T> Intern = new ConcurrentDictionary<string, T>();
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; }
}
}
}

Просмотреть файл

@ -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<Unit> Observe();
IObservable<Unit> ToObservable();
}
public interface IHystrixObservable<TResult> : IHystrixInvokable
{
IObservable<TResult> Observe();
IObservable<TResult> ToObservable();
}
}

Просмотреть файл

@ -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();
/// <summary>
/// Mark when a thread begins executing a command.
/// </summary>
void MarkThreadExecution();
/// <summary>
/// Mark when a thread completes executing a command.
/// </summary>
void MarkThreadCompletion();
/// <summary>
/// Mark when a command gets rejected from the threadpool
/// </summary>
void MarkThreadRejection();
/// <summary>
/// Whether the queue will allow adding an item to it.
/// <para>
/// 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.
///
/// </para>
/// </summary>
/// <returns> boolean whether there is space on the queue </returns>
bool IsQueueSpaceAvailable { get; }
bool IsShutdown { get; }

Просмотреть файл

@ -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
{
/// <summary>
@ -30,7 +28,10 @@ namespace Steeltoe.CircuitBreaker.Hystrix
/// </summary>
public class HystrixThreadPoolKeyDefault : HystrixKeyDefault<HystrixThreadPoolKeyDefault>, IHystrixThreadPoolKey
{
internal HystrixThreadPoolKeyDefault(string name) : base(name) { }
internal HystrixThreadPoolKeyDefault(string name)
: base(name)
{
}
/// <summary>
/// Retrieve (or create) an interned IHystrixThreadPoolKey instance for a given name.
@ -39,7 +40,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix
/// <returns> IHystrixThreadPoolKey instance that is interned (cached) so a given name will always retrieve the same instance. </returns>
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; }
}
}
}

Просмотреть файл

@ -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; }
}
}

Просмотреть файл

@ -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;
}
}
}

Просмотреть файл

@ -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 + '\'' +
'}';
}
}
}

Просмотреть файл

@ -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<Event, Bucket, Output> where Event : IHystrixEvent
public abstract class BucketedCounterStream<Event, Bucket, Output>
where Event : IHystrixEvent
{
// TODO: protected
public readonly int numBuckets;
public readonly int bucketSizeInMs;
protected readonly int numBuckets;
protected readonly int bucketSizeInMs;
protected readonly IObservable<Bucket> bucketedStream;
protected readonly AtomicReference<IDisposable> subscription = new AtomicReference<IDisposable>(null);
private readonly Func<IObservable<Event>, IObservable<Bucket>> reduceBucketToSummary;
//protected readonly BehaviorSubject<Output> counterSubject;
protected BucketedCounterStream(IHystrixEventStream<Event> inputEventStream, int numBuckets, int bucketSizeInMs, Func<Bucket, Event, Bucket> appendRawEventToBucket)
{
//this.counterSubject = new BehaviorSubject<Output>(EmptyOutputValue);
this.numBuckets = numBuckets;
this.bucketSizeInMs = bucketSizeInMs;
this.reduceBucketToSummary = (eventsObservable) =>
@ -43,72 +40,31 @@ namespace Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer
return result;
};
IList<Bucket> emptyEventCountsToStart = new List<Bucket>();
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<Output> 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;

Просмотреть файл

@ -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<Event, Bucket, Output> : BucketedCounterStream<Event, Bucket, Output> where Event : IHystrixEvent
public abstract class BucketedCumulativeCounterStream<Event, Bucket, Output> : BucketedCounterStream<Event, Bucket, Output>
where Event : IHystrixEvent
{
private IObservable<Output> sourceStream;
private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false);
public readonly BehaviorSubject<Output> counterSubject;
private readonly BehaviorSubject<Output> counterSubject;
private IObservable<Output> sourceStream;
protected BucketedCumulativeCounterStream(IHystrixEventStream<Event> stream, int numBuckets, int bucketSizeInMs, Func<Bucket, Event, Bucket> reduceCommandCompletion, Func<Output, Bucket, Output> reduceBucket)
: base(stream, numBuckets, bucketSizeInMs, reduceCommandCompletion)
{
this.counterSubject = new BehaviorSubject<Output>(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<Output> Observe()
{
return sourceStream;
}
//private IDisposable connect;
public void StartCachingStreamValuesIfUnstarted()
{
if (subscription.Value == null)
{
//the stream is not yet started
//IConnectableObservable<Output> connectable = Observe() as IConnectableObservable<Output>;
//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;
}

Просмотреть файл

@ -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<Event, Bucket, Output> : BucketedCounterStream<Event, Bucket, Output> where Event : IHystrixEvent
public abstract class BucketedRollingCounterStream<Event, Bucket, Output> : BucketedCounterStream<Event, Bucket, Output>
where Event : IHystrixEvent
{
private IObservable<Output> sourceStream;
private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false);
protected BehaviorSubject<Output> counterSubject;
//protected IDisposable counterSubscription;
private readonly AtomicBoolean isSourceCurrentlySubscribed = new AtomicBoolean(false);
private IObservable<Output> sourceStream;
protected BucketedRollingCounterStream(IHystrixEventStream<Event> stream, int numBuckets, int bucketSizeInMs, Func<Bucket, Event, Bucket> appendRawEventToBucket, Func<Output, Bucket, Output> reduceBucket)
: base(stream, numBuckets, bucketSizeInMs, appendRawEventToBucket)
{
Func<IObservable<Bucket>, IObservable<Output>> reduceWindowToSummary = (window) => {
Func<IObservable<Bucket>, IObservable<Output>> reduceWindowToSummary = (window) =>
{
var result = window.Aggregate(EmptyOutputValue, (arg1, arg2) => reduceBucket(arg1, arg2)).Select(n => n);
return result;
};
this.counterSubject = new BehaviorSubject<Output>(EmptyOutputValue);
this.sourceStream = bucketedStream //stream broken up into buckets
counterSubject = new BehaviorSubject<Output>(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<Output> 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
}
}
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше