Reputation: 3816
I've started to implement health checks in my .NET Core Web API. There are two health checks, one for checking if the SQL Server has any pending migrations and the other is checking if another API is live. Both added within ConfigureServices
in Startup
class.
In order to do the migration check, I need to access the DbContext
which has already been added to DI using AddDbContext
and to check the API, I need to get the API base url from configuration which is already in DI using services.Configure<>
. I use the following code to get access to the DbContext
.
I'm using AspNetCore.HealthChecks.Uris
package to use AddUrlGroup
health check.
var sp = services.BuildServiceProvider();
var dbContext = sp.GetService<AppDbContext>();
var apis = sp.GetService<IOptions<InternalServicesConfiguration>>().Value;
services.AddHealthChecks().AddCheck("Database", new SqlDatabaseHealthCheck(dbContext), tags: new[] { "ready" })
.AddUrlGroup(new Uri(new Uri(apis.Api1BaseUri), "/health/live"), HttpMethod.Get, "API 1", HealthStatus.UnHealthy, new []{"ready"});
But services.BuildServiceProvider()
shows the following warning:
Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'
I can get the api base urls using
_configuration.GetSection("InternalServicesConfiguration").Get(typeof(InternalServicesConfiguration));
But I can't think of an alternative way to access the DbContext
.
Any help much appreciated.
Upvotes: 1
Views: 1091
Reputation: 3473
With regard to accessing IOptions (please see updated health check). Is there another way other than getting it using _configuration.GetSection("").Get<>()
You could register those options in a following way (in ConfigureServices):
services.Configure<InternalServicesConfiguration>(Configuration.GetSection("InternalServicesConfiguration"));
And to get those options, in your class just inject IOptions<InternalServicesConfiguration> options
, where the options.Value
prop is the configuration value
Upvotes: 0
Reputation: 3473
You can register your healthcheck like this:
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("Database");
And then just inject your DbContext
into ExampleHealthCheck
class, which has to implement IHealthCheck
interface
Upvotes: 2
Reputation: 1613
There are some healthchecks you can use directly for EF in the official docs
But if you want to write any custom or more complex checks, your best bet might be to create a class that implements the IHealthCheck
interface, where you can inject anything you want.
Also from the docs about Custom health checks, an example:
public class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var healthCheckResultHealthy = true;
if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("An unhealthy result."));
}
}
which, as kebek alerady answered, you will register like
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
Upvotes: 0