Browse Source

Updated healthcheck lib

pull/223/head
Eduard Tomas 7 years ago
parent
commit
22cc8daa65
31 changed files with 670 additions and 430 deletions
  1. +103
    -103
      eShopOnContainers-ServicesAndWebApps.sln
  2. +15
    -7
      src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/HealthCheckMiddleware.cs
  3. +11
    -4
      src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/HealthCheckStartupFilter.cs
  4. +16
    -5
      src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/HealthCheckWebHostBuilderExtension.cs
  5. +2
    -2
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/HealthCheckBuilderSqlServerExtensions.cs
  6. +0
    -0
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj
  7. +109
    -0
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/CachedHealthCheck.cs
  8. +19
    -0
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/CachedHealthCheckExtensions.cs
  9. +30
    -24
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Checks/AddCheck.cs
  10. +5
    -5
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Checks/NumericChecks.cs
  11. +1
    -64
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Checks/UrlChecks.cs
  12. +11
    -8
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/CompositeHealthCheckResult.cs
  13. +15
    -49
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheck.cs
  14. +102
    -7
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckBuilder.cs
  15. +0
    -18
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckExtensions.cs
  16. +37
    -0
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckGroup.cs
  17. +0
    -1
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckResult.cs
  18. +91
    -26
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckService.cs
  19. +13
    -5
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckServiceCollectionExtensions.cs
  20. +0
    -38
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckServiceExtensions.cs
  21. +1
    -4
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/IHealthCheck.cs
  22. +46
    -1
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/IHealthCheckService.cs
  23. +18
    -42
      src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Internal/UrlChecker.cs
  24. +22
    -10
      src/BuildingBlocks/HealthChecks/src/common/Guard.cs
  25. +0
    -1
      src/Services/Basket/Basket.API/Basket.API.csproj
  26. +1
    -1
      src/Services/Catalog/Catalog.API/Catalog.API.csproj
  27. +1
    -1
      src/Services/Identity/Identity.API/Identity.API.csproj
  28. +1
    -1
      src/Services/Ordering/Ordering.API/Ordering.API.csproj
  29. +0
    -1
      src/Web/WebMVC/WebMVC.csproj
  30. +0
    -1
      src/Web/WebSPA/WebSPA.csproj
  31. +0
    -1
      src/Web/WebStatus/WebStatus.csproj

+ 103
- 103
eShopOnContainers-ServicesAndWebApps.sln View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.12
VisualStudioVersion = 15.0.26403.7
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}"
EndProject
@ -62,18 +62,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationEventLogEF", "sr
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HealthChecks", "HealthChecks", "{A81ECBC2-6B00-4DCD-8388-469174033379}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HealthChecks", "src\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj", "{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}"
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}") = "Microsoft.Extensions.HealthChecks.Data", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj", "{7804FC60-23E6-490C-8E08-F9FEF829F184}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebStatus", "src\Web\WebStatus\WebStatus.csproj", "{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Resilience", "Resilience", "{FBF43D93-F2E7-4FF8-B4AB-186895949B88}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Resilience.Http", "src\BuildingBlocks\Resilience\Resilience.Http\Resilience.Http.csproj", "{D1C47FF1-91F1-4CAF-9ABB-AD642B821502}"
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@ -712,54 +712,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
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|ARM.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhone.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x64.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x64.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x86.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.AppStore|x86.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|ARM.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhone.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x64.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x64.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x86.ActiveCfg = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Debug|x86.Build.0 = Debug|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|Any CPU.Build.0 = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|ARM.ActiveCfg = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|ARM.Build.0 = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhone.ActiveCfg = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhone.Build.0 = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|x64.ActiveCfg = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|x64.Build.0 = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.Release|x86.ActiveCfg = Release|Any CPU
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E}.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
@ -808,54 +760,6 @@ Global
{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
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|ARM.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhone.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x64.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x64.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x86.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.AppStore|x86.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|ARM.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhone.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x64.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x64.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x86.ActiveCfg = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Debug|x86.Build.0 = Debug|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|Any CPU.Build.0 = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|ARM.ActiveCfg = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|ARM.Build.0 = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhone.ActiveCfg = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhone.Build.0 = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|x64.ActiveCfg = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|x64.Build.0 = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.Release|x86.ActiveCfg = Release|Any CPU
{7804FC60-23E6-490C-8E08-F9FEF829F184}.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
@ -952,6 +856,102 @@ Global
{D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x64.Build.0 = Release|Any CPU
{D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.Release|x86.ActiveCfg = Release|Any CPU
{D1C47FF1-91F1-4CAF-9ABB-AD642B821502}.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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -981,11 +981,11 @@ Global
{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}
{DF8367F8-E6BD-4D07-99D2-E416BF8AB01E} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{942ED6E8-0050-495F-A0EA-01E97F63760C} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{7804FC60-23E6-490C-8E08-F9FEF829F184} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
{FBF43D93-F2E7-4FF8-B4AB-186895949B88} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
{D1C47FF1-91F1-4CAF-9ABB-AD642B821502} = {FBF43D93-F2E7-4FF8-B4AB-186895949B88}
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379}
EndGlobalSection
EndGlobal

+ 15
- 7
src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/HealthCheckMiddleware.cs View File

@ -1,6 +1,8 @@
// 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;
@ -11,30 +13,34 @@ namespace Microsoft.AspNetCore.HealthChecks
{
public class HealthCheckMiddleware
{
private RequestDelegate _next;
private string _path;
private int? _port;
private IHealthCheckService _service;
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)
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)
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 result = await _service.CheckHealthAsync();
var timeoutTokenSource = new CancellationTokenSource(_timeout);
var result = await _service.CheckHealthAsync(timeoutTokenSource.Token);
var status = result.CheckStatus;
if (status != CheckStatus.Healthy)
@ -60,7 +66,9 @@ namespace Microsoft.AspNetCore.HealthChecks
}
if (context.Request.Path == _path)
{
return true;
}
return false;
}


