Skip to content

Commit

Permalink
add raveb db health check issue JudahGabriel#89
Browse files Browse the repository at this point in the history
  • Loading branch information
kdcllc committed Feb 12, 2019
1 parent 4238231 commit 6669570
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 7 deletions.
1 change: 1 addition & 0 deletions Chavah.NetCore/Chavah.NetCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<LangVersion>Latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1591;</NoWarn>
Expand Down
67 changes: 67 additions & 0 deletions Chavah.NetCore/Common/HealthChecks/HealthCheckBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using BitShuva.Chavah.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.HealthChecks;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Microsoft.Extensions.DependencyInjection
{
public static class HealthCheckBuilderExtensions
{
/// <summary>
/// Add a healthcheck for ravendb.
/// </summary>
/// <param name="builder"></param>
/// <param name="services"></param>
/// <param name="name"></param>
/// <param name="failureStatus"></param>
/// <param name="tags"></param>
/// <returns></returns>
public static IHealthChecksBuilder AddRavenDbCheck(
this IHealthChecksBuilder builder,
IServiceCollection services,
string name = "ravendb",
HealthStatus? failureStatus = default,
IEnumerable<string> tags = default)
{
var provider = services.BuildServiceProvider();

var options = provider.GetRequiredService<IOptions<AppSettings>>().Value.DbConnection;

var hostingEnviroment = provider.GetRequiredService<IHostingEnvironment>();

builder.Add(new HealthCheckRegistration(
name,
sp => new RavenDdHealthCheck(options, hostingEnviroment),
failureStatus,
tags));

return builder;
}

internal static Task WriteResponse(
HttpContext httpContext,
HealthReport result)
{
httpContext.Response.ContentType = "application/json";

var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));

return httpContext.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
}
}
68 changes: 68 additions & 0 deletions Chavah.NetCore/Common/HealthChecks/RavenDdHealthCheck.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using BitShuva.Chavah.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Raven.Client.Documents;
using Raven.Client.ServerWide.Operations;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Extensions.HealthChecks
{
public class RavenDdHealthCheck : IHealthCheck
{
private readonly DbConnection _options;
private readonly IHostingEnvironment _hostingEnvironment;

public RavenDdHealthCheck(DbConnection options, IHostingEnvironment hostingEnvironment)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentException(nameof(hostingEnvironment));
}

public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
try
{
using (var store = new DocumentStore
{
Urls = new[] { _options.Url },
Database = _options.DatabaseName
})
{
if (!string.IsNullOrWhiteSpace(_options.CertFileName))
{
var certFilePath = Path.Combine(_hostingEnvironment.ContentRootPath, _options.CertFileName);
store.Certificate = new X509Certificate2(certFilePath, _options.CertPassword);
}

store.Initialize();

var operation = new GetDatabaseNamesOperation(start: 0, pageSize: 100);
var databaseNames = await store.Maintenance.Server.SendAsync(operation);

if (!string.IsNullOrWhiteSpace(_options.DatabaseName)
&& !databaseNames.Contains(_options.DatabaseName, StringComparer.OrdinalIgnoreCase))
{
return new HealthCheckResult(
context.Registration.FailureStatus,
$"RavenDB doesn't contains '{_options.DatabaseName}' database.");
}
else
{
return HealthCheckResult.Healthy();
}
}
}
catch (Exception ex)
{
return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
}
}
}
}
2 changes: 0 additions & 2 deletions Chavah.NetCore/Models/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ public class DbConnection
public string DatabaseName { get; set; }
public string CertFileName { get; set; }
public string CertPassword { get; set; }

public string FileName { get; set; }
}

public class Application
Expand Down
2 changes: 1 addition & 1 deletion Chavah.NetCore/Startup.RavenDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static IServiceCollection AddRavenDocStore(this IServiceCollection servic
var provider = services.BuildServiceProvider();
var host = provider.GetRequiredService<IHostingEnvironment>();

var settings = provider.GetRequiredService<IOptions<AppSettings>>().Value.DbConnection;
var settings = provider.GetRequiredService<IOptionsMonitor<AppSettings>>().CurrentValue.DbConnection;
var docStore = new DocumentStore
{
Urls = new[] { settings.Url },
Expand Down
18 changes: 16 additions & 2 deletions Chavah.NetCore/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using cloudscribe.Syndication.Models.Rss;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
Expand Down Expand Up @@ -47,6 +48,9 @@ public void ConfigureServices(IServiceCollection services)
services.AddOptions();
services.Configure<AppSettings>(Configuration);

var hcBuilder = services.AddHealthChecks();
hcBuilder.AddRavenDbCheck(services);

// Add application services.
services.AddTransient<IEmailService, SendGridEmailService>();
services.AddTransient<IPushNotificationSender, PushNotificationSender>();
Expand All @@ -67,8 +71,8 @@ public void ConfigureServices(IServiceCollection services)

// Add RavenDB and identity.
services
.AddRavenDocStore() // Create a RavenDB DocumentStore singleton.
.AddRavenDbAsyncSession() // Create a RavenDB IAsyncDocumentSession for each request.
.AddRavenDocStore() // Create a RavenDB DocumentStore singleton.
.AddRavenDbAsyncSession() // Create a RavenDB IAsyncDocumentSession for each request.
.AddRavenDbIdentity<AppUser>(c => // Use Raven for users and roles.
{
c.Password.RequireNonAlphanumeric = false;
Expand Down Expand Up @@ -114,13 +118,17 @@ public void ConfigureServices(IServiceCollection services)
new HeaderApiVersionReader("api-version", "api-v")
);
});

services.AddCustomAddSwagger();

services.AddPwnedPassword(_=> new PwnedOptions());

services.Configure<SecurityStampValidatorOptions>(options =>
{
// enables immediate logout, after updating the user's stat.
options.ValidationInterval = TimeSpan.Zero;
});

services.AddAuthentication(options=>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
Expand All @@ -133,6 +141,7 @@ public void ConfigureServices(IServiceCollection services)
return Task.CompletedTask;
};
});

services.AddHttpsRedirection(options => options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect );
services.AddAuthorization(options => options.AddPolicy(Policies.Administrator, policy => policy.RequireRole(AppUser.AdminRole)));

Expand Down Expand Up @@ -184,6 +193,11 @@ public void ConfigureServices(IServiceCollection services)
});
}

app.UseHealthChecks("/healthy", new HealthCheckOptions
{
ResponseWriter = HealthCheckBuilderExtensions.WriteResponse
});

app.UseHttpsRedirection();
app.UseAuthentication();

Expand Down
3 changes: 1 addition & 2 deletions Chavah.NetCore/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
"Url": "http://chavah.db:8080",
"DatabaseName": "ChavahDb",
"CertFileName": "",
"CertPassword": "",
"FileName": "ChavahDb.ravendbdump"
"CertPassword": ""
},

"Application": {
Expand Down

0 comments on commit 6669570

Please sign in to comment.