Add Database health sample

This commit is contained in:
Ryan Nowak 2018-08-03 14:47:20 -07:00
parent ebafbcdae3
commit d1cba1f55b
7 changed files with 150 additions and 0 deletions

View File

@ -17,6 +17,7 @@
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
@ -37,6 +38,7 @@
<MoqPackageVersion>4.7.49</MoqPackageVersion>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
<SystemDataSqlClientPackageVersion>4.6.0-preview1-26725-04</SystemDataSqlClientPackageVersion>
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.5.0</SystemDiagnosticsDiagnosticSourcePackageVersion>
<SystemReflectionMetadataPackageVersion>1.6.0</SystemReflectionMetadataPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion>

View File

@ -0,0 +1,47 @@

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace HealthChecksSample
{
// Pass in `--scenario db` at the command line to run this sample.
public class DBHealthStartup
{
public DBHealthStartup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Registers required services for health checks
services.AddHealthChecks()
// Add a health check for a SQL database
.AddCheck(new SqlConnectionHealthCheck("MyDatabase", Configuration["ConnectionStrings:DefaultConnection"]));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// This will register the health checks middleware at the URL /health.
//
// By default health checks will return a 200 with 'Healthy' when the database is responsive
// - We've registered a SqlConnectionHealthCheck
// - The default response writer writes the HealthCheckStatus as text/plain content
//
// This is the simplest way to use health checks, it is suitable for systems
// that want to check for 'liveness' of an application with a database.
app.UseHealthChecks("/health");
app.Run(async (context) =>
{
await context.Response.WriteAsync("Go to /health to see the health status");
});
}
}
}

View File

@ -0,0 +1,64 @@
// 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.Common;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace HealthChecksSample
{
public abstract class DbConnectionHealthCheck : IHealthCheck
{
protected DbConnectionHealthCheck(string name, string connectionString)
: this(name, connectionString, testQuery: null)
{
}
protected DbConnectionHealthCheck(string name, string connectionString, string testQuery)
{
Name = name ?? throw new System.ArgumentNullException(nameof(name));
ConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
TestQuery = testQuery;
}
public string Name { get; }
protected string ConnectionString { get; }
// This sample supports specifying a query to run as a boolean test of whether the database
// is responding. It is important to choose a query that will return quickly or you risk
// overloading the database.
//
// In most cases this is not necessary, but if you find it necessary, choose a simple query such as 'SELECT 1'.
protected string TestQuery { get; }
protected abstract DbConnection CreateConnection(string connectionString);
public async Task<HealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (var connection = CreateConnection(ConnectionString))
{
try
{
await connection.OpenAsync(cancellationToken);
if (TestQuery != null)
{
var command = connection.CreateCommand();
command.CommandText = TestQuery;
await command.ExecuteNonQueryAsync(cancellationToken);
}
}
catch (DbException ex)
{
return HealthCheckResult.Unhealthy(ex);
}
}
return HealthCheckResult.Healthy();
}
}
}

View File

@ -8,10 +8,12 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(MicrosoftExtensionsConfigurationCommandLinePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsConfigurationJsonPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
<PackageReference Include="System.Data.SqlClient" Version="$(SystemDataSqlClientPackageVersion)" />
</ItemGroup>
<ItemGroup>

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
@ -19,6 +20,7 @@ namespace HealthChecksSample
{ "writer", typeof(CustomWriterStartup) },
{ "liveness", typeof(LivenessProbeStartup) },
{ "port", typeof(ManagementPortStartup) },
{ "db", typeof(DBHealthStartup) },
};
}
@ -30,6 +32,8 @@ namespace HealthChecksSample
public static IWebHost BuildWebHost(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.AddCommandLine(args)
.Build();

View File

@ -0,0 +1,26 @@
using System.Data.Common;
using System.Data.SqlClient;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace HealthChecksSample
{
public class SqlConnectionHealthCheck : DbConnectionHealthCheck
{
private static readonly string DefaultTestQuery = "Select 1";
public SqlConnectionHealthCheck(string name, string connectionString)
: this(name, connectionString, testQuery: DefaultTestQuery)
{
}
public SqlConnectionHealthCheck(string name, string connectionString, string testQuery)
: base(name, connectionString, testQuery ?? DefaultTestQuery)
{
}
protected override DbConnection CreateConnection(string connectionString)
{
return new SqlConnection(connectionString);
}
}
}

View File

@ -0,0 +1,5 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
}
}