+ 11
- 4
src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/HealthCheckStartupFilter.cs View File

@ -11,15 +11,18 @@ namespace Microsoft.AspNetCore.HealthChecks
{
private string _path;
private int? _port;
private TimeSpan _timeout;
public HealthCheckStartupFilter(int port)
public HealthCheckStartupFilter(int port, TimeSpan timeout)
{
_port = port;
_timeout = timeout;
}
public HealthCheckStartupFilter(string path)
public HealthCheckStartupFilter(string path, TimeSpan timeout)
{
_path = path;
_timeout = timeout;
}
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
@ -27,9 +30,13 @@ namespace Microsoft.AspNetCore.HealthChecks
return app =>
{
if (_port.HasValue)
app.UseMiddleware<HealthCheckMiddleware>(_port);
{
app.UseMiddleware<HealthCheckMiddleware>(_port, _timeout);
}
else
app.UseMiddleware<HealthCheckMiddleware>(_path);
{
app.UseMiddleware<HealthCheckMiddleware>(_path, _timeout);
}
next(app);
};


+ 16
- 5
src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/HealthCheckWebHostBuilderExtension.cs View File

@ -1,6 +1,7 @@
// 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;
@ -8,28 +9,38 @@ 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(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));
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(!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)));
builder.ConfigureServices(services => services.AddSingleton<IStartupFilter>(new HealthCheckStartupFilter(path, timeout)));
return builder;
}
}


src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.Data/HealthCheckBuilderDataExtensions.cs → src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/HealthCheckBuilderSqlServerExtensions.cs View File

@ -7,7 +7,7 @@ using System.Data.SqlClient;
namespace Microsoft.Extensions.HealthChecks
{
public static class HealthCheckBuilderDataExtensions
public static class HealthCheckBuilderSqlServerExtensions
{
public static HealthCheckBuilder AddSqlCheck(this HealthCheckBuilder builder, string name, string connectionString)
{
@ -33,7 +33,7 @@ namespace Microsoft.Extensions.HealthChecks
}
}
}
catch(Exception ex)
catch (Exception ex)
{
return HealthCheckResult.Unhealthy($"SqlCheck({name}): Exception during check: {ex.GetType().FullName}");
}

src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.Data/Microsoft.Extensions.HealthChecks.Data.csproj → src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj View File


+ 109
- 0
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/CachedHealthCheck.cs View File

@ -0,0 +1,109 @@
// 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);
}
}
}

+ 19
- 0
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/CachedHealthCheckExtensions.cs View File

@ -0,0 +1,19 @@
// 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);
}
}
}

+ 30
- 24
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Checks/AddCheck.cs View File

