Skip to main content

2 posts tagged with "Health Checks"

Application health monitoring

View All Tags

How to Setup ASP.NET Core Health Check UI

· 2 min read
Mark Burton
Software Engineer & Technical Writer

In Part one we setup the health check endpoints, now to add a frontend.

The Health Checks UI is best hosted in its own service as it can consolidate health checks for a number of services.

Swagger CORS error

Adding the HealthChecks UI to the service involves adding 2 nuget packages, the main AspNetCore.HealthChecks.UI package and a storage provider, initially I have used the InMemory storage provider as I do not have the need to see historical data. There are also providers various databases including SqlServer and SQLite which can be used to persist the data.

<PackageReference Include="AspNetCore.HealthChecks.UI" Version="$(AspNetCoreHealthChecksUIVersion)" />
<PackageReference Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="$(AspNetCoreHealthChecksUIVersion)" />

As the HealthChecks nuget packages will be used across all projects I have set the version numbers centrally in Directory.Build.props.

<AspNetCoreHealthChecksUIVersion>3.1.1</AspNetCoreHealthChecksUIVersion>

The HealthChecks UI can now be added to ConfigureServices and Configure in Startup.cs.

As I want to limit the access to the UI in the same way as I did for the HealthCheck endpoints I have the service listening on multiple ports and use RequireHost when configuring the endpoints to ensure the UI is only accessible internally.

public void ConfigureServices(IServiceCollection services)
{
services
.AddHealthChecksUI()
.AddInMemoryStorage();
services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHealthChecksUI();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapHealthChecksUI(config => {
config.UIPath = "/hc-ui";
}).RequireHost($"*:{Configuration["ManagementPort"]}");
});
}
``` Finally we need to tell the UI where to read the HealthChecks from, this can either be done in a configuration file ```json
...
"https_port": 1131,
"Urls": "http://localhost:1130;https://localhost:1131;https://localhost:1132",
"ManagementPort": "1132",
"AllowedHosts": "*",
"HealthChecks-UI": {
"HealthChecks": [
{
"Name": "LoginService Check",
"Uri": "https://localhost:1116/hc"
},
{
"Name": "ResourceService Check",
"Uri": "https://localhost:5002/hc"
},
{
"Name": "NotificationService Check",
"Uri": "https://localhost:1179/hc"
}
]
}
...
``` or in code by adding settings to the `AddHealthChecksUI` method. ```csharp
services.AddHealthChecksUI(setupSettings: settings => {
settings
.DisableDatabaseMigrations()
.AddHealthCheckEndpoint(name: healthCheckName, uri: healthCheckUri)
.AddWebhookNotification(name: webhookName, uri: webhookUri, payload: webhookPayload,
restorePayload: webhookRestorePayload)
.SetEvaluationTimeInSeconds(evaluationTimeInSeconds)
.SetMinimumSecondsBetweenFailureNotifications(minimumSeconds);
}).AddInMemoryStorage();
``` You can get the full working demo from [my GitHub repo](https:/github.comMarkZitherSwaggerAndHealthCheckBlog).

Secure ASP.NET Core Health Checks to a specific port

· 2 min read
Mark Burton
Software Engineer & Technical Writer

To secure Health Checks it is possible to make them available on internal addresses only and on a different port to the publicly served pagesAPI endpoints. First we need to make the service available over 2 different ports, this can be achieved by adding a Urls value to the appsettings.config. json "Logging": \\\{ "IncludeScopes": false, "LogLevel": \{ "Default": "Debug", "System": "Information", "Microsoft": "Information" \\} }, "Urls": "http:/localhost:1114;http:/localhost:1115", "ManagementPort": "1115", "ConnectionStrings": \\{ "LoginServiceDb": "Data Source=.,11433;Initial Catalog=LoginServiceDatabase;Integrated Security=true;" \}, This can be done in several ways, and is described in more detail by Andrew Lock in his post 5 ways to set the URLs for an ASP.NET Core app. Now when you debug the service you should see in the log that it is listening on 2 ports ``` info: Microsoft.Hosting.Lifetime[0] Now listening on: http:/localhost:1114 info: Microsoft.Hosting.Lifetime[0] Now listening on: http:/localhost:1115 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.

**Special note if you are using http.sys** If you want to run this over https you will need to take care of the port reservation and certification binding. I have a explanation of that in the GitHub Repo README.
::: Now that we have the service listening on 2 addresses we can specify one of them will serve up the Health Checks by setting the `ManagementPort`. In `startup.cs` we can use the `ManagementPort` to secure the Health Check endpoint ```csharp HealthCheck middleware app.UseHealthChecks("hc", $"\\{Configuration["ManagementPort"]\}", new HealthCheckOptions() \\{ Predicate = _ => true, ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse \}); app.UseEndpoints(endpoints => \\\{ endpoints.MapControllerRoute("default", "\{controller=Home\\}\{action=Index\}\\{id?\}"); endpoints.MapHealthChecks("health").RequireHost($"*:\\{Configuration["ManagementPort"]\}"); });
``` If you debug now you will have access to the `health` endpoint only on the `ManagementPort` and not on the public facing URL. ![HealthCheck external shows 404 while internal shows overall health status](/img/health_endpoint.png) More interestingly you can also go to the `hc` endpoint, this contains more detailed information about the state of the service and therefore needs to be secured. ![HealthCheck external shows 404 while internal shows detailed health status](/img/hc_endpoint.png) Now you can safely get the status of your services reported as json, but there are 2 further aspects of ASP.NET Core Health Checks, the UI and push-based monitoring, i will cover those in parts 2 and 3.