Integrate HealthCheck to all eShop services and apps
Integrate WebStatus with Healthcheck
This commit is contained in:
parent
06e641a97f
commit
0f6f4e6d14
@ -4,6 +4,9 @@
|
||||
<add key="repositoryPath" value="packages" />
|
||||
</config>
|
||||
<packageSources>
|
||||
<add key="Preview-aspnetcore-tools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json"/>
|
||||
<add key="Preview-aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json"/>
|
||||
<add key="Preview-aspnetcore" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"/>
|
||||
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnet-feb2017-patch/api/v3/index.json" />
|
||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
|
@ -187,6 +187,13 @@ services:
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc
|
||||
- BasketUrlHC=http://basket.api/hc
|
||||
- MarketingUrlHC=http://marketing.api/hc
|
||||
- PaymentUrlHC=http://payment.api/hc
|
||||
- LocationUrlHC=http://locations.api/hc
|
||||
ports:
|
||||
- "5200:80"
|
||||
volumes:
|
||||
@ -196,6 +203,13 @@ services:
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc
|
||||
- BasketUrlHC=http://basket.api/hc
|
||||
- MarketingUrlHC=http://marketing.api/hc
|
||||
- PaymentUrlHC=http://payment.api/hc
|
||||
- LocationUrlHC=http://locations.api/hc
|
||||
ports:
|
||||
- "5201:80"
|
||||
volumes:
|
||||
@ -205,6 +219,13 @@ services:
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc
|
||||
- BasketUrlHC=http://basket.api/hc
|
||||
- MarketingUrlHC=http://marketing.api/hc
|
||||
- PaymentUrlHC=http://payment.api/hc
|
||||
- LocationUrlHC=http://locations.api/hc
|
||||
ports:
|
||||
- "5202:80"
|
||||
volumes:
|
||||
@ -214,6 +235,13 @@ services:
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc
|
||||
- BasketUrlHC=http://basket.api/hc
|
||||
- MarketingUrlHC=http://marketing.api/hc
|
||||
- PaymentUrlHC=http://payment.api/hc
|
||||
- LocationUrlHC=http://locations.api/hc
|
||||
ports:
|
||||
- "5203:80"
|
||||
volumes:
|
||||
@ -226,6 +254,13 @@ services:
|
||||
- urls__catalog=http://catalog.api
|
||||
- urls__orders=http://ordering.api
|
||||
- urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc
|
||||
- BasketUrlHC=http://basket.api/hc
|
||||
- MarketingUrlHC=http://marketing.api/hc
|
||||
- PaymentUrlHC=http://payment.api/hc
|
||||
- LocationUrlHC=http://locations.api/hc
|
||||
ports:
|
||||
- "5120:80" # Important: In a production environment your should remove the external port (5120) kept here for microservice debugging purposes.
|
||||
# The API Gateway redirects and access through the internal port (80).
|
||||
@ -237,6 +272,13 @@ services:
|
||||
- urls__catalog=http://catalog.api
|
||||
- urls__orders=http://ordering.api
|
||||
- urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc
|
||||
- BasketUrlHC=http://basket.api/hc
|
||||
- MarketingUrlHC=http://marketing.api/hc
|
||||
- PaymentUrlHC=http://payment.api/hc
|
||||
- LocationUrlHC=http://locations.api/hc
|
||||
ports:
|
||||
- "5121:80" # Important: In a production environment your should remove the external port (5121) kept here for microservice debugging purposes.
|
||||
# The API Gateway redirects and access through the internal port (80).
|
||||
@ -260,7 +302,41 @@ services:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||
- CatalogUrl=http://catalog.api/hc
|
||||
- OrderingUrl=http://ordering.api/hc
|
||||
- HealthChecks-UI__HealthChecks__0__Name=Ordering HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__0__Uri=http://ordering.api/hc
|
||||
- HealthChecks-UI__HealthChecks__1__Name=Ordering HTTP Background Check
|
||||
- HealthChecks-UI__HealthChecks__1__Uri=http://ordering.backgroundtasks/hc
|
||||
- HealthChecks-UI__HealthChecks__2__Name=Basket HTTP Background Check
|
||||
- HealthChecks-UI__HealthChecks__2__Uri=http://basket.api/hc
|
||||
- HealthChecks-UI__HealthChecks__3__Name=Catalog HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__3__Uri=http://catalog.api/hc
|
||||
- HealthChecks-UI__HealthChecks__4__Name=Identity HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__4__Uri=http://identity.api/hc
|
||||
- HealthChecks-UI__HealthChecks__5__Name=Marketing HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__5__Uri=http://marketing.api/hc
|
||||
- HealthChecks-UI__HealthChecks__6__Name=Locations HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__6__Uri=http://locations.api/hc
|
||||
- HealthChecks-UI__HealthChecks__7__Name=Payments HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__7__Uri=http://payment.api/hc
|
||||
- HealthChecks-UI__HealthChecks__8__Name=Ordering SignalRHub HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__8__Uri=http://ordering.signalrhub/hc
|
||||
- HealthChecks-UI__HealthChecks__9__Name=WebMVC HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__9__Uri=http://webmvc/hc
|
||||
- HealthChecks-UI__HealthChecks__10__Name=WebSPA HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__10__Uri=http://webspa/hc
|
||||
- HealthChecks-UI__HealthChecks__11__Name=Mobile Shopping API GW HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__11__Uri=http://mobileshoppingapigw/hc
|
||||
- HealthChecks-UI__HealthChecks__12__Name=Mobile Marketing API GW HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__12__Uri=http://mobilemarketingapigw/hc
|
||||
- HealthChecks-UI__HealthChecks__13__Name=Web Shopping API GW HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__13__Uri=http://webshoppingapigw/hc
|
||||
- HealthChecks-UI__HealthChecks__14__Name=Web Marketing API GW HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__14__Uri=http://webmarketingapigw/hc
|
||||
- HealthChecks-UI__HealthChecks__15__Name=Mobile Shopping Aggregator HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__15__Uri=http://mobileshoppingagg/hc
|
||||
- HealthChecks-UI__HealthChecks__16__Name=Web Shopping API GW HTTP Check
|
||||
- HealthChecks-UI__HealthChecks__16__Uri=http://webshoppingagg/hc
|
||||
|
||||
- OrderingBackgroundTasksUrl=http://ordering.backgroundtasks/hc
|
||||
- BasketUrl=http://basket.api/hc
|
||||
- IdentityUrl=http://identity.api/hc
|
||||
@ -300,14 +376,11 @@ services:
|
||||
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||
- PurchaseUrl=http://webshoppingapigw
|
||||
- IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser.
|
||||
- MarketingUrl=http://webmarketingapigw
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser.
|
||||
- BasketUrlHC=http://basket.api/hc
|
||||
- MarketingUrlHC=http://marketing.api/hc
|
||||
- PaymentUrlHC=http://payment.api/hc
|
||||
- MarketingUrl=http://webmarketingapigw
|
||||
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
|
||||
- IdentityUrlHC=http://identity.api/hc
|
||||
- PurchaseUrlHC=http://webshoppingapigw/hc
|
||||
- MarketingUrlHC=http://webmarketingapigw/hc
|
||||
- UseCustomizationData=True
|
||||
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
||||
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
||||
|
@ -56,16 +56,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusRabbitMQ", "src\Bui
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationEventLogEF", "src\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj", "{9EE28E45-1533-472B-8267-56C48855BA0E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HealthChecks", "HealthChecks", "{A81ECBC2-6B00-4DCD-8388-469174033379}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj", "{942ED6E8-0050-495F-A0EA-01E97F63760C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebStatus", "src\Web\WebStatus\WebStatus.csproj", "{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HealthChecks", "src\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj", "{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.SqlServer", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj", "{4BD76717-3102-4969-8C2C-BAAA3F0263B6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}"
|
||||
@ -76,8 +68,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.API", "src\Servic
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusServiceBus", "src\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj", "{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.AzureStorage", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj", "{768C887F-C229-4B94-ACD8-0C7F65686524}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{1815B651-941C-466B-AE33-D1D7EEB8F77F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}"
|
||||
@ -644,54 +634,6 @@ Global
|
||||
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||
@ -740,102 +682,6 @@ Global
|
||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||
@ -980,54 +826,6 @@ Global
|
||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x64.Build.0 = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x86.Build.0 = Release|Any CPU
|
||||
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||
@ -1869,17 +1667,12 @@ Global
|
||||
{0044B293-1DCC-4224-B948-00CF6DC7F510} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||
{8088F3FC-6787-45FA-A924-816EC81CBFAC} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||
{9EE28E45-1533-472B-8267-56C48855BA0E} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||
{A81ECBC2-6B00-4DCD-8388-469174033379} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
||||
{942ED6E8-0050-495F-A0EA-01E97F63760C} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
|
||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||
{41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
|
||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6}
|
||||
{A5260DE0-1FDD-467E-9CC1-A028AB081CEE} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
|
||||
{DF395F85-B010-465D-857A-7EBCC512C0C2} = {A5260DE0-1FDD-467E-9CC1-A028AB081CEE}
|
||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||
{768C887F-C229-4B94-ACD8-0C7F65686524} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||
{1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
||||
{15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F}
|
||||
{77849D35-37D4-4802-81DC-9477B2775A40} = {932D8224-11F6-4D07-B109-DA28AD288A63}
|
||||
|
@ -4,10 +4,9 @@ EXPOSE 80
|
||||
|
||||
FROM microsoft/dotnet:2.2.100-preview3-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/
|
||||
RUN dotnet restore src/ApiGateways/ApiGw-Base/
|
||||
COPY . .
|
||||
WORKDIR /src/src/ApiGateways/ApiGw-Base/
|
||||
RUN dotnet restore -nowarn:msb3202,nu1503
|
||||
RUN dotnet build -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
|
@ -9,7 +9,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="Ocelot" Version="12.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,10 +1,13 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Middleware;
|
||||
using System;
|
||||
using HealthChecks.UI.Client;
|
||||
|
||||
namespace OcelotApiGw
|
||||
{
|
||||
@ -22,6 +25,15 @@ namespace OcelotApiGw
|
||||
var identityUrl = _cfg.GetValue<string>("IdentityUrl");
|
||||
var authenticationProviderKey = "IdentityApiKey";
|
||||
|
||||
services.AddHealthChecks()
|
||||
.AddUrlGroup(new Uri(_cfg["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
|
||||
.AddUrlGroup(new Uri(_cfg["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
|
||||
.AddUrlGroup(new Uri(_cfg["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
|
||||
.AddUrlGroup(new Uri(_cfg["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
|
||||
.AddUrlGroup(new Uri(_cfg["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
|
||||
.AddUrlGroup(new Uri(_cfg["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
|
||||
.AddUrlGroup(new Uri(_cfg["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
|
||||
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy",
|
||||
@ -75,6 +87,12 @@ namespace OcelotApiGw
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
loggerFactory.AddConsole(_cfg.GetSection("Logging"));
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
@ -12,7 +12,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="2.2.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.2.0-preview3-35497" />
|
||||
</ItemGroup>
|
||||
|
@ -17,6 +17,8 @@ using Microsoft.Extensions.Logging;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
using Swashbuckle.AspNetCore.Swagger;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
||||
{
|
||||
@ -32,6 +34,15 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddHealthChecks()
|
||||
.AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
|
||||
|
||||
services.AddCustomMvc(Configuration)
|
||||
.AddCustomAuthentication(Configuration)
|
||||
.AddHttpServices();
|
||||
@ -48,6 +59,12 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
if (env.IsDevelopment())
|
||||
|
@ -18,6 +18,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Net.Http;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
||||
{
|
||||
@ -33,6 +35,15 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddHealthChecks()
|
||||
.AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
|
||||
.AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
|
||||
|
||||
services.AddCustomMvc(Configuration)
|
||||
.AddCustomAuthentication(Configuration)
|
||||
.AddApplicationServices();
|
||||
@ -48,6 +59,12 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
if (env.IsDevelopment())
|
||||
|
@ -12,6 +12,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.2.0-preview3-35497" />
|
||||
|
@ -1,76 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.HealthChecks
|
||||
{
|
||||
public class HealthCheckMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly string _path;
|
||||
private readonly int? _port;
|
||||
private readonly IHealthCheckService _service;
|
||||
private readonly TimeSpan _timeout;
|
||||
|
||||
public HealthCheckMiddleware(RequestDelegate next, IHealthCheckService service, int port, TimeSpan timeout)
|
||||
{
|
||||
_port = port;
|
||||
_service = service;
|
||||
_next = next;
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
public HealthCheckMiddleware(RequestDelegate next, IHealthCheckService service, string path, TimeSpan timeout)
|
||||
{
|
||||
_path = path;
|
||||
_service = service;
|
||||
_next = next;
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
if (IsHealthCheckRequest(context))
|
||||
{
|
||||
var timeoutTokenSource = new CancellationTokenSource(_timeout);
|
||||
var result = await _service.CheckHealthAsync(timeoutTokenSource.Token);
|
||||
var status = result.CheckStatus;
|
||||
|
||||
if (status != CheckStatus.Healthy)
|
||||
context.Response.StatusCode = 503;
|
||||
|
||||
context.Response.Headers.Add("content-type", "application/json");
|
||||
await context.Response.WriteAsync(JsonConvert.SerializeObject(new { status = status.ToString() }));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsHealthCheckRequest(HttpContext context)
|
||||
{
|
||||
if (_port.HasValue)
|
||||
{
|
||||
var connInfo = context.Features.Get<IHttpConnectionFeature>();
|
||||
if (connInfo.LocalPort == _port)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (context.Request.Path == _path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace Microsoft.AspNetCore.HealthChecks
|
||||
{
|
||||
public class HealthCheckStartupFilter : IStartupFilter
|
||||
{
|
||||
private string _path;
|
||||
private int? _port;
|
||||
private TimeSpan _timeout;
|
||||
|
||||
public HealthCheckStartupFilter(int port, TimeSpan timeout)
|
||||
{
|
||||
_port = port;
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
public HealthCheckStartupFilter(string path, TimeSpan timeout)
|
||||
{
|
||||
_path = path;
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
|
||||
{
|
||||
return app =>
|
||||
{
|
||||
if (_port.HasValue)
|
||||
{
|
||||
app.UseMiddleware<HealthCheckMiddleware>(_port, _timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseMiddleware<HealthCheckMiddleware>(_path, _timeout);
|
||||
}
|
||||
|
||||
next(app);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.HealthChecks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
{
|
||||
public static class HealthCheckWebHostBuilderExtension
|
||||
{
|
||||
public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(10);
|
||||
|
||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, int port)
|
||||
=> UseHealthChecks(builder, port, DefaultTimeout);
|
||||
|
||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, int port, TimeSpan timeout)
|
||||
{
|
||||
Guard.ArgumentValid(port > 0 && port < 65536, nameof(port), "Port must be a value between 1 and 65535.");
|
||||
Guard.ArgumentValid(timeout > TimeSpan.Zero, nameof(timeout), "Health check timeout must be a positive time span.");
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
var existingUrl = builder.GetSetting(WebHostDefaults.ServerUrlsKey);
|
||||
builder.UseSetting(WebHostDefaults.ServerUrlsKey, $"{existingUrl};http://localhost:{port}");
|
||||
|
||||
services.AddSingleton<IStartupFilter>(new HealthCheckStartupFilter(port, timeout));
|
||||
});
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, string path)
|
||||
=> UseHealthChecks(builder, path, DefaultTimeout);
|
||||
|
||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, string path, TimeSpan timeout)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(path), path);
|
||||
// REVIEW: Is there a better URL path validator somewhere?
|
||||
Guard.ArgumentValid(!path.Contains("?"), nameof(path), "Path cannot contain query string values.");
|
||||
Guard.ArgumentValid(path.StartsWith("/"), nameof(path), "Path should start with '/'.");
|
||||
Guard.ArgumentValid(timeout > TimeSpan.Zero, nameof(timeout), "Health check timeout must be a positive time span.");
|
||||
|
||||
builder.ConfigureServices(services => services.AddSingleton<IStartupFilter>(new HealthCheckStartupFilter(path, timeout)));
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
{
|
||||
public static class HealthCheckWebHostExtensions
|
||||
{
|
||||
private const int DEFAULT_TIMEOUT_SECONDS = 300;
|
||||
|
||||
public static void RunWhenHealthy(this IWebHost webHost)
|
||||
{
|
||||
webHost.RunWhenHealthy(TimeSpan.FromSeconds(DEFAULT_TIMEOUT_SECONDS));
|
||||
}
|
||||
|
||||
public static void RunWhenHealthy(this IWebHost webHost, TimeSpan timeout)
|
||||
{
|
||||
var healthChecks = webHost.Services.GetService(typeof(IHealthCheckService)) as IHealthCheckService;
|
||||
|
||||
var loops = 0;
|
||||
do
|
||||
{
|
||||
var checkResult = healthChecks.CheckHealthAsync().Result;
|
||||
if (checkResult.CheckStatus == CheckStatus.Healthy)
|
||||
{
|
||||
webHost.Run();
|
||||
break;
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
loops++;
|
||||
|
||||
} while (loops < timeout.TotalSeconds);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0-preview3-35497" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,175 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.WindowsAzure.Storage;
|
||||
using Microsoft.WindowsAzure.Storage.Auth;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
// REVIEW: Do we want these to continue to use default parameters?
|
||||
// REVIEW: What are the appropriate guards for these functions?
|
||||
|
||||
public static class AzureHealthCheckBuilderExtensions
|
||||
{
|
||||
public static HealthCheckBuilder AddAzureBlobStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string containerName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
var credentials = new StorageCredentials(accountName, accountKey);
|
||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
||||
return AddAzureBlobStorageCheck(builder, storageAccount, containerName, cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddAzureBlobStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string containerName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
builder.AddCheck($"AzureBlobStorageCheck {storageAccount.BlobStorageUri} {containerName}", async () =>
|
||||
{
|
||||
bool result;
|
||||
try
|
||||
{
|
||||
var blobClient = storageAccount.CreateCloudBlobClient();
|
||||
|
||||
var properties = await blobClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(containerName))
|
||||
{
|
||||
var container = blobClient.GetContainerReference(containerName);
|
||||
|
||||
result = await container.ExistsAsync();
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result
|
||||
? HealthCheckResult.Healthy($"AzureBlobStorage {storageAccount.BlobStorageUri} is available")
|
||||
: HealthCheckResult.Unhealthy($"AzureBlobStorage {storageAccount.BlobStorageUri} is unavailable");
|
||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddAzureTableStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string tableName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
var credentials = new StorageCredentials(accountName, accountKey);
|
||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
||||
return AddAzureTableStorageCheck(builder, storageAccount, tableName, cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddAzureTableStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string tableName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
builder.AddCheck($"AzureTableStorageCheck {storageAccount.TableStorageUri} {tableName}", async () =>
|
||||
{
|
||||
bool result;
|
||||
try
|
||||
{
|
||||
var tableClient = storageAccount.CreateCloudTableClient();
|
||||
|
||||
var properties = await tableClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(tableName))
|
||||
{
|
||||
var table = tableClient.GetTableReference(tableName);
|
||||
|
||||
result = await table.ExistsAsync();
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result
|
||||
? HealthCheckResult.Healthy($"AzureTableStorage {storageAccount.BlobStorageUri} is available")
|
||||
: HealthCheckResult.Unhealthy($"AzureTableStorage {storageAccount.BlobStorageUri} is unavailable");
|
||||
|
||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddAzureFileStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string shareName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
var credentials = new StorageCredentials(accountName, accountKey);
|
||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
||||
return AddAzureFileStorageCheck(builder, storageAccount, shareName, cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddAzureFileStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string shareName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
builder.AddCheck($"AzureFileStorageCheck {storageAccount.FileStorageUri} {shareName}", async () =>
|
||||
{
|
||||
bool result;
|
||||
try
|
||||
{
|
||||
var fileClient = storageAccount.CreateCloudFileClient();
|
||||
|
||||
var properties = await fileClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(shareName))
|
||||
{
|
||||
var share = fileClient.GetShareReference(shareName);
|
||||
|
||||
result = await share.ExistsAsync();
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result
|
||||
? HealthCheckResult.Healthy($"AzureFileStorage {storageAccount.BlobStorageUri} is available")
|
||||
: HealthCheckResult.Unhealthy($"AzureFileStorage {storageAccount.BlobStorageUri} is unavailable");
|
||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddAzureQueueStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string queueName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
var credentials = new StorageCredentials(accountName, accountKey);
|
||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
||||
return AddAzureQueueStorageCheck(builder, storageAccount, queueName, cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddAzureQueueStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string queueName = null, TimeSpan? cacheDuration = null)
|
||||
{
|
||||
builder.AddCheck($"AzureQueueStorageCheck {storageAccount.QueueStorageUri} {queueName}", async () =>
|
||||
{
|
||||
bool result;
|
||||
try
|
||||
{
|
||||
var queueClient = storageAccount.CreateCloudQueueClient();
|
||||
|
||||
var properties = await queueClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(queueName))
|
||||
{
|
||||
var queue = queueClient.GetQueueReference(queueName);
|
||||
|
||||
result = await queue.ExistsAsync();
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result
|
||||
? HealthCheckResult.Healthy($"AzureFileStorage {storageAccount.BlobStorageUri} is available")
|
||||
: HealthCheckResult.Unhealthy($"AzureFileStorage {storageAccount.BlobStorageUri} is unavailable");
|
||||
|
||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
|
||||
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0" />
|
||||
<PackageReference Include="WindowsAzure.Storage" Version="9.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,22 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("HealthChecks.Azure")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("0c4158b7-7153-4d2e-abfa-4ce07d44f75f")]
|
@ -1,54 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
// REVIEW: What are the appropriate guards for these functions?
|
||||
|
||||
public static class HealthCheckBuilderSqlServerExtensions
|
||||
{
|
||||
public static HealthCheckBuilder AddSqlCheck(this HealthCheckBuilder builder, string name, string connectionString)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return AddSqlCheck(builder, name, connectionString, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddSqlCheck(this HealthCheckBuilder builder, string name, string connectionString, TimeSpan cacheDuration)
|
||||
{
|
||||
builder.AddCheck($"SqlCheck({name})", async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
//TODO: There is probably a much better way to do this.
|
||||
using (var connection = new SqlConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
using (var command = connection.CreateCommand())
|
||||
{
|
||||
command.CommandType = CommandType.Text;
|
||||
command.CommandText = "SELECT 1";
|
||||
var result = (int)await command.ExecuteScalarAsync().ConfigureAwait(false);
|
||||
if (result == 1)
|
||||
{
|
||||
return HealthCheckResult.Healthy($"SqlCheck({name}): Healthy");
|
||||
}
|
||||
|
||||
return HealthCheckResult.Unhealthy($"SqlCheck({name}): Unhealthy");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy($"SqlCheck({name}): Exception during check: {ex.GetType().FullName}");
|
||||
}
|
||||
}, cacheDuration);
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.6.0-preview3-27014-02" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,109 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public abstract class CachedHealthCheck
|
||||
{
|
||||
private static readonly TypeInfo HealthCheckTypeInfo = typeof(IHealthCheck).GetTypeInfo();
|
||||
|
||||
private volatile int _writerCount;
|
||||
|
||||
public CachedHealthCheck(string name, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
||||
Guard.ArgumentValid(cacheDuration.TotalMilliseconds >= 0, nameof(cacheDuration), "Cache duration must be zero (disabled) or greater than zero.");
|
||||
|
||||
Name = name;
|
||||
CacheDuration = cacheDuration;
|
||||
}
|
||||
|
||||
public IHealthCheckResult CachedResult { get; internal set; }
|
||||
|
||||
public TimeSpan CacheDuration { get; }
|
||||
|
||||
public DateTimeOffset CacheExpiration { get; internal set; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
protected virtual DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
|
||||
|
||||
protected abstract IHealthCheck Resolve(IServiceProvider serviceProvider);
|
||||
|
||||
public async ValueTask<IHealthCheckResult> RunAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
while (CacheExpiration <= UtcNow)
|
||||
{
|
||||
// Can't use a standard lock here because of async, so we'll use this flag to determine when we should write a value,
|
||||
// and the waiters who aren't allowed to write will just spin wait for the new value.
|
||||
if (Interlocked.Exchange(ref _writerCount, 1) != 0)
|
||||
{
|
||||
await Task.Delay(5, cancellationToken).ConfigureAwait(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var check = Resolve(serviceProvider);
|
||||
CachedResult = await check.CheckAsync(cancellationToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
CachedResult = HealthCheckResult.Unhealthy("The health check operation timed out");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CachedResult = HealthCheckResult.Unhealthy($"Exception during check: {ex.GetType().FullName}");
|
||||
}
|
||||
|
||||
CacheExpiration = UtcNow + CacheDuration;
|
||||
_writerCount = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return CachedResult;
|
||||
}
|
||||
|
||||
public static CachedHealthCheck FromHealthCheck(string name, TimeSpan cacheDuration, IHealthCheck healthCheck)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(healthCheck), healthCheck);
|
||||
|
||||
return new TypeOrHealthCheck_HealthCheck(name, cacheDuration, healthCheck);
|
||||
}
|
||||
|
||||
public static CachedHealthCheck FromType(string name, TimeSpan cacheDuration, Type healthCheckType)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(healthCheckType), healthCheckType);
|
||||
Guard.ArgumentValid(HealthCheckTypeInfo.IsAssignableFrom(healthCheckType.GetTypeInfo()), nameof(healthCheckType), $"Health check must implement '{typeof(IHealthCheck).FullName}'.");
|
||||
|
||||
return new TypeOrHealthCheck_Type(name, cacheDuration, healthCheckType);
|
||||
}
|
||||
|
||||
class TypeOrHealthCheck_HealthCheck : CachedHealthCheck
|
||||
{
|
||||
private readonly IHealthCheck _healthCheck;
|
||||
|
||||
public TypeOrHealthCheck_HealthCheck(string name, TimeSpan cacheDuration, IHealthCheck healthCheck) : base(name, cacheDuration)
|
||||
=> _healthCheck = healthCheck;
|
||||
|
||||
protected override IHealthCheck Resolve(IServiceProvider serviceProvider) => _healthCheck;
|
||||
}
|
||||
|
||||
class TypeOrHealthCheck_Type : CachedHealthCheck
|
||||
{
|
||||
private readonly Type _healthCheckType;
|
||||
|
||||
public TypeOrHealthCheck_Type(string name, TimeSpan cacheDuration, Type healthCheckType) : base(name, cacheDuration)
|
||||
=> _healthCheckType = healthCheckType;
|
||||
|
||||
protected override IHealthCheck Resolve(IServiceProvider serviceProvider)
|
||||
=> (IHealthCheck)serviceProvider.GetRequiredService(_healthCheckType);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public static class CachedHealthCheckExtensions
|
||||
{
|
||||
public static ValueTask<IHealthCheckResult> RunAsync(this CachedHealthCheck check, IServiceProvider serviceProvider)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(check), check);
|
||||
|
||||
return check.RunAsync(serviceProvider, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public enum CheckStatus
|
||||
{
|
||||
Unknown,
|
||||
Unhealthy,
|
||||
Healthy,
|
||||
Warning
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public static partial class HealthCheckBuilderExtensions
|
||||
{
|
||||
// Lambda versions of AddCheck for Func/Func<Task>/Func<ValueTask>
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<IHealthCheckResult> check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, IHealthCheckResult> check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<IHealthCheckResult> check, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, IHealthCheckResult> check, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<Task<IHealthCheckResult>> check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, Task<IHealthCheckResult>> check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<ValueTask<IHealthCheckResult>> check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), cacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), cacheDuration);
|
||||
}
|
||||
|
||||
// IHealthCheck versions of AddCheck
|
||||
|
||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string checkName, IHealthCheck check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck(checkName, check, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
// Type versions of AddCheck
|
||||
|
||||
public static HealthCheckBuilder AddCheck<TCheck>(this HealthCheckBuilder builder, string name) where TCheck : class, IHealthCheck
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return builder.AddCheck<TCheck>(name, builder.DefaultCacheDuration);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public static partial class HealthCheckBuilderExtensions
|
||||
{
|
||||
// Numeric checks
|
||||
|
||||
public static HealthCheckBuilder AddMinValueCheck<T>(this HealthCheckBuilder builder, string name, T minValue, Func<T> currentValueFunc) where T : IComparable<T>
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return AddMinValueCheck(builder, name, minValue, currentValueFunc, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddMinValueCheck<T>(this HealthCheckBuilder builder, string name, T minValue, Func<T> currentValueFunc, TimeSpan cacheDuration)
|
||||
where T : IComparable<T>
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
||||
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
|
||||
|
||||
builder.AddCheck(name, () =>
|
||||
{
|
||||
var currentValue = currentValueFunc();
|
||||
var status = currentValue.CompareTo(minValue) >= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
||||
return HealthCheckResult.FromStatus(
|
||||
status,
|
||||
$"min={minValue}, current={currentValue}",
|
||||
new Dictionary<string, object> { { "min", minValue }, { "current", currentValue } }
|
||||
);
|
||||
}, cacheDuration);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddMaxValueCheck<T>(this HealthCheckBuilder builder, string name, T maxValue, Func<T> currentValueFunc) where T : IComparable<T>
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return AddMaxValueCheck(builder, name, maxValue, currentValueFunc, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddMaxValueCheck<T>(this HealthCheckBuilder builder, string name, T maxValue, Func<T> currentValueFunc, TimeSpan cacheDuration)
|
||||
where T : IComparable<T>
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
||||
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
|
||||
|
||||
builder.AddCheck(name, () =>
|
||||
{
|
||||
var currentValue = currentValueFunc();
|
||||
var status = currentValue.CompareTo(maxValue) <= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
||||
return HealthCheckResult.FromStatus(
|
||||
status,
|
||||
$"max={maxValue}, current={currentValue}",
|
||||
new Dictionary<string, object> { { "max", maxValue }, { "current", currentValue } }
|
||||
);
|
||||
}, cacheDuration);
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public static partial class HealthCheckBuilderExtensions
|
||||
{
|
||||
// System checks
|
||||
|
||||
public static HealthCheckBuilder AddPrivateMemorySizeCheck(this HealthCheckBuilder builder, long maxSize)
|
||||
=> AddMaxValueCheck(builder, $"PrivateMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().PrivateMemorySize64);
|
||||
|
||||
public static HealthCheckBuilder AddPrivateMemorySizeCheck(this HealthCheckBuilder builder, long maxSize, TimeSpan cacheDuration)
|
||||
=> AddMaxValueCheck(builder, $"PrivateMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().PrivateMemorySize64, cacheDuration);
|
||||
|
||||
public static HealthCheckBuilder AddVirtualMemorySizeCheck(this HealthCheckBuilder builder, long maxSize)
|
||||
=> AddMaxValueCheck(builder, $"VirtualMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().VirtualMemorySize64);
|
||||
|
||||
public static HealthCheckBuilder AddVirtualMemorySizeCheck(this HealthCheckBuilder builder, long maxSize, TimeSpan cacheDuration)
|
||||
=> AddMaxValueCheck(builder, $"VirtualMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().VirtualMemorySize64, cacheDuration);
|
||||
|
||||
public static HealthCheckBuilder AddWorkingSetCheck(this HealthCheckBuilder builder, long maxSize)
|
||||
=> AddMaxValueCheck(builder, $"WorkingSet({maxSize})", maxSize, () => Process.GetCurrentProcess().WorkingSet64);
|
||||
|
||||
public static HealthCheckBuilder AddWorkingSetCheck(this HealthCheckBuilder builder, long maxSize, TimeSpan cacheDuration)
|
||||
=> AddMaxValueCheck(builder, $"WorkingSet({maxSize})", maxSize, () => Process.GetCurrentProcess().WorkingSet64, cacheDuration);
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.HealthChecks.Internal;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public static partial class HealthCheckBuilderExtensions
|
||||
{
|
||||
// Default URL check
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return AddUrlCheck(builder, url, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, TimeSpan cacheDuration)
|
||||
=> AddUrlCheck(builder, url, response => UrlChecker.DefaultUrlCheck(response), cacheDuration);
|
||||
|
||||
// Func returning IHealthCheckResult
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, Func<HttpResponseMessage, IHealthCheckResult> checkFunc)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return AddUrlCheck(builder, url, checkFunc, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
||||
Func<HttpResponseMessage, IHealthCheckResult> checkFunc,
|
||||
TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||
|
||||
return AddUrlCheck(builder, url, response => new ValueTask<IHealthCheckResult>(checkFunc(response)), cacheDuration);
|
||||
}
|
||||
|
||||
// Func returning Task<IHealthCheckResult>
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return AddUrlCheck(builder, url, checkFunc, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
||||
Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc,
|
||||
TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||
|
||||
return AddUrlCheck(builder, url, response => new ValueTask<IHealthCheckResult>(checkFunc(response)), cacheDuration);
|
||||
}
|
||||
|
||||
// Func returning ValueTask<IHealthCheckResult>
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
|
||||
return AddUrlCheck(builder, url, checkFunc, builder.DefaultCacheDuration);
|
||||
}
|
||||
|
||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
||||
Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc,
|
||||
TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(url), url);
|
||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||
|
||||
var urlCheck = new UrlChecker(checkFunc, url);
|
||||
builder.AddCheck($"UrlCheck({url})", () => urlCheck.CheckAsync(), cacheDuration);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a composite health check result built from several results.
|
||||
/// </summary>
|
||||
public class CompositeHealthCheckResult : IHealthCheckResult
|
||||
{
|
||||
private static readonly IReadOnlyDictionary<string, object> _emptyData = new Dictionary<string, object>();
|
||||
private readonly CheckStatus _initialStatus;
|
||||
private readonly CheckStatus _partiallyHealthyStatus;
|
||||
private readonly Dictionary<string, IHealthCheckResult> _results = new Dictionary<string, IHealthCheckResult>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public CompositeHealthCheckResult(CheckStatus partiallyHealthyStatus = CheckStatus.Warning,
|
||||
CheckStatus initialStatus = CheckStatus.Unknown)
|
||||
{
|
||||
_partiallyHealthyStatus = partiallyHealthyStatus;
|
||||
_initialStatus = initialStatus;
|
||||
}
|
||||
|
||||
public CheckStatus CheckStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
var checkStatuses = new HashSet<CheckStatus>(_results.Select(x => x.Value.CheckStatus));
|
||||
if (checkStatuses.Count == 0)
|
||||
{
|
||||
return _initialStatus;
|
||||
}
|
||||
if (checkStatuses.Count == 1)
|
||||
{
|
||||
return checkStatuses.First();
|
||||
}
|
||||
if (checkStatuses.Contains(CheckStatus.Healthy))
|
||||
{
|
||||
return _partiallyHealthyStatus;
|
||||
}
|
||||
|
||||
return CheckStatus.Unhealthy;
|
||||
}
|
||||
}
|
||||
|
||||
public string Description => string.Join(Environment.NewLine, _results.Select(r => $"{r.Key}: {r.Value.Description}"));
|
||||
|
||||
public IReadOnlyDictionary<string, object> Data
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new Dictionary<string, object>();
|
||||
|
||||
foreach (var kvp in _results)
|
||||
result.Add(kvp.Key, kvp.Value.Data);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, IHealthCheckResult> Results => _results;
|
||||
|
||||
public void Add(string name, CheckStatus status, string description)
|
||||
=> Add(name, status, description, null);
|
||||
|
||||
public void Add(string name, CheckStatus status, string description, Dictionary<string, object> data)
|
||||
{
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
||||
Guard.ArgumentValid(status != CheckStatus.Unknown, nameof(status), "Cannot add 'Unknown' status to composite health check result.");
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(description), description);
|
||||
|
||||
_results.Add(name, HealthCheckResult.FromStatus(status, description, data));
|
||||
}
|
||||
|
||||
public void Add(string name, IHealthCheckResult checkResult)
|
||||
{
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
||||
Guard.ArgumentNotNull(nameof(checkResult), checkResult);
|
||||
|
||||
_results.Add(name, checkResult);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public class HealthCheck : IHealthCheck
|
||||
{
|
||||
protected HealthCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(check), check);
|
||||
|
||||
Check = check;
|
||||
}
|
||||
|
||||
protected Func<CancellationToken, ValueTask<IHealthCheckResult>> Check { get; }
|
||||
|
||||
public ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||
=> Check(cancellationToken);
|
||||
|
||||
public static HealthCheck FromCheck(Func<IHealthCheckResult> check)
|
||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()));
|
||||
|
||||
public static HealthCheck FromCheck(Func<CancellationToken, IHealthCheckResult> check)
|
||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)));
|
||||
|
||||
public static HealthCheck FromTaskCheck(Func<Task<IHealthCheckResult>> check)
|
||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()));
|
||||
|
||||
public static HealthCheck FromTaskCheck(Func<CancellationToken, Task<IHealthCheckResult>> check)
|
||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)));
|
||||
|
||||
public static HealthCheck FromValueTaskCheck(Func<ValueTask<IHealthCheckResult>> check)
|
||||
=> new HealthCheck(token => check());
|
||||
|
||||
public static HealthCheck FromValueTaskCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
|
||||
=> new HealthCheck(check);
|
||||
}
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public class HealthCheckBuilder
|
||||
{
|
||||
private readonly Dictionary<string, CachedHealthCheck> _checksByName;
|
||||
private readonly HealthCheckGroup _currentGroup;
|
||||
private readonly Dictionary<string, HealthCheckGroup> _groups;
|
||||
|
||||
public HealthCheckBuilder()
|
||||
{
|
||||
_checksByName = new Dictionary<string, CachedHealthCheck>(StringComparer.OrdinalIgnoreCase);
|
||||
_currentGroup = new HealthCheckGroup(string.Empty, CheckStatus.Unhealthy);
|
||||
_groups = new Dictionary<string, HealthCheckGroup>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
[string.Empty] = _currentGroup
|
||||
};
|
||||
|
||||
DefaultCacheDuration = TimeSpan.FromMinutes(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This constructor should only be used when creating a grouped health check builder.
|
||||
/// </summary>
|
||||
public HealthCheckBuilder(HealthCheckBuilder rootBuilder, HealthCheckGroup currentGroup)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(rootBuilder), rootBuilder);
|
||||
Guard.ArgumentNotNull(nameof(currentGroup), currentGroup);
|
||||
|
||||
_checksByName = rootBuilder._checksByName;
|
||||
_currentGroup = currentGroup;
|
||||
_groups = rootBuilder._groups;
|
||||
|
||||
DefaultCacheDuration = rootBuilder.DefaultCacheDuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the registered checks, indexed by check name.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, CachedHealthCheck> ChecksByName => _checksByName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current default cache duration used when registering checks.
|
||||
/// </summary>
|
||||
public TimeSpan DefaultCacheDuration { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the registered groups, indexed by group name. The root group's name is <see cref="string.Empty"/>.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, HealthCheckGroup> Groups => _groups;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a health check type that will later be resolved via dependency
|
||||
/// injection.
|
||||
/// </summary>
|
||||
public HealthCheckBuilder AddCheck<TCheck>(string checkName, TimeSpan cacheDuration) where TCheck : class, IHealthCheck
|
||||
{
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(checkName), checkName);
|
||||
Guard.ArgumentValid(!_checksByName.ContainsKey(checkName), nameof(checkName), $"A check with name '{checkName}' has already been registered.");
|
||||
|
||||
var namedCheck = CachedHealthCheck.FromType(checkName, cacheDuration, typeof(TCheck));
|
||||
|
||||
_checksByName.Add(checkName, namedCheck);
|
||||
_currentGroup.ChecksInternal.Add(namedCheck);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a concrete health check to the builder.
|
||||
/// </summary>
|
||||
public HealthCheckBuilder AddCheck(string checkName, IHealthCheck check, TimeSpan cacheDuration)
|
||||
{
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(checkName), checkName);
|
||||
Guard.ArgumentNotNull(nameof(check), check);
|
||||
Guard.ArgumentValid(!_checksByName.ContainsKey(checkName), nameof(checkName), $"A check with name '{checkName}' has already been registered.");
|
||||
|
||||
var namedCheck = CachedHealthCheck.FromHealthCheck(checkName, cacheDuration, check);
|
||||
|
||||
_checksByName.Add(checkName, namedCheck);
|
||||
_currentGroup.ChecksInternal.Add(namedCheck);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new health check group, to which you can add one or more health
|
||||
/// checks. Uses <see cref="CheckStatus.Unhealthy"/> when the group is
|
||||
/// partially successful.
|
||||
/// </summary>
|
||||
public HealthCheckBuilder AddHealthCheckGroup(string groupName, Action<HealthCheckBuilder> groupChecks)
|
||||
=> AddHealthCheckGroup(groupName, groupChecks, CheckStatus.Unhealthy);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new health check group, to which you can add one or more health
|
||||
/// checks.
|
||||
/// </summary>
|
||||
public HealthCheckBuilder AddHealthCheckGroup(string groupName, Action<HealthCheckBuilder> groupChecks, CheckStatus partialSuccessStatus)
|
||||
{
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(groupName), groupName);
|
||||
Guard.ArgumentNotNull(nameof(groupChecks), groupChecks);
|
||||
Guard.ArgumentValid(partialSuccessStatus != CheckStatus.Unknown, nameof(partialSuccessStatus), "Check status 'Unknown' is not valid for partial success.");
|
||||
Guard.ArgumentValid(!_groups.ContainsKey(groupName), nameof(groupName), $"A group with name '{groupName}' has already been registered.");
|
||||
Guard.OperationValid(_currentGroup.GroupName == string.Empty, "Nested groups are not supported by HealthCheckBuilder.");
|
||||
|
||||
var group = new HealthCheckGroup(groupName, partialSuccessStatus);
|
||||
_groups.Add(groupName, group);
|
||||
|
||||
var innerBuilder = new HealthCheckBuilder(this, group);
|
||||
groupChecks(innerBuilder);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public HealthCheckBuilder WithDefaultCacheDuration(TimeSpan duration)
|
||||
{
|
||||
Guard.ArgumentValid(duration >= TimeSpan.Zero, nameof(duration), "Duration must be zero (disabled) or a positive duration.");
|
||||
|
||||
DefaultCacheDuration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HealthCheckBuilder WithPartialSuccessStatus(CheckStatus partiallyHealthyStatus)
|
||||
{
|
||||
_currentGroup.PartiallyHealthyStatus = partiallyHealthyStatus;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public class HealthCheckGroup
|
||||
{
|
||||
private CheckStatus _partialSuccessStatus;
|
||||
|
||||
public HealthCheckGroup(string groupName, CheckStatus partialSuccessStatus)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(groupName), groupName);
|
||||
|
||||
GroupName = groupName;
|
||||
PartiallyHealthyStatus = partialSuccessStatus;
|
||||
}
|
||||
|
||||
public IReadOnlyList<CachedHealthCheck> Checks => ChecksInternal.AsReadOnly();
|
||||
|
||||
internal List<CachedHealthCheck> ChecksInternal { get; } = new List<CachedHealthCheck>();
|
||||
|
||||
public string GroupName { get; }
|
||||
|
||||
public CheckStatus PartiallyHealthyStatus
|
||||
{
|
||||
get => _partialSuccessStatus;
|
||||
internal set
|
||||
{
|
||||
Guard.ArgumentValid(value != CheckStatus.Unknown, nameof(value), "Check status 'Unknown' is not valid for partial success.");
|
||||
|
||||
_partialSuccessStatus = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public class HealthCheckResult : IHealthCheckResult
|
||||
{
|
||||
private static readonly IReadOnlyDictionary<string, object> _emptyData = new Dictionary<string, object>();
|
||||
|
||||
public CheckStatus CheckStatus { get; }
|
||||
public IReadOnlyDictionary<string, object> Data { get; }
|
||||
public string Description { get; }
|
||||
|
||||
private HealthCheckResult(CheckStatus checkStatus, string description, IReadOnlyDictionary<string, object> data)
|
||||
{
|
||||
CheckStatus = checkStatus;
|
||||
Description = description;
|
||||
Data = data ?? _emptyData;
|
||||
}
|
||||
|
||||
public static HealthCheckResult Unhealthy(string description)
|
||||
=> new HealthCheckResult(CheckStatus.Unhealthy, description, null);
|
||||
|
||||
public static HealthCheckResult Unhealthy(string description, IReadOnlyDictionary<string, object> data)
|
||||
=> new HealthCheckResult(CheckStatus.Unhealthy, description, data);
|
||||
|
||||
public static HealthCheckResult Healthy(string description)
|
||||
=> new HealthCheckResult(CheckStatus.Healthy, description, null);
|
||||
|
||||
public static HealthCheckResult Healthy(string description, IReadOnlyDictionary<string, object> data)
|
||||
=> new HealthCheckResult(CheckStatus.Healthy, description, data);
|
||||
|
||||
public static HealthCheckResult Warning(string description)
|
||||
=> new HealthCheckResult(CheckStatus.Warning, description, null);
|
||||
|
||||
public static HealthCheckResult Warning(string description, IReadOnlyDictionary<string, object> data)
|
||||
=> new HealthCheckResult(CheckStatus.Warning, description, data);
|
||||
|
||||
public static HealthCheckResult Unknown(string description)
|
||||
=> new HealthCheckResult(CheckStatus.Unknown, description, null);
|
||||
|
||||
public static HealthCheckResult Unknown(string description, IReadOnlyDictionary<string, object> data)
|
||||
=> new HealthCheckResult(CheckStatus.Unknown, description, data);
|
||||
|
||||
public static HealthCheckResult FromStatus(CheckStatus status, string description)
|
||||
=> new HealthCheckResult(status, description, null);
|
||||
|
||||
public static HealthCheckResult FromStatus(CheckStatus status, string description, IReadOnlyDictionary<string, object> data)
|
||||
=> new HealthCheckResult(status, description, data);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public class HealthCheckResults
|
||||
{
|
||||
public IList<IHealthCheckResult> CheckResults { get; } = new List<IHealthCheckResult>();
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public class HealthCheckService : IHealthCheckService
|
||||
{
|
||||
private readonly HealthCheckBuilder _builder;
|
||||
private readonly IReadOnlyList<HealthCheckGroup> _groups;
|
||||
private readonly HealthCheckGroup _root;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
|
||||
public HealthCheckService(HealthCheckBuilder builder, IServiceProvider serviceProvider, IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
_builder = builder;
|
||||
_groups = GetGroups().Where(group => group.GroupName != string.Empty).ToList();
|
||||
_root = GetGroup(string.Empty);
|
||||
_serviceProvider = serviceProvider;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
}
|
||||
|
||||
public async Task<CompositeHealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
using (var scope = GetServiceScope())
|
||||
{
|
||||
var scopeServiceProvider = scope.ServiceProvider;
|
||||
var groupTasks = _groups.Select(group => new { Group = group, Task = RunGroupAsync(scopeServiceProvider, group, cancellationToken) }).ToList();
|
||||
var result = await RunGroupAsync(scopeServiceProvider, _root, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await Task.WhenAll(groupTasks.Select(x => x.Task));
|
||||
|
||||
foreach (var groupTask in groupTasks)
|
||||
{
|
||||
result.Add($"Group({groupTask.Group.GroupName})", groupTask.Task.Result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<CachedHealthCheck> GetAllChecks()
|
||||
=> _builder.ChecksByName.Values.ToList().AsReadOnly();
|
||||
|
||||
public CachedHealthCheck GetCheck(string checkName)
|
||||
=> _builder.ChecksByName[checkName];
|
||||
|
||||
public HealthCheckGroup GetGroup(string groupName)
|
||||
=> _builder.Groups[groupName];
|
||||
|
||||
public IReadOnlyList<HealthCheckGroup> GetGroups()
|
||||
=> _builder.Groups.Values.ToList().AsReadOnly();
|
||||
|
||||
private IServiceScope GetServiceScope()
|
||||
=> _serviceScopeFactory == null ? new UnscopedServiceProvider(_serviceProvider) : _serviceScopeFactory.CreateScope();
|
||||
|
||||
public async ValueTask<IHealthCheckResult> RunCheckAsync(CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
using (var scope = GetServiceScope())
|
||||
{
|
||||
return await RunCheckAsync(scope.ServiceProvider, healthCheck, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses the provided service provider and executes the provided check.
|
||||
/// </summary>
|
||||
public ValueTask<IHealthCheckResult> RunCheckAsync(IServiceProvider serviceProvider, CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(serviceProvider), serviceProvider);
|
||||
Guard.ArgumentNotNull(nameof(healthCheck), healthCheck);
|
||||
|
||||
return healthCheck.RunAsync(serviceProvider, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new resolution scope from the default service provider and executes the checks in the given group.
|
||||
/// </summary>
|
||||
public async Task<CompositeHealthCheckResult> RunGroupAsync(HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
using (var scope = GetServiceScope())
|
||||
return await RunGroupAsync(scope.ServiceProvider, group, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses the provided service provider and executes the checks in the given group.
|
||||
/// </summary>
|
||||
public async Task<CompositeHealthCheckResult> RunGroupAsync(IServiceProvider serviceProvider, HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = new CompositeHealthCheckResult(group.PartiallyHealthyStatus);
|
||||
var checkTasks = group.Checks.Select(check => new { Check = check, Task = check.RunAsync(serviceProvider, cancellationToken).AsTask() }).ToList();
|
||||
await Task.WhenAll(checkTasks.Select(checkTask => checkTask.Task));
|
||||
|
||||
foreach (var checkTask in checkTasks)
|
||||
{
|
||||
result.Add(checkTask.Check.Name, checkTask.Task.Result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private class UnscopedServiceProvider : IServiceScope
|
||||
{
|
||||
public UnscopedServiceProvider(IServiceProvider serviceProvider)
|
||||
=> ServiceProvider = serviceProvider;
|
||||
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class HealthCheckServiceCollectionExtensions
|
||||
{
|
||||
private static readonly Type HealthCheckServiceInterface = typeof(IHealthCheckService);
|
||||
|
||||
public static IServiceCollection AddHealthChecks(this IServiceCollection services, Action<HealthCheckBuilder> checks)
|
||||
{
|
||||
Guard.OperationValid(!services.Any(descriptor => descriptor.ServiceType == HealthCheckServiceInterface), "AddHealthChecks may only be called once.");
|
||||
|
||||
var builder = new HealthCheckBuilder();
|
||||
|
||||
services.AddSingleton<IHealthCheckService, HealthCheckService>(serviceProvider =>
|
||||
{
|
||||
var serviceScopeFactory = serviceProvider.GetService<IServiceScopeFactory>();
|
||||
return new HealthCheckService(builder, serviceProvider, serviceScopeFactory);
|
||||
});
|
||||
|
||||
checks(builder);
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public interface IHealthCheck
|
||||
{
|
||||
ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public interface IHealthCheckResult
|
||||
{
|
||||
CheckStatus CheckStatus { get; }
|
||||
string Description { get; }
|
||||
IReadOnlyDictionary<string, object> Data { get; }
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks
|
||||
{
|
||||
public interface IHealthCheckService
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs all registered health checks.
|
||||
/// </summary>
|
||||
Task<CompositeHealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Gets all registered health checks as a flat list.
|
||||
/// </summary>
|
||||
IReadOnlyList<CachedHealthCheck> GetAllChecks();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a health check by name.
|
||||
/// </summary>
|
||||
CachedHealthCheck GetCheck(string checkName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all health checks in a group.
|
||||
/// </summary>
|
||||
HealthCheckGroup GetGroup(string groupName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the health check groups.
|
||||
/// </summary>
|
||||
IReadOnlyList<HealthCheckGroup> GetGroups();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new resolution scope from the default service provider and executes the provided check.
|
||||
/// </summary>
|
||||
ValueTask<IHealthCheckResult> RunCheckAsync(CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Uses the provided service provider and executes the provided check.
|
||||
/// </summary>
|
||||
ValueTask<IHealthCheckResult> RunCheckAsync(IServiceProvider serviceProvider, CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new resolution scope from the default service provider and executes the checks in the given group.
|
||||
/// </summary>
|
||||
Task<CompositeHealthCheckResult> RunGroupAsync(HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Uses the provided service provider and executes the checks in the given group.
|
||||
/// </summary>
|
||||
Task<CompositeHealthCheckResult> RunGroupAsync(IServiceProvider serviceProvider, HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Extensions.HealthChecks.Internal
|
||||
{
|
||||
public class UrlChecker
|
||||
{
|
||||
private readonly Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> _checkFunc;
|
||||
private readonly string _url;
|
||||
|
||||
public UrlChecker(Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc, string url)
|
||||
{
|
||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
||||
Guard.ArgumentNotNullOrEmpty(nameof(url), url);
|
||||
|
||||
_checkFunc = checkFunc;
|
||||
_url = url;
|
||||
}
|
||||
|
||||
public CheckStatus PartiallyHealthyStatus { get; set; } = CheckStatus.Warning;
|
||||
|
||||
public async Task<IHealthCheckResult> CheckAsync()
|
||||
{
|
||||
using (var httpClient = CreateHttpClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await httpClient.GetAsync(_url).ConfigureAwait(false);
|
||||
return await _checkFunc(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var data = new Dictionary<string, object> { { "url", _url } };
|
||||
return HealthCheckResult.Unhealthy($"Exception during check: {ex.GetType().FullName}", data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private HttpClient CreateHttpClient()
|
||||
{
|
||||
var httpClient = GetHttpClient();
|
||||
httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true };
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public static async ValueTask<IHealthCheckResult> DefaultUrlCheck(HttpResponseMessage response)
|
||||
{
|
||||
var status = response.IsSuccessStatusCode ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
||||
var data = new Dictionary<string, object>
|
||||
{
|
||||
{ "url", response.RequestMessage.RequestUri.ToString() },
|
||||
{ "status", (int)response.StatusCode },
|
||||
{ "reason", response.ReasonPhrase },
|
||||
{ "body", await response.Content?.ReadAsStringAsync() }
|
||||
};
|
||||
return HealthCheckResult.FromStatus(status, $"status code {response.StatusCode} ({(int)response.StatusCode})", data);
|
||||
}
|
||||
|
||||
protected virtual HttpClient GetHttpClient()
|
||||
=> new HttpClient();
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
|
||||
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,57 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
static class Guard
|
||||
{
|
||||
public static void ArgumentNotNull(string argumentName, object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(argumentName);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ArgumentNotNullOrEmpty(string argumentName, string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(argumentName);
|
||||
}
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
throw new ArgumentException("Value cannot be an empty string.", argumentName);
|
||||
}
|
||||
}
|
||||
|
||||
// Use IReadOnlyCollection<T> instead of IEnumerable<T> to discourage double enumeration
|
||||
public static void ArgumentNotNullOrEmpty<T>(string argumentName, IReadOnlyCollection<T> items)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
throw new ArgumentNullException(argumentName);
|
||||
}
|
||||
if (items.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("Collection must contain at least one item.", argumentName);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ArgumentValid(bool valid, string argumentName, string exceptionMessage)
|
||||
{
|
||||
if (!valid)
|
||||
{
|
||||
throw new ArgumentException(exceptionMessage, argumentName);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OperationValid(bool valid, string exceptionMessage)
|
||||
{
|
||||
if (!valid)
|
||||
{
|
||||
throw new InvalidOperationException(exceptionMessage);
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
@ -21,16 +25,15 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.4" />
|
||||
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.6" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -22,7 +22,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
{
|
||||
options.ConfigPath = "/Failing";
|
||||
})
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
|
@ -4,10 +4,13 @@ using Basket.API.Infrastructure.Filters;
|
||||
using Basket.API.Infrastructure.Middlewares;
|
||||
using Basket.API.IntegrationEvents.EventHandling;
|
||||
using Basket.API.IntegrationEvents.Events;
|
||||
using HealthChecks.UI.Client;
|
||||
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -22,7 +25,6 @@ using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
||||
using Microsoft.eShopOnContainers.Services.Basket.API.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using RabbitMQ.Client;
|
||||
@ -31,7 +33,6 @@ using Swashbuckle.AspNetCore.Swagger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
{
|
||||
@ -62,12 +63,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
|
||||
ConfigureAuthService(services);
|
||||
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")),
|
||||
TimeSpan.Zero //No cache for this HealthCheck, better just for demos
|
||||
);
|
||||
});
|
||||
services.AddCustomHealthCheck(Configuration);
|
||||
|
||||
services.Configure<BasketSettings>(Configuration);
|
||||
|
||||
@ -192,6 +188,11 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
@ -312,6 +313,40 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
|
||||
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
|
||||
eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomExtensionMethods
|
||||
{
|
||||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
hcBuilder
|
||||
.AddRedis(
|
||||
configuration["ConnectionString"],
|
||||
name: "redis-check",
|
||||
tags: new string[] { "redis" });
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "basket-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "basket-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,11 +34,17 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureStorage" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
@ -50,10 +56,6 @@
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -34,7 +34,6 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>()
|
||||
.UseApplicationInsights()
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseWebRoot("Pics")
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
|
@ -22,13 +22,14 @@ using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHa
|
||||
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using RabbitMQ.Client;
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Reflection;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||
{
|
||||
@ -49,7 +50,8 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||
.AddCustomOptions(Configuration)
|
||||
.AddIntegrationServices(Configuration)
|
||||
.AddEventBus(Configuration)
|
||||
.AddSwagger();
|
||||
.AddSwagger()
|
||||
.AddCustomHealthCheck(Configuration);
|
||||
|
||||
var container = new ContainerBuilder();
|
||||
container.Populate(services);
|
||||
@ -72,6 +74,12 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
@ -120,24 +128,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||
}
|
||||
|
||||
public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
checks.AddSqlCheck("CatalogDb", configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
|
||||
|
||||
var accountName = configuration.GetValue<string>("AzureStorageAccountName");
|
||||
var accountKey = configuration.GetValue<string>("AzureStorageAccountKey");
|
||||
if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
|
||||
{
|
||||
checks.AddAzureBlobStorageCheck(accountName, accountKey);
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||
@ -157,6 +148,49 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var accountName = configuration.GetValue<string>("AzureStorageAccountName");
|
||||
var accountKey = configuration.GetValue<string>("AzureStorageAccountKey");
|
||||
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
hcBuilder
|
||||
.AddSqlServer(
|
||||
configuration["ConnectionString"],
|
||||
name: "CatalogDB-check",
|
||||
tags: new string[] { "catalogdb" });
|
||||
|
||||
if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureBlobStorage(
|
||||
$"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net",
|
||||
name: "catalog-storage-check",
|
||||
tags: new string[] { "catalogstorage" });
|
||||
}
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "catalog-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "catalog-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddDbContext<CatalogContext>(options =>
|
||||
|
@ -13,6 +13,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
@ -41,9 +44,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -40,7 +40,6 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseKestrel()
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
|
@ -15,11 +15,12 @@ using Microsoft.eShopOnContainers.Services.Identity.API.Models;
|
||||
using Microsoft.eShopOnContainers.Services.Identity.API.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Services.Identity.API
|
||||
{
|
||||
@ -65,16 +66,11 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
|
||||
.PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
|
||||
}
|
||||
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
checks.AddSqlCheck("Identity_Db", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
|
||||
});
|
||||
|
||||
services.AddHealthChecks()
|
||||
.AddSqlServer(Configuration["ConnectionString"],
|
||||
name: "IdentityDB-check",
|
||||
tags: new string[] { "IdentityDB" });
|
||||
|
||||
services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();
|
||||
services.AddTransient<IRedirectService, RedirectService>();
|
||||
|
||||
@ -143,6 +139,12 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
|
||||
}
|
||||
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
|
@ -6,11 +6,16 @@
|
||||
<UserSecretsId>aspnet-Locations.API-20161122013619</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.MongoDb" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
@ -24,8 +29,6 @@
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -17,7 +17,6 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
|
@ -1,9 +1,11 @@
|
||||
using Autofac;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -19,14 +21,12 @@ using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Reposito
|
||||
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using RabbitMQ.Client;
|
||||
using Swashbuckle.AspNetCore.Swagger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||
{
|
||||
@ -43,7 +43,9 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||
{
|
||||
RegisterAppInsights(services);
|
||||
|
||||
services.AddMvc(options =>
|
||||
services
|
||||
.AddCustomHealthCheck(Configuration)
|
||||
.AddMvc(options =>
|
||||
{
|
||||
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||
})
|
||||
@ -95,12 +97,7 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||
|
||||
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
|
||||
});
|
||||
}
|
||||
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")));
|
||||
});
|
||||
}
|
||||
|
||||
RegisterEventBus(services);
|
||||
|
||||
@ -169,6 +166,12 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
ConfigureAuth(app);
|
||||
@ -272,4 +275,38 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomExtensionMethods
|
||||
{
|
||||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
hcBuilder
|
||||
.AddMongoDb(
|
||||
configuration["ConnectionString"],
|
||||
name: "locations-mongodb-check",
|
||||
tags: new string[] { "mongodb" });
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "locations-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "locations-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,17 @@
|
||||
<Folder Include="Infrastructure\MarketingMigrations\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureStorage" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.MongoDb" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0-preview3-35497" />
|
||||
@ -36,9 +43,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -28,7 +28,6 @@
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseApplicationInsights()
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseWebRoot("Pics")
|
||||
|
@ -13,8 +13,8 @@
|
||||
using EntityFrameworkCore;
|
||||
using Extensions.Configuration;
|
||||
using Extensions.DependencyInjection;
|
||||
using Extensions.HealthChecks;
|
||||
using Extensions.Logging;
|
||||
using HealthChecks.UI.Client;
|
||||
using Infrastructure;
|
||||
using Infrastructure.Filters;
|
||||
using Infrastructure.Repositories;
|
||||
@ -24,6 +24,7 @@
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Middlewares;
|
||||
@ -33,7 +34,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
@ -51,29 +51,19 @@
|
||||
RegisterAppInsights(services);
|
||||
|
||||
// Add framework services.
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||
})
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
|
||||
.AddControllersAsServices(); //Injecting Controllers themselves thru DIFor further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
|
||||
services
|
||||
.AddCustomHealthCheck(Configuration)
|
||||
.AddMvc(options =>
|
||||
{
|
||||
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||
})
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
|
||||
.AddControllersAsServices(); //Injecting Controllers themselves thru DIFor further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
|
||||
|
||||
services.Configure<MarketingSettings>(Configuration);
|
||||
|
||||
ConfigureAuthService(services);
|
||||
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")));
|
||||
|
||||
var accountName = Configuration.GetValue<string>("AzureStorageAccountName");
|
||||
var accountKey = Configuration.GetValue<string>("AzureStorageAccountKey");
|
||||
if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
|
||||
{
|
||||
checks.AddAzureBlobStorageCheck(accountName, accountKey);
|
||||
}
|
||||
});
|
||||
|
||||
services.AddDbContext<MarketingContext>(options =>
|
||||
{
|
||||
options.UseSqlServer(Configuration["ConnectionString"],
|
||||
@ -197,6 +187,12 @@
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
@ -310,4 +306,53 @@
|
||||
app.UseAuthentication();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomExtensionMethods
|
||||
{
|
||||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
hcBuilder
|
||||
.AddSqlServer(
|
||||
configuration["ConnectionString"],
|
||||
name: "MarketingDB-check",
|
||||
tags: new string[] { "marketingdb" })
|
||||
.AddMongoDb(
|
||||
configuration["MongoConnectionString"],
|
||||
name: "MarketingDB-mongodb-check",
|
||||
tags: new string[] { "mongodb" });
|
||||
|
||||
var accountName = configuration.GetValue<string>("AzureStorageAccountName");
|
||||
var accountKey = configuration.GetValue<string>("AzureStorageAccountKey");
|
||||
if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureBlobStorage(
|
||||
$"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net",
|
||||
name: "marketing-storage-check",
|
||||
tags: new string[] { "marketingstorage" });
|
||||
}
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "marketing-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "marketing-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,16 +20,17 @@
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
|
||||
<ProjectReference Include="..\Ordering.Domain\Ordering.Domain.csproj" />
|
||||
<ProjectReference Include="..\Ordering.Infrastructure\Ordering.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="7.5.0" />
|
||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="5.1.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
@ -37,6 +38,7 @@
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
|
@ -34,7 +34,6 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>()
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
{
|
||||
|
@ -26,7 +26,6 @@
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ordering.Infrastructure;
|
||||
using RabbitMQ.Client;
|
||||
@ -36,6 +35,8 @@
|
||||
using System.Data.Common;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Reflection;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
@ -88,6 +89,13 @@
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
ConfigureAuth(app);
|
||||
|
||||
app.UseMvcWithDefaultRoute();
|
||||
@ -175,15 +183,31 @@
|
||||
|
||||
public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddHealthChecks(checks =>
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
hcBuilder
|
||||
.AddSqlServer(
|
||||
configuration["ConnectionString"],
|
||||
name: "OrderingDB-check",
|
||||
tags: new string[] { "orderingdb" });
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
checks.AddSqlCheck("OrderingDb", configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
|
||||
});
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "ordering-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "ordering-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
@ -14,18 +14,20 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Dapper" Version="1.50.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -13,8 +13,7 @@ namespace Ordering.BackgroundTasks
|
||||
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>()
|
||||
.UseHealthChecks("/hc")
|
||||
.UseStartup<Startup>()
|
||||
.ConfigureLogging((hostingContext, builder) =>
|
||||
{
|
||||
builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
|
||||
|
@ -9,13 +9,14 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ordering.BackgroundTasks.Configuration;
|
||||
using Ordering.BackgroundTasks.Tasks;
|
||||
using RabbitMQ.Client;
|
||||
using System;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace Ordering.BackgroundTasks
|
||||
{
|
||||
@ -32,16 +33,7 @@ namespace Ordering.BackgroundTasks
|
||||
public IServiceProvider ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
//add health check for this service
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
|
||||
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
checks.AddSqlCheck("OrderingDb", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
|
||||
});
|
||||
services.AddCustomHealthCheck(Configuration);
|
||||
|
||||
//configure settings
|
||||
|
||||
@ -112,6 +104,11 @@ namespace Ordering.BackgroundTasks
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env)
|
||||
{
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
@ -158,4 +155,38 @@ namespace Ordering.BackgroundTasks
|
||||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomExtensionMethods
|
||||
{
|
||||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
hcBuilder
|
||||
.AddSqlServer(
|
||||
configuration["ConnectionString"],
|
||||
name: "OrderingTaskDB-check",
|
||||
tags: new string[] { "orderingtaskdb" });
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "orderingtask-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "orderingtask-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.1.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Redis" Version="1.1.0-preview3-35497" />
|
||||
|
@ -15,9 +15,10 @@ using Ordering.SignalrHub.IntegrationEvents;
|
||||
using Ordering.SignalrHub.IntegrationEvents.EventHandling;
|
||||
using Ordering.SignalrHub.IntegrationEvents.Events;
|
||||
using RabbitMQ.Client;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace Ordering.SignalrHub
|
||||
{
|
||||
@ -32,14 +33,16 @@ namespace Ordering.SignalrHub
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public IServiceProvider ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy",
|
||||
builder => builder.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials());
|
||||
});
|
||||
services
|
||||
.AddCustomHealthCheck(Configuration)
|
||||
.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy",
|
||||
builder => builder.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials());
|
||||
});
|
||||
|
||||
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
|
||||
{
|
||||
@ -127,6 +130,12 @@ namespace Ordering.SignalrHub
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
app.UseAuthentication();
|
||||
@ -211,4 +220,32 @@ namespace Ordering.SignalrHub
|
||||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomExtensionMethods
|
||||
{
|
||||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "signalr-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "signalr-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
@ -20,9 +23,6 @@
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -16,7 +16,6 @@ namespace Payment.API
|
||||
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
|
@ -1,5 +1,7 @@
|
||||
using Autofac;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Azure.ServiceBus;
|
||||
@ -9,15 +11,13 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Payment.API.IntegrationEvents.EventHandling;
|
||||
using Payment.API.IntegrationEvents.Events;
|
||||
using RabbitMQ.Client;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace Payment.API
|
||||
{
|
||||
@ -32,7 +32,8 @@ namespace Payment.API
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public IServiceProvider ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
{
|
||||
services.AddCustomHealthCheck(Configuration);
|
||||
services.Configure<PaymentSettings>(Configuration);
|
||||
|
||||
RegisterAppInsights(services);
|
||||
@ -77,12 +78,7 @@ namespace Payment.API
|
||||
|
||||
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
|
||||
});
|
||||
}
|
||||
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")));
|
||||
});
|
||||
}
|
||||
|
||||
RegisterEventBus(services);
|
||||
|
||||
@ -103,6 +99,13 @@ namespace Payment.API
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
@ -174,4 +177,32 @@ namespace Payment.API
|
||||
eventBus.Subscribe<OrderStatusChangedToStockConfirmedIntegrationEvent, OrderStatusChangedToStockConfirmedIntegrationEventHandler>();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomExtensionMethods
|
||||
{
|
||||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var hcBuilder = services.AddHealthChecks();
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
hcBuilder
|
||||
.AddAzureServiceBusTopic(
|
||||
configuration["EventBusConnection"],
|
||||
topicName: "eshop_event_bus",
|
||||
name: "payment-servicebus-check",
|
||||
tags: new string[] { "servicebus" });
|
||||
}
|
||||
else
|
||||
{
|
||||
hcBuilder
|
||||
.AddRabbitMQ(
|
||||
$"amqp://{configuration["EventBusConnection"]}",
|
||||
name: "payment-rabbitmqbus-check",
|
||||
tags: new string[] { "rabbitmqbus" });
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseHealthChecks("/hc")
|
||||
.UseStartup<Startup>()
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
{
|
||||
|
@ -1,9 +1,11 @@
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -53,6 +55,12 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
loggerFactory.AddAzureWebAppDiagnostics();
|
||||
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
@ -129,21 +137,11 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
|
||||
public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
|
||||
checks.AddUrlCheck(configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
|
||||
checks.AddUrlCheck(configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
});
|
||||
|
||||
services.AddHealthChecks()
|
||||
.AddUrlGroup(new Uri(configuration["PurchaseUrlHC"]), name: "purchaseapigw-check", tags: new string[] { "purchaseapigw" })
|
||||
.AddUrlGroup(new Uri(configuration["MarketingUrlHC"]), name: "marketingapigw-check", tags: new string[] { "marketingapigw" })
|
||||
.AddUrlGroup(new Uri(configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" });
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,15 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="BuildBundlerMinifier" Version="2.6.375" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0-preview3-35497" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
@ -41,12 +45,6 @@
|
||||
<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.7.385" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="ViewModels\CampaignItem.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -16,7 +16,6 @@ namespace eShopConContainers.WebSPA
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>()
|
||||
.UseHealthChecks("/hc")
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
{
|
||||
|
@ -8,13 +8,14 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.IO;
|
||||
using WebSPA.Infrastructure;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
|
||||
namespace eShopConContainers.WebSPA
|
||||
{
|
||||
@ -42,21 +43,10 @@ namespace eShopConContainers.WebSPA
|
||||
{
|
||||
RegisterAppInsights(services);
|
||||
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
|
||||
checks.AddUrlCheck(Configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(Configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(Configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
|
||||
checks.AddUrlCheck(Configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(Configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
|
||||
});
|
||||
services.AddHealthChecks()
|
||||
.AddUrlGroup(new Uri(Configuration["PurchaseUrlHC"]), name: "purchaseapigw-check", tags: new string[] { "purchaseapigw" })
|
||||
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapigw-check", tags: new string[] { "marketingapigw" })
|
||||
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" });
|
||||
|
||||
services.Configure<AppSettings>(Configuration);
|
||||
|
||||
@ -97,6 +87,12 @@ namespace eShopConContainers.WebSPA
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
});
|
||||
|
||||
// Configure XSRF middleware, This pattern is for SPA style applications where XSRF token is added on Index page
|
||||
// load and passed back token on every subsequent async request
|
||||
// app.Use(async (context, next) =>
|
||||
|
@ -85,6 +85,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
@ -105,11 +107,6 @@
|
||||
</Target>
|
||||
-->
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="wwwroot\assets\" />
|
||||
</ItemGroup>
|
||||
|
@ -1,32 +1,17 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using System.Threading.Tasks;
|
||||
using WebStatus.Viewmodels;
|
||||
|
||||
namespace WebStatus.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
private readonly IHealthCheckService _healthCheckSvc;
|
||||
public HomeController(IHealthCheckService checkSvc)
|
||||
public HomeController()
|
||||
{
|
||||
_healthCheckSvc = checkSvc;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Index()
|
||||
public IActionResult Index()
|
||||
{
|
||||
var result = await _healthCheckSvc.CheckHealthAsync();
|
||||
|
||||
var data = new HealthStatusViewModel(result.CheckStatus);
|
||||
|
||||
foreach (var checkResult in result.Results)
|
||||
{
|
||||
data.AddResult(checkResult.Key, checkResult.Value);
|
||||
}
|
||||
|
||||
ViewBag.RefreshSeconds = 60;
|
||||
|
||||
return View(data);
|
||||
return Redirect("/hc-ui");
|
||||
}
|
||||
|
||||
public IActionResult Error()
|
||||
|
@ -1,18 +0,0 @@
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using System;
|
||||
|
||||
namespace WebStatus.Extensions
|
||||
{
|
||||
public static class HealthCheckBuilderExtensions
|
||||
{
|
||||
public static HealthCheckBuilder AddUrlCheckIfNotNull(this HealthCheckBuilder builder, string url, TimeSpan cacheDuration)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
builder.AddUrlCheck(url, cacheDuration);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,11 +16,7 @@ namespace WebStatus
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
{
|
||||
config.AddEnvironmentVariables();
|
||||
})
|
||||
.UseStartup<Startup>()
|
||||
.ConfigureLogging((hostingContext, builder) =>
|
||||
{
|
||||
builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
|
||||
|
@ -1,16 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using HealthChecks.UI.Client;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WebStatus.Extensions;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace WebStatus
|
||||
{
|
||||
@ -29,28 +26,9 @@ namespace WebStatus
|
||||
RegisterAppInsights(services);
|
||||
|
||||
services.AddOptions();
|
||||
|
||||
// Add framework services.
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
|
||||
checks.AddUrlCheckIfNotNull(Configuration["OrderingUrl"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheckIfNotNull(Configuration["OrderingBackgroundTasksUrl"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheckIfNotNull(Configuration["BasketUrl"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
|
||||
checks.AddUrlCheckIfNotNull(Configuration["CatalogUrl"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheckIfNotNull(Configuration["IdentityUrl"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheckIfNotNull(Configuration["LocationsUrl"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheckIfNotNull(Configuration["MarketingUrl"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheckIfNotNull(Configuration["PaymentUrl"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheckIfNotNull(Configuration["mvc"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
|
||||
checks.AddUrlCheckIfNotNull(Configuration["spa"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
|
||||
});
|
||||
|
||||
services.AddHealthChecks();
|
||||
services.AddHealthChecksUI();
|
||||
|
||||
services.AddMvc()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
||||
}
|
||||
@ -82,6 +60,8 @@ namespace WebStatus
|
||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
|
||||
app.UseHealthChecksUI(config => config.UIPath = "/hc-ui");
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
@ -1,23 +0,0 @@
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace WebStatus.Viewmodels
|
||||
{
|
||||
public class HealthStatusViewModel
|
||||
{
|
||||
private readonly CheckStatus _overall;
|
||||
|
||||
private readonly Dictionary<string, IHealthCheckResult> _results;
|
||||
|
||||
public CheckStatus OverallStatus => _overall;
|
||||
|
||||
public IEnumerable<NamedCheckResult> Results => _results.Select(kvp => new NamedCheckResult(kvp.Key, kvp.Value));
|
||||
|
||||
private HealthStatusViewModel() => _results = new Dictionary<string, IHealthCheckResult>();
|
||||
|
||||
public HealthStatusViewModel(CheckStatus overall) : this() => _overall = overall;
|
||||
|
||||
public void AddResult(string name, IHealthCheckResult result) => _results.Add(name, result);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
|
||||
namespace WebStatus.Viewmodels
|
||||
{
|
||||
public class NamedCheckResult
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public IHealthCheckResult Result { get; }
|
||||
|
||||
public NamedCheckResult(string name, IHealthCheckResult result)
|
||||
{
|
||||
Name = name;
|
||||
Result = result;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
@using Microsoft.AspNetCore.Html
|
||||
@using Microsoft.Extensions.HealthChecks
|
||||
@model WebStatus.Viewmodels.HealthStatusViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "System Status";
|
||||
|
||||
}
|
||||
|
||||
@functions
|
||||
{
|
||||
static readonly string[] LabelClass = new[] { "default", "danger", "success", "warning" };
|
||||
|
||||
public HtmlString StatusLabel(CheckStatus status)
|
||||
{
|
||||
return new HtmlString($@"<span class=""label label-{LabelClass[(int) status]}"">{status}</span>");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<style>.label {font-size: 100%}</style>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2 class="overall-status-title">Overall Status: @StatusLabel(Model.OverallStatus)</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-group-status">
|
||||
@foreach (var result in Model.Results)
|
||||
{
|
||||
<div class="row list-group-status-item">
|
||||
<div class="col-md-9">
|
||||
<h4 class="list-group-status-item-title">@result.Name</h4>
|
||||
<p class="list-group-item-text">
|
||||
@if (result.Result.Data.ContainsKey("url"))
|
||||
{
|
||||
<p>@result.Result.Data["url"]</p>
|
||||
}
|
||||
<p class="text-@(LabelClass[(int)result.Result.CheckStatus])" style="font-weight:bold">
|
||||
@result.Result.Description
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h3>@StatusLabel(result.Result.CheckStatus)</h3>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
@ -1,14 +0,0 @@
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
}
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
|
||||
</p>
|
@ -1,60 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - WebStatus</title>
|
||||
|
||||
<environment names="Development">
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" />
|
||||
</environment>
|
||||
<environment names="Staging,Production">
|
||||
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/4.1.1/css/bootstrap.min.css"
|
||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
|
||||
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
|
||||
</environment>
|
||||
|
||||
@if (ViewBag.RefreshSeconds != null && ViewBag.RefreshSeconds > 0)
|
||||
{
|
||||
<meta http-equiv="refresh" content="@ViewBag.RefreshSeconds">
|
||||
}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-dark bg-dark fixed-top">
|
||||
<a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">
|
||||
 <b>eShopOnContainers</b> WebStatus
|
||||
</a>
|
||||
</nav>
|
||||
<br />
|
||||
<div class="container body-content">
|
||||
@RenderBody()
|
||||
</div>
|
||||
<br />
|
||||
<div id="footer">
|
||||
<p> © 2017 - WebStatus</p>
|
||||
</div>
|
||||
|
||||
|
||||
<environment names="Development">
|
||||
<script src="~/lib/jquery/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
|
||||
</environment>
|
||||
<environment names="Staging,Production">
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
|
||||
asp-fallback-src="~/lib/jquery/jquery.min.js"
|
||||
asp-fallback-test="window.jQuery"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
|
||||
</script>
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/4.1.1/bootstrap.min.js"
|
||||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
|
||||
</script>
|
||||
</environment>
|
||||
</body>
|
||||
</html>
|
@ -1,2 +0,0 @@
|
||||
@using WebStatus
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
@ -1,3 +0,0 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
@ -5,6 +5,9 @@
|
||||
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
@ -13,9 +16,4 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,21 +1,84 @@
|
||||
{
|
||||
"Logging": {
|
||||
"IncludeScopes": false,
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
},
|
||||
"OrderingUrl": "http://localhost:5102/hc",
|
||||
"OrderingBackgroundTasksUrl": "http://localhost:5111/hc",
|
||||
"BasketUrl": "http://localhost:5103/hc",
|
||||
"CatalogUrl": "http://localhost:5101/hc",
|
||||
"IdentityUrl": "http://localhost:5105/hc",
|
||||
"MarketingUrl": "http://localhost:5110/hc",
|
||||
"LocationsUrl": "http://localhost:5109/hc",
|
||||
"PaymentUrl": "http://localhost:5108/hc",
|
||||
"ApplicationInsights": {
|
||||
"InstrumentationKey": ""
|
||||
"HealthChecks-UI": {
|
||||
"HealthChecks": [
|
||||
{
|
||||
"Name": "Ordering HTTP Check",
|
||||
"Uri": "http://localhost:5102/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Ordering HTTP Background Check",
|
||||
"Uri": "http://localhost:5111/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Basket HTTP Check",
|
||||
"Uri": "http://localhost:5103/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Catalog HTTP Check",
|
||||
"Uri": "http://localhost:5101/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Identity HTTP Check",
|
||||
"Uri": "http://localhost:5105/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Marketing HTTP Check",
|
||||
"Uri": "http://localhost:5110/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Locations HTTP Check",
|
||||
"Uri": "http://localhost:5109/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Payments HTTP Check",
|
||||
"Uri": "http://localhost:5108/hc"
|
||||
},
|
||||
{
|
||||
"Name": "WebMVC HTTP Check",
|
||||
"Uri": "http://localhost:5100/hc"
|
||||
},
|
||||
{
|
||||
"Name": "WebSPA HTTP Check",
|
||||
"Uri": "http://localhost:5104/hc"
|
||||
},
|
||||
{
|
||||
"Name": "SignalR HTTP Check",
|
||||
"Uri": "http://localhost:5112/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Mobile Shopping API GW HTTP Check",
|
||||
"Uri": "http://localhost:5200/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Mobile Marketing API GW HTTP Check",
|
||||
"Uri": "http://localhost:5201/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Web Shopping API GW HTTP Check",
|
||||
"Uri": "http://localhost:5202/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Web Marketing API GW HTTP Check",
|
||||
"Uri": "http://localhost:5203/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Mobile Shopping Aggregator HTTP Check",
|
||||
"Uri": "http://localhost:5120/hc"
|
||||
},
|
||||
{
|
||||
"Name": "Web Shopping Aggregator HTTP Check",
|
||||
"Uri": "http://localhost:5121/hc"
|
||||
}
|
||||
],
|
||||
"Webhooks": [
|
||||
{
|
||||
"Name": "",
|
||||
"Uri": "",
|
||||
"Payload": "",
|
||||
"RestoredPayload": ""
|
||||
}
|
||||
],
|
||||
"EvaluationTimeOnSeconds": 10,
|
||||
"MinimumSecondsBetweenFailureNotifications": 60
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user