@ -15,96 +15,102 @@ namespace Microsoft.Extensions.HealthChecks
{
Guard.ArgumentNotNull(nameof(builder), builder);
builder.AddCheck(name, HealthCheck.FromCheck(check, builder.DefaultCacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromCheck(check, builder.DefaultCacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromCheck(check, cacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromCheck(check, cacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, builder.DefaultCacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, builder.DefaultCacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, cacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromTaskCheck(check, cacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, builder.DefaultCacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, builder.DefaultCacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, cacheDuration));
return 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);
builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check, cacheDuration));
return 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);
}
}
}

+ 5
- 5
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Checks/NumericChecks.cs View File

@ -14,7 +14,7 @@ namespace Microsoft.Extensions.HealthChecks
where T : IComparable<T>
{
Guard.ArgumentNotNull(nameof(builder), builder);
Guard.ArgumentNotNullOrWhitespace(nameof(name), name);
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
builder.AddCheck(name, () =>
@ -23,7 +23,7 @@ namespace Microsoft.Extensions.HealthChecks
var status = currentValue.CompareTo(minValue) >= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
return HealthCheckResult.FromStatus(
status,
$"{name}: min={minValue}, current={currentValue}",
$"min={minValue}, current={currentValue}",
new Dictionary<string, object> { { "min", minValue }, { "current", currentValue } }
);
});
@ -35,16 +35,16 @@ namespace Microsoft.Extensions.HealthChecks
where T : IComparable<T>
{
Guard.ArgumentNotNull(nameof(builder), builder);
Guard.ArgumentNotNullOrWhitespace(nameof(name), name);
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
builder.AddCheck($"{name}", () =>
builder.AddCheck(name, () =>
{
var currentValue = currentValueFunc();
var status = currentValue.CompareTo(maxValue) <= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
return HealthCheckResult.FromStatus(
status,
$"{name}: max={maxValue}, current={currentValue}",
$"max={maxValue}, current={currentValue}",
new Dictionary<string, object> { { "max", maxValue }, { "current", currentValue } }
);
});


+ 1
- 64
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Checks/UrlChecks.cs View File

@ -2,8 +2,6 @@
// 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.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.HealthChecks.Internal;
@ -37,73 +35,12 @@ namespace Microsoft.Extensions.HealthChecks
Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
{
Guard.ArgumentNotNull(nameof(builder), builder);
Guard.ArgumentNotNullOrWhitespace(nameof(url), url);
Guard.ArgumentNotNullOrEmpty(nameof(url), url);
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
var urlCheck = new UrlChecker(checkFunc, url);
builder.AddCheck($"UrlCheck({url})", () => urlCheck.CheckAsync());
return builder;
}
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName)
=> AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => UrlChecker.DefaultUrlCheck(response));
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
Func<HttpResponseMessage, IHealthCheckResult> checkFunc)
{
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
return AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
}
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc)
{
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
return AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
}
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
{
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
return AddUrlChecks(builder, urlItems, groupName, CheckStatus.Warning, response => checkFunc(response));
}
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
CheckStatus partialSuccessStatus)
=> AddUrlChecks(builder, urlItems, groupName, partialSuccessStatus, response => UrlChecker.DefaultUrlCheck(response));
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
CheckStatus partialSuccessStatus, Func<HttpResponseMessage, IHealthCheckResult> checkFunc)
{
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
return AddUrlChecks(builder, urlItems, groupName, partialSuccessStatus, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
}
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
CheckStatus partialSuccessStatus, Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc)
{
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
return AddUrlChecks(builder, urlItems, groupName, partialSuccessStatus, response => new ValueTask<IHealthCheckResult>(checkFunc(response)));
}
public static HealthCheckBuilder AddUrlChecks(this HealthCheckBuilder builder, IEnumerable<string> urlItems, string groupName,
CheckStatus partialSuccessStatus, Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
{
var urls = urlItems?.ToArray();
Guard.ArgumentNotNull(nameof(builder), builder);
Guard.ArgumentNotNullOrEmpty(nameof(urlItems), urls);
Guard.ArgumentNotNullOrWhitespace(nameof(groupName), groupName);
var urlChecker = new UrlChecker(checkFunc, urls) { PartiallyHealthyStatus = partialSuccessStatus };
builder.AddCheck($"UrlChecks({groupName})", () => urlChecker.CheckAsync());
return builder;
}
}
}

+ 11
- 8
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/CompositeHealthCheckResult.cs View File

@ -7,7 +7,6 @@ using System.Linq;
namespace Microsoft.Extensions.HealthChecks
{
// REVIEW: Does this need to be thread safe?
/// <summary>
/// Represents a composite health check result built from several results.
/// </summary>
@ -31,17 +30,23 @@ namespace Microsoft.Extensions.HealthChecks
{
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.Value.Description));
public string Description => string.Join(Environment.NewLine, _results.Select(r => $"{r.Key}: {r.Value.Description}"));
public IReadOnlyDictionary<string, object> Data
{
@ -58,23 +63,21 @@ namespace Microsoft.Extensions.HealthChecks
public IReadOnlyDictionary<string, IHealthCheckResult> Results => _results;
// REVIEW: Should description be required? Seems redundant for success checks.
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.ArgumentNotNullOrWhitespace(nameof(name), name);
Guard.ArgumentValid(status != CheckStatus.Unknown, nameof(status), "Cannot add unknown status to composite health check result");
Guard.ArgumentNotNullOrWhitespace(nameof(description), description);
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.ArgumentNotNullOrWhitespace(nameof(name), name);
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
Guard.ArgumentNotNull(nameof(checkResult), checkResult);
_results.Add(name, checkResult);


+ 15
- 49
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheck.cs View File

@ -9,68 +9,34 @@ namespace Microsoft.Extensions.HealthChecks
{
public class HealthCheck : IHealthCheck
{
private DateTimeOffset _cacheExpiration;
private IHealthCheckResult _cachedResult;
private volatile int _writerCount;
protected HealthCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
protected HealthCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
{
Guard.ArgumentNotNull(nameof(check), check);
Guard.ArgumentValid(cacheDuration >= TimeSpan.Zero, nameof(cacheDuration), "Cache duration must either be zero (disabled) or a positive value");
Check = check;
CacheDuration = cacheDuration;
}
public TimeSpan CacheDuration { get; }
protected Func<CancellationToken, ValueTask<IHealthCheckResult>> Check { get; }
protected virtual DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
public async ValueTask<IHealthCheckResult> CheckAsync(CancellationToken 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
{
_cachedResult = await Check(cancellationToken).ConfigureAwait(false);
_cacheExpiration = UtcNow + CacheDuration;
break;
}
finally
{
_writerCount = 0;
}
}
return _cachedResult;
}
public ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken))
=> Check(cancellationToken);
public static HealthCheck FromCheck(Func<IHealthCheckResult> check, TimeSpan cacheDuration)
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()), cacheDuration);
public static HealthCheck FromCheck(Func<IHealthCheckResult> check)
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()));
public static HealthCheck FromCheck(Func<CancellationToken, IHealthCheckResult> check, TimeSpan cacheDuration)
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)), cacheDuration);
public static HealthCheck FromCheck(Func<CancellationToken, IHealthCheckResult> check)
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)));
public static HealthCheck FromTaskCheck(Func<Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()), cacheDuration);
public static HealthCheck FromTaskCheck(Func<Task<IHealthCheckResult>> check)
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()));
public static HealthCheck FromTaskCheck(Func<CancellationToken, Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)), cacheDuration);
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, TimeSpan cacheDuration)
=> new HealthCheck(token => check(), cacheDuration);
public static HealthCheck FromValueTaskCheck(Func<ValueTask<IHealthCheckResult>> check)
=> new HealthCheck(token => check());
public static HealthCheck FromValueTaskCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
=> new HealthCheck(check, cacheDuration);
public static HealthCheck FromValueTaskCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
=> new HealthCheck(check);
}
}

+ 102
- 7
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckBuilder.cs View File

@ -8,33 +8,128 @@ namespace Microsoft.Extensions.HealthChecks
{
public class HealthCheckBuilder
{
private readonly Dictionary<string, IHealthCheck> _checks;
private readonly Dictionary<string, CachedHealthCheck> _checksByName;
private readonly HealthCheckGroup _currentGroup;
private readonly Dictionary<string, HealthCheckGroup> _groups;
public HealthCheckBuilder()
{
_checks = new Dictionary<string, IHealthCheck>(StringComparer.OrdinalIgnoreCase);
_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);
}
public IReadOnlyDictionary<string, IHealthCheck> Checks => _checks;
/// <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; }
public HealthCheckBuilder AddCheck(string name, IHealthCheck check)
/// <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.ArgumentNotNullOrWhitespace(nameof(name), name);
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);
_checks.Add(name, check);
return this;
}
public HealthCheckBuilder WithDefaultCacheDuration(TimeSpan duration)
{
Guard.ArgumentValid(duration >= TimeSpan.Zero, nameof(duration), "Duration must be zero (disabled) or a positive 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;
}
}
}

+ 0
- 18
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckExtensions.cs View File

@ -1,18 +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 static class HealthCheckExtensions
{
public static ValueTask<IHealthCheckResult> CheckAsync(this IHealthCheck healthCheck)
{
Guard.ArgumentNotNull(nameof(healthCheck), healthCheck);
return healthCheck.CheckAsync(CancellationToken.None);
}
}
}

+ 37
- 0
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckGroup.cs View File

@ -0,0 +1,37 @@
// 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;
}
}
}
}

+ 0
- 1
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckResult.cs View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Extensions.HealthChecks
{


+ 91
- 26
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckService.cs View File

@ -3,52 +3,117 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.Extensions.HealthChecks
{
public class HealthCheckService : IHealthCheckService
{
public IReadOnlyDictionary<string, IHealthCheck> _checks;
private readonly HealthCheckBuilder _builder;
private readonly IReadOnlyList<HealthCheckGroup> _groups;
private readonly HealthCheckGroup _root;
private readonly IServiceProvider _serviceProvider;
private readonly IServiceScopeFactory _serviceScopeFactory;
private ILogger<HealthCheckService> _logger;
public HealthCheckService(HealthCheckBuilder builder, ILogger<HealthCheckService> logger)
public HealthCheckService(HealthCheckBuilder builder, IServiceProvider serviceProvider, IServiceScopeFactory serviceScopeFactory)
{
_checks = builder.Checks;
_logger = logger;
_builder = builder;
_groups = GetGroups().Where(group => group.GroupName != string.Empty).ToList();
_root = GetGroup(string.Empty);
_serviceProvider = serviceProvider;
_serviceScopeFactory = serviceScopeFactory;
}
public async Task<CompositeHealthCheckResult> CheckHealthAsync(CheckStatus partiallyHealthyStatus, CancellationToken cancellationToken)
public async Task<CompositeHealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken))
{
var logMessage = new StringBuilder();
var result = new CompositeHealthCheckResult(partiallyHealthyStatus);
foreach (var check in _checks)
using (var scope = GetServiceScope())
{
try
{
var healthCheckResult = await check.Value.CheckAsync().ConfigureAwait(false);
logMessage.AppendLine($"HealthCheck: {check.Key} : {healthCheckResult.CheckStatus}");
result.Add(check.Key, healthCheckResult);
}
catch (Exception ex)
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)
{
logMessage.AppendLine($"HealthCheck: {check.Key} : Exception {ex.GetType().FullName} thrown");
result.Add(check.Key, CheckStatus.Unhealthy, $"Exception during check: {ex.GetType().FullName}");
result.Add($"Group({groupTask.Group.GroupName})", groupTask.Task.Result);
}
return result;
}
}
public IReadOnlyList<CachedHealthCheck> GetAllChecks()
=> _builder.ChecksByName.Values.ToList().AsReadOnly();
if (logMessage.Length == 0)
logMessage.AppendLine("HealthCheck: No checks have been registered");
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);
}
_logger.Log((result.CheckStatus == CheckStatus.Healthy ? LogLevel.Information : LogLevel.Error), 0, logMessage.ToString(), null, MessageFormatter);
return result;
}
private static string MessageFormatter(string state, Exception error) => state;
private class UnscopedServiceProvider : IServiceScope
{
public UnscopedServiceProvider(IServiceProvider serviceProvider)
=> ServiceProvider = serviceProvider;
public IServiceProvider ServiceProvider { get; }
public void Dispose() { }
}
}
}

+ 13
- 5
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckServiceCollectionExtensions.cs View File

@ -2,20 +2,28 @@
// 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
{
public static IServiceCollection AddHealthChecks(this IServiceCollection services, Action<HealthCheckBuilder> checkupAction)
private static readonly Type HealthCheckServiceInterface = typeof(IHealthCheckService);
public static IServiceCollection AddHealthChecks(this IServiceCollection services, Action<HealthCheckBuilder> checks)
{
var checkupBuilder = new HealthCheckBuilder();
Guard.OperationValid(!services.Any(descriptor => descriptor.ServiceType == HealthCheckServiceInterface), "AddHealthChecks may only be called once.");
var builder = new HealthCheckBuilder();
checkupAction.Invoke(checkupBuilder);
services.AddSingleton<IHealthCheckService, HealthCheckService>(serviceProvider =>
{
var serviceScopeFactory = serviceProvider.GetService<IServiceScopeFactory>();
return new HealthCheckService(builder, serviceProvider, serviceScopeFactory);
});
services.AddSingleton(checkupBuilder);
services.AddSingleton<IHealthCheckService, HealthCheckService>();
checks(builder);
return services;
}
}


+ 0
- 38
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/HealthCheckServiceExtensions.cs View File

@ -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.Threading;
using System.Threading.Tasks;
namespace Microsoft.Extensions.HealthChecks
{
public static class HealthCheckServiceExtensions
{
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service)
{
Guard.ArgumentNotNull(nameof(service), service);
return service.CheckHealthAsync(CheckStatus.Unhealthy, CancellationToken.None);
}
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service, CheckStatus partiallyHealthyStatus)
{
Guard.ArgumentNotNull(nameof(service), service);
return service.CheckHealthAsync(partiallyHealthyStatus, CancellationToken.None);
}
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service, CancellationToken cancellationToken)
{
Guard.ArgumentNotNull(nameof(service), service);
return service.CheckHealthAsync(CheckStatus.Unhealthy, cancellationToken);
}
public static Task<CompositeHealthCheckResult> CheckHealthAsync(this IHealthCheckService service, CheckStatus partiallyHealthyStatus, CancellationToken cancellationToken)
{
Guard.ArgumentNotNull(nameof(service), service);
return service.CheckHealthAsync(partiallyHealthyStatus, cancellationToken);
}
}
}

+ 1
- 4
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/IHealthCheck.cs View File

@ -1,7 +1,6 @@
// 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;
@ -9,8 +8,6 @@ namespace Microsoft.Extensions.HealthChecks
{
public interface IHealthCheck
{
TimeSpan CacheDuration { get; }
ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken);
ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken));
}
}

+ 46
- 1
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/IHealthCheckService.cs View File

@ -1,6 +1,8 @@
// 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;
@ -8,6 +10,49 @@ namespace Microsoft.Extensions.HealthChecks
{
public interface IHealthCheckService
{
Task<CompositeHealthCheckResult> CheckHealthAsync(CheckStatus partiallyHealthyStatus, CancellationToken cancellationToken);
/// <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));
}
}

+ 18
- 42
src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Internal/UrlChecker.cs View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
@ -13,55 +12,33 @@ namespace Microsoft.Extensions.HealthChecks.Internal
public class UrlChecker
{
private readonly Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> _checkFunc;
private readonly string[] _urls;
private readonly string _url;
// REVIEW: Cache timeout here?
public UrlChecker(Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc, params string[] urls)
public UrlChecker(Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc, string url)
{
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
Guard.ArgumentNotNullOrEmpty(nameof(urls), urls);
Guard.ArgumentNotNullOrEmpty(nameof(url), url);
_checkFunc = checkFunc;
_urls = urls;
_url = url;
}
public CheckStatus PartiallyHealthyStatus { get; set; } = CheckStatus.Warning;
public Task<IHealthCheckResult> CheckAsync()
=> _urls.Length == 1 ? CheckSingleAsync() : CheckMultiAsync();
public async Task<IHealthCheckResult> CheckSingleAsync()
{
var httpClient = CreateHttpClient();
var result = default(IHealthCheckResult);
await CheckUrlAsync(httpClient, _urls[0], (_, checkResult) => result = checkResult).ConfigureAwait(false);
return result;
}
public async Task<IHealthCheckResult> CheckMultiAsync()
public async Task<IHealthCheckResult> CheckAsync()
{
var composite = new CompositeHealthCheckResult(PartiallyHealthyStatus);
var httpClient = CreateHttpClient();
// REVIEW: Should these be done in parallel?
foreach (var url in _urls)
await CheckUrlAsync(httpClient, url, (name, checkResult) => composite.Add(name, checkResult)).ConfigureAwait(false);
return composite;
}
private async Task CheckUrlAsync(HttpClient httpClient, string url, Action<string, IHealthCheckResult> adder)
{
var name = $"UrlCheck({url})";
try
{
var response = await httpClient.GetAsync(url).ConfigureAwait(false);
var result = await _checkFunc(response);
adder(name, result);
}
catch (Exception ex)
using (var httpClient = CreateHttpClient())
{
adder(name, HealthCheckResult.Unhealthy($"Exception during check: {ex.GetType().FullName}"));
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);
}
}
}
@ -74,8 +51,7 @@ namespace Microsoft.Extensions.HealthChecks.Internal
public static async ValueTask<IHealthCheckResult> DefaultUrlCheck(HttpResponseMessage response)
{
// REVIEW: Should this be an explicit 200 check, or just an "is success" check?
var status = response.StatusCode == HttpStatusCode.OK ? CheckStatus.Healthy : CheckStatus.Unhealthy;
var status = response.IsSuccessStatusCode ? CheckStatus.Healthy : CheckStatus.Unhealthy;
var data = new Dictionary<string, object>
{
{ "url", response.RequestMessage.RequestUri.ToString() },
@ -83,7 +59,7 @@ namespace Microsoft.Extensions.HealthChecks.Internal
{ "reason", response.ReasonPhrase },
{ "body", await response.Content?.ReadAsStringAsync() }
};
return HealthCheckResult.FromStatus(status, $"UrlCheck({response.RequestMessage.RequestUri}): status code {response.StatusCode} ({(int)response.StatusCode})", data);
return HealthCheckResult.FromStatus(status, $"status code {response.StatusCode} ({(int)response.StatusCode})", data);
}
protected virtual HttpClient GetHttpClient()


+ 22
- 10
src/BuildingBlocks/HealthChecks/src/common/Guard.cs View File

@ -9,37 +9,49 @@ static class Guard
public static void ArgumentNotNull(string argumentName, object value)
{
if (value == null)
{
throw new ArgumentNullException(argumentName);
}
}
public static void ArgumentNotNullOrEmpty<T>(string argumentName, string value)
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);
{
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);
{
throw new ArgumentException("Collection must contain at least one item.", argumentName);
}
}
public static void ArgumentNotNullOrWhitespace(string argumentName, string value)
public static void ArgumentValid(bool valid, string argumentName, string exceptionMessage)
{
if (value == null)
throw new ArgumentNullException(argumentName);
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Value must contain a non-whitespace value", argumentName);
if (!valid)
{
throw new ArgumentException(exceptionMessage, argumentName);
}
}
public static void ArgumentValid(bool valid, string argumentName, string exceptionMessage)
public static void OperationValid(bool valid, string exceptionMessage)
{
if (!valid)
throw new ArgumentException(exceptionMessage, argumentName);
{
throw new InvalidOperationException(exceptionMessage);
}
}
}

+ 0
- 1
src/Services/Basket/Basket.API/Basket.API.csproj View File

@ -43,7 +43,6 @@
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.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.Data\Microsoft.Extensions.HealthChecks.Data.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup>


+ 1
- 1
src/Services/Catalog/Catalog.API/Catalog.API.csproj View File

@ -59,7 +59,7 @@
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.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.Data\Microsoft.Extensions.HealthChecks.Data.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" />
</ItemGroup>


+ 1
- 1
src/Services/Identity/Identity.API/Identity.API.csproj View File

@ -63,7 +63,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.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>


+ 1
- 1
src/Services/Ordering/Ordering.API/Ordering.API.csproj View File

@ -27,7 +27,7 @@
<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.Data\Microsoft.Extensions.HealthChecks.Data.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="..\Ordering.Domain\Ordering.Domain.csproj" />
<ProjectReference Include="..\Ordering.Infrastructure\Ordering.Infrastructure.csproj" />


+ 0
- 1
src/Web/WebMVC/WebMVC.csproj View File

@ -59,7 +59,6 @@
<ItemGroup>
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\Resilience\Resilience.Http\Resilience.Http.csproj" />
</ItemGroup>


+ 0
- 1
src/Web/WebSPA/WebSPA.csproj View File

@ -74,7 +74,6 @@
<ItemGroup>
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup>


+ 0
- 1
src/Web/WebStatus/WebStatus.csproj View File

@ -21,7 +21,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.Data\Microsoft.Extensions.HealthChecks.Data.csproj" />
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
</ItemGroup>


Loading…
Cancel
